Найти конец потока для cin и ifstream?

Я просматриваю учебник по C++, который у меня есть для освежения знаний по программированию на C++. Одна из практических задач (не вдаваясь в подробности) требует, чтобы я определил функцию, которая может быть передана ifstream или cin (например, istream) в качестве аргумента. Оттуда я должен прочитать поток. Проблема в том, что я не могу придумать, как заставить эту функцию one использовать cin и ifstream для эффективного поиска конца потока. А именно,

while(input_stream.peek() != EOF)

не будет работать для cin. Я мог бы переработать функцию для поиска определенной фразы (например, «#Конец потока#» или что-то в этом роде), но я думаю, что это плохая идея, если в файловом потоке, который я передаю, есть именно эта фраза.

Я думал использовать перегрузку функций, но до сих пор в книге упоминалось, когда мне нужно это сделать. Возможно, я трачу слишком много усилий на эту единственную практическую задачу, но мне нравится творческий процесс, и мне любопытно, есть ли такой способ сделать это без перегрузки.


person user435219    schedule 30.08.2010    source источник
comment
Проверьте этот вопрос: stackoverflow.com/questions/3197025/   -  person Archie    schedule 30.08.2010


Ответы (3)


eof() работает для cin. Вы делаете что-то не так; пожалуйста, опубликуйте свой код. Одним из распространенных камней преткновения является то, что флаг eof устанавливается после того, как вы пытаетесь прочитать за концом потока.

Вот демонстрация:

#include <iostream>
#include <string>

int main( int, char*[] )
{
    std::string s;
    for ( unsigned n = 0; n < 5; ++n )
    {
        bool before = std::cin.eof();
        std::cin >> s;
        bool after = std::cin.eof();
        std::cout << int(before) << " " << int(after) << "  " << s << std::endl;
    }

    return 0;
}

и его вывод:

D:>t
aaaaa
0 0  aaaaa
bbbbb
0 0  bbbbb
^Z
0 1  bbbbb
1 1  bbbbb
1 1  bbbbb

(EOF можно сгенерировать с помощью Ctrl-Z в Windows и Ctrl-D во многих других ОС)

person atzz    schedule 30.08.2010
comment
Извините за путаницу, сначала у меня было while(!input_stream.eof()), но потом я понял, что вместо этого написал while(input_stream.peek != EOF). Несмотря на это, оба метода работают с control+z (как ни странно, я только что читал о символе eof в Википедии). Спасибо за помощь atzz и всем! - person user435219; 30.08.2010
comment
Предпочтительно преобразовывать поток в логическое значение вместо .eof или .bad. - person Mooing Duck; 02.05.2012

Почему std::cin.eof() не работает? cin будет сигнализировать об окончании EOF при закрытии стандартного ввода, что произойдет, когда пользователь подаст сигнал с помощью Ctrl+d (*nix) или Ctrl+z (Windows) или (в случай конвейерного входного потока), когда конвейерный файл заканчивается

person Michael Mrozek    schedule 30.08.2010
comment
В Windows это Ctrl+Z, Ctrl+D для систем на базе UNIX. - person Archie; 30.08.2010
comment
Ах, это действительно работает (в любом случае, Ctrl + Z для Windows). Извините, если есть небольшая путаница, поскольку я изначально использовал while(!input_stream.eof()) в предыдущем посте и отредактировал его на while(input_stream.peek() != EOF). Во всяком случае, одна проблема, которую я беспокою по поводу использования while(!input_stream.eof()), заключается в том, что когда функция считывает символ EOF, для input_stream устанавливается бит ошибки. Это должно произойти? - person user435219; 30.08.2010
comment
@ user435219: да, потому что ему не удалось прочитать данные, потому что он достиг EOF. EOF почти всегда также вызывает fail - person Mooing Duck; 02.05.2012

Если вы используете поток в логическом контексте, то он преобразует себя в значение, эквивалентное true, если он не достиг EOF, и false, если была предпринята попытка чтения после EOF (это также не ложно, если есть была предыдущая ошибка чтения из потока).

Поскольку большинство операций ввода-вывода с потоками возвращают поток (поэтому их можно объединить в цепочку). Вы можете выполнить операцию чтения и использовать результат в тесте (как указано выше).

Итак, программа для чтения потока чисел из потока:

int main()
{
   int x;

   // Here we try and read a number from the stream.
   // If this fails (because of EOF or other error) an internal flag is set.
   // The stream is returned as the result of operator>>
   // So the stream is then being used in the boolean context of the while()
   // So it will be converted to true if operator>>  worked correctly.
   //                         or false if operator>> failed because of EOF
   while(std::cin >> x)
   {
       // The loop is only entered if operator>> worked correctly.
       std::cout << "Value: " << x << "\n";
   }

   // Exit when EOF (or other error).
}
person Martin York    schedule 30.08.2010