2009-10-06 4 views
1

Почему я получаю дополнительную итерацию (дополнительная строка), когда этот код завершается? Должна ли быть дополнительная новая линия в EOF? Я бы предпочел не добавлять лишние/специальные символы, чтобы отметить EOF.Файловый эхо-цикл с дополнительной финальной итерацией

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 

int main(){ 
    ifstream infile("dictionary.txt"); // one word per line 
    string text; 
    while(infile){ 
     infile >> text; 
     cout << text << endl; 
    } 
    infile.close(); 
    return 0; 
} 
+1

Можете ли вы подтвердить, что «dictionary.txt» не имеет новую строку в конце ? Потому что ваш код, кажется, прямое чтение, выписывание. – Nasir

+1

@ nr81: Это стандартный анти-шаблон для чтения файла. Очистка eof не проверяется после чтения (с помощью оператора >>), тогда последняя строка будет напечатана дважды. См. Ответы ниже для правильного шаблона для чтения файла. –

ответ

6

попробовать

while(infile>>text) cout << text << endl; 

вместо этого.

+0

В то время как состояние действительно поднимает мои судороги. Мне не нравятся побочные эффекты - за исключением, конечно, тех особых случаев, когда я это делаю. Во всяком случае, я сопротивлялся нисходящей линии по разным причинам и, наконец, решил подняться - не в последнюю очередь потому, что это кратким, простым, надежным и обычным стандартным библиотечным идиомом, который каждый должен понимать. Даже так ... подумайте, что зарычал;;) – Steve314

+0

Спасибо, Steve314, я не против того, чтобы зарычал. ;-) И, честно говоря, когда побочный эффект работает, мне нравятся побочные эффекты. –

3

С вашим условием while вы проверяете, находится ли поток в хорошем состоянии. Затем вы читаете из потока, который может или не может быть успешным. Затем вы выводите значение текста. То, что вы должны сделать, это:

while(infile >> text){ 
    cout << text << endl; 
} 
3

В конце файла, infile еще может вычисляться true, но после удаления слова с infile >> text терпит неудачу. Даже если это не удается, вы все равно распечатываете строку. Лучший способ сделать это было бы позволить проверку контура, а для успешного извлечения:

string text; 
ifstream infile("dictionary.txt"); // one word per line 
while (infile >> text) { 
    cout << text << endl; 
} 
infile.close(); 
6

Входной поток не не выявлять конец файла до после вы пытаетесь прочитать мимо него. Когда вы читаете последнее слово в файле, входной поток все еще действителен; в следующем цикле infile >> текст пытается прочитать прошлый EOF и не удается, но следующая строка все равно выполняется.

Петля должна выглядеть следующим образом:

while (infile >> text) 
    cout << text << endl; 

Таким образом EOF будет обнаружен, прежде чем он пытается записать на выход.

+1

Вы включили волшебные слова об EOF. +1 –

1

Вы уже получили ряд поправок, но, возможно, немного отличается один стоит учесть:

#include <iterator> 
#include <iostream> 
#include <string> 
#include <fstream> 

using namespace std; // not really a good idea, but harmless enough for now. 

int main() { 
    ifstream infile("dictionary.txt"); 
    copy(istream_iterator<string>(infile), istream_iterator<string>(), 
     ostream_iterator<string>(cout, "\n")); 
    return 0; 
} 
+0

+1 ради разнообразия. Я не думаю, что это особенно интересно в этом случае, потому что я сомневаюсь, что идея состоит в том, чтобы скопировать слова или протолкнуть их в другой итератор. –

 Смежные вопросы

  • Нет связанных вопросов^_^