본문 바로가기

StackOverflow

[C++] 왜 iostream::eof를 반복문(루프)의 조건문에 쓰면 안되죠?

http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong


Q: 왜 iostream::eof를 루프의 조건문에 쓰면 안되죠? 

제가 방금 이 링크의 댓글을 봤는데요, 루프의 조건문에 iostream::eof를 쓰면 "완전히 확실하게 틀리다"라고 하네요. 저는 일반적으로 while(cin>>n) 이런 식으로 코딩을 하는데, 아마 묵시적으로 EOF를 체크하는 구문일겁니다. 그런데 왜 iostream::eof 이렇게 명시적으로 EOF를 체크하는 구문을 호출하면 안되는거죠?

C 언어에서 scanf("...",...)!=EOF를 쓰는 것과는 어떻게 다르죠?


(질문자: MAK)


A: 왜냐하면,iostream::eof스트림을 다 읽은 다음에 설정되기 때문입니다. 이것은 절대로 다음에 읽을 스트림이 해당 스트림의 마지막인지 여부를 나타내는 것이 아닙니다.

아래와 같은 상황을 생각해 보세요.

while(!inStream.eof()){
  int data;
  // 아직 스트림이 끝나지 않았고, 이제 읽기 시작합니다.
  inStream >> data;
  // 이런 빌어먹을, 이제 end를 읽었고, (fail bit와 마찬가지로) *여기에서만* EOF 비트가 설정될 것입니다.
  // (이젠 더 이상 초기화 되어있지 않은) 데이터로 작업을 합니다.
}

이 경우에는 어떨까요.

int data;
while(inStream >> data){
  // 이 라인이 수행된다면, 읽기가 성공했다고 확신할 수 있습니다.
  // 만약 그렇지 않다면, 연산자 >> 을 통해 반환된 스트림의 값이 false로 변환 될 것입니다.
  // 그러면 반복문의 조건에 맞지 않아 여기로 들어오지 않을 것이고
  // 우리는 정상적으로 초기화 된 데이터로 작업할 수 있을 것입니다. (아마도요)
}


그리고 두 번째 질문의 경우

if(scanf("...",...)!=EOF)

는 아래와 같은 코드입니다. (역주: 스트림 데이터를 읽은 결과를 이용하기 때문에, EOF가 설정된 이후 EOF를 체크합니다)

if(!(inStream >> data).eof())

아래 코드와는 다른 코드입니다.

if(!inStream.eof())
    inFile >> data


(답변자: Xeo)


-

I just found a comment in this answer saying that using iostream::eof in a loop condition is "almost certainly wrong". I generally use something like while(cin>>n) - which I guess implicitly checks for EOF, why is checking for eof explicitly using iostream::eof wrong?

How is it different from using scanf("...",...)!=EOF in C (which I often use with no problems)?

shareeditflag


-

225down voteaccepted

Because iostream::eof will only be set after reading the end of the stream. It does not indicate, that the next read will be the end of the stream.
Consider this (and assume then next read will be at the end of the stream):

while(!inStream.eof()){
  int data;
  // yay, not end of stream yet, now read ...
  inStream >> data;
  // oh crap, now we read the end and *only* now the eof bit will be set (as well as the fail bit)
  // do stuff with (now uninitialized) data
}

Against this:

int data;
while(inStream >> data){
  // when we land here, we can be sure that the read was successful.
  // if it wasn't, the returned stream from operator>> would be converted to false
  // and the loop wouldn't even be entered
  // do stuff with correctly initialized data (hopefully)
}

And on your second question: Because

if(scanf("...",...)!=EOF)

is the same as

if(!(inStream >> data).eof())

and not the same as

if(!inStream.eof())
    inFile >> data
shareeditflag