С++ - почему cin.eof() дважды читает последний символ?

Возможный дубликат:
Почему считается ли iostream::eof внутри условия цикла неправильным?


У меня очень простой вопрос...

#include<iostream>
using namespace std;
int main()
{
    char x;
    while(!cin.eof())
    {
        cin>>x;
        cout<<"char: "<< x << endl;
    }
    return 0;
}


Почему, когда я пытаюсь запустить этот код в Linux:
./file_name ‹ test_file.txt
Результат:
char: a
char: b
char: c
char: d
char: d
когда только test_file.txt:
abcd


person rAge    schedule 12.11.2012    source источник
comment
comment
Потому что всегда неправильно, неправильно, неправильно вообще использовать eof(). К настоящему времени существуют тысячи дубликатов этого вопроса, и если вопрос не является дубликатом, он все еще содержит ту же ошибку... ворчать ворчать   -  person Kerrek SB    schedule 12.11.2012


Ответы (3)


Конец файла определяется сбоем операции ввода.

So, in

    cin>>x;
    cout<<"char: "<< x << endl;

оператор вывода выполняется даже в случае сбоя операции ввода.

И когда он терпит неудачу, он не обновляет x.

Вместо тестирования .eof() проверьте .fail().

Вы можете сделать это, используя объект потока непосредственно в качестве условия, например.

#include<iostream>
using namespace std;
int main()
{
    char x;
    while( cin >> x )
    {
        cout<<"char: "<< x << endl;
    }
}

Здесь выражение cin >> x выполняет операцию ввода, которая может обновить x, и в качестве результата выражения возвращает ссылку на поток, то есть на cin. Таким образом, cin используется непосредственно как условие. Это вызывает преобразование в логическое значение, которое определено таким образом, что само по себе эквивалентно !cin.fail() (т. е. выражение cin >> x в качестве условия эквивалентно написанию !(cin >> x).fail() или, как выражение с запятой, (cin >> x, !cin.fail())).

person Cheers and hth. - Alf    schedule 12.11.2012

Вы используете немного неправильный шаблон для чтения из файла. Правильная форма

while(cin >> x) {
    cout<<"char: "<< x << endl;
}

Имейте в виду, что eof сообщает вам, если вы попытались прочитать после конца ввода; он не сообщает вам, собираетесь ли вы это сделать. Ваш исходный код читает d в первый раз, видит, что он не пытался прочитать конец, а затем пытается прочитать еще раз. Это чтение завершается ошибкой, но теперь вы находитесь внутри цикла, а x имеет значение d из предыдущей итерации, поэтому оно печатается еще раз.

Приведенный выше код проверяет состояние потока (которое, кстати, будет обнаруживать не только конец файла, но и ошибки) после попытки чтения в x; поэтому цикл вообще не будет выполняться после первого неудачного чтения.

person Jon    schedule 12.11.2012

вы должны использовать цикл for с размером файла, чтобы избежать нулевого символа

person user1816090    schedule 12.11.2012