Намерете края на потока за 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 в wikipedia). Благодаря за помощта atzz и на всички! - person user435219; 30.08.2010
comment
Предпочитайте преобразуването на потока в булево пред .eof или .bad. - person Mooing Duck; 02.05.2012

Защо std::cin.eof() не работи? cin ще сигнализира EOF, когато stdin се затвори, което ще се случи, когато потребителят го сигнализира с 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 (не е и false, ако има беше предишна грешка при четене от потока).

Тъй като повечето IO операции на потоци връщат потока (така че те могат да бъдат верижни). Можете да извършите вашата операция за четене и да използвате резултата в теста (както по-горе).

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

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