2008-08-22 7 views
104

다음 C++ 코드가 EOF를 돌 때까지 (한 줄에 하나 개의 번호를 가지고있는) 텍스트 파일에서 정수를 읽어 ifstream 객체를 사용을 반복합니다. 마지막 행의 정수를 두 번 읽는 이유는 무엇입니까? 이 문제를 해결하는 방법?은 마지막 줄

코드 :

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

int main() 
{ 
    ifstream iFile("input.txt"); // input.txt has integers, one per line 

    while (!iFile.eof()) 
    { 
     int x; 
     iFile >> x; 
     cerr << x << endl; 
    } 

    return 0; 
} 

input.txt를 :

10 
20 
30 

출력 :

10 
20 
30 
30 

참고 : 코드 스 니펫을 작게 유지하기 위해 모든 오류 검사 코드를 건너 뛰었습니다. 위의 동작은 Windows (Visual C++), cygwin (gcc) 및 Linux (gcc)에서 볼 수 있습니다.

답변

109

이벤트 체인을 따라 가십시오. 마지막 두 번째 반복에서

  • 잡아 10
  • 잡아 20
  • 잡아 30
  • 잡아 EOF

봐. 당신은 30을 움켜 잡고 EOF를 확인하기 위해 계속했습니다. EOF 표시가 아직 읽혀지지 않았기 때문에 EOF에 도달하지 못했습니다 ("이진법 적으로"말하기, 개념적 위치는 30 행 직후 임). 따라서 다음 반복을 수행합니다. x는 이전 반복에서 여전히 30입니다. 이제 스트림에서 읽으면 EOF를 얻습니다. x는 30으로 유지되고 ios :: eofbit가 발생합니다. stderr x에 출력합니다 (이전 반복과 마찬가지로 30입니다). 다음으로 루프 상태에서 EOF를 확인하고 이번에는 루프를 벗어났습니다. 코드에 또 다른 버그가있다, 그런데

while (true) { 
    int x; 
    iFile >> x; 
    if(iFile.eof()) break; 
    cerr << x << endl; 
} 

:

이보십시오. 빈 파일에서 실행하려고 시도한 적이 있습니까? 당신이 얻는 행동은 똑같은 이유 때문입니다.

ifstream iFile("input.txt");  // input.txt has integers, one per line 
int x; 

while (iFile >> x) 
{ 
    cerr << x << endl; 
} 

얼마나 안전하고 확실하지 ...

+40

'while (iFile >> x)'을 사용하십시오. 정수를 읽고 스트림을 반환합니다. 스트림이 bool 값으로 사용되면 스트림이 유효한지 확인합니다. 유효 함은 eof()와 bad()가 모두 거짓임을 의미합니다. http://stackoverflow.com/questions/21647/c-reading-from-text-file-until-eof-repeats-last-line#21666 –

+3

위와 동일한 정신 : 'while (true)'대신, 'while (file.good())'를 쓰는 것이 더 좋습니다. – PHF

+1

오류 또는 파일 끝까지 파일을 읽는 방법을 잘 모르는 경우이 기사를 읽으십시오 (아주 좋은 설명) https://gehrcke.de/2011/06/read-files-in-c-using-if-bad-failbit-eofbit-and-perror/ – stviper

29

나는 지금, 당신은 동안 블록의 내부에 추가 할 수있는 체크 아웃 단풍이 예제를 좋아 여기에 : 원래 코드의 많은 수정을하지 않고

#include <iterator> 
#include <algorithm> 

// ... 

    copy(istream_iterator<int>(iFile), istream_iterator<int>(), 
     ostream_iterator<int>(cerr, "\n")); 
+0

0이 x == 0과 같은 유효한 값이면 어떻게 될까요? – harryngh

+4

@harryngh 올바르게 이해하면,'iFile >> x'는'x'가 아니라 스트림 자체를 반환합니다. 스트림은 암시 적으로 EOF를 테스트하는 'bool'로 변환됩니다. – wchargin

5

, 그것은 될 수 :

while (!iFile.eof()) 
{ 
    int x; 
    iFile >> x; 
    if (!iFile.eof()) break; 
    cerr << x << endl; 
} 

하지만 일반적으로 위의 두 가지 다른 솔루션을 선호합니다.

2
int x; 
ifile >> x 

while (!iFile.eof()) 
{ 
    cerr << x << endl;   
    iFile >> x;  
} 
5

EOF 패턴은 EOF 검사 프로세스를 '부트 스트랩'하기 위해 먼저 읽어야합니다. 빈 파일은 처음 읽을 때까지 처음에는 EOF가 설정되지 않는다고 가정합니다. 프라임 읽기는이 인스턴스에서 EOF를 catch하고 루프를 완전히 건너 뜁니다.

여기서 기억해야 할 것은 파일의 사용 가능한 데이터를 처음 읽으려고 시도 할 때까지 EOF를 얻지 못한다는 것입니다. 정확한 양의 데이터를 읽는 것은 EOF를 표시하지 않습니다.

EOF가 입력 값이 루프로 들어가는 동안 x 값으로 설정되는 것을 막았 기 때문에 파일이 비어 있다면 지정된 코드가 인쇄되었음을 지적해야합니다.

  • 0

그래서 주요 읽기를 추가하고 이동 루프의 끝까지 읽어

int x; 

iFile >> x; // prime read here 
while (!iFile.eof()) { 
    cerr << x << endl; 
    iFile >> x; 
} 
2

마지막 줄의 끝에 새 라인 문자를 가지고있는 >> 연산자로 읽지 않으며 파일의 끝이 아닙니다. 실험을하고 새 줄 (파일의 마지막 문자)을 삭제하십시오. 중복되지 않습니다. 유연한 코드를 사용하고 원치 않는 결과를 피하려면 다른 사용자가 제공 한 솔루션을 적용하기 만하면됩니다.

관련 문제