Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 루프 조건에서 iostream::eof()를 쓰면 안 되는 이유

C++에서 파일을 읽을 때 루프 조건으로 iostream::eof()를 사용하는 방식은 잘못된 관행으로 간주됩니다. 그 이유는 간단합니다. eof()를 호출하는 시점에는 아직 파일 끝(EOF)에 도달하지 않았을 수 있으며, 따라서 EOF에 도달하지 않았다는 사실이 곧 '다음 읽기가 반드시 성공한다'는 의미가 되지 않기 때문입니다.

eof()는 미래를 예측하는 함수가 아니라, 이전 입출력 연산에서 파일 끝에 도달했는지를 알려주는 상태 플래그일 뿐입니다. 그럼에도 while(!stream.eof()) 형태의 루프가 자주 사용되는데, 이는 마지막 데이터를 읽은 후 한 번 더 루프가 실행되어 실패한 읽기 결과까지 처리하게 만드는 버그의 주요 원인이 됩니다.

잘못된 예: eof()를 루프 조건으로 사용

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

int main() {
   ifstream myFile("myfile.txt");
   string x;

   while(!myFile.eof()) {
      myFile >> x;
      // 읽기가 실제로 성공했는지 다시 확인해야 함
      if(myFile) {
         // x를 가지고 원하는 작업 수행
      }
   }
}

위 코드의 문제는 !myFile.eof()가 참인 시점에 myFile >> x가 실패할 수 있다는 점입니다. 파일 끝에 공백이나 줄바꿈 문자가 남아 있으면, 마지막 단어를 모두 읽은 뒤에도 EOF 플래그가 설정되지 않아 루프가 한 번 더 돌게 되고, 실패한 읽기로 인해 x가 유효하지 않은 값을 가질 수 있습니다. 결국 루프 내부에서 읽기 성공 여부를 중복으로 검사해야 하는 번거로움이 생깁니다.

올바른 예: 스트림 자체를 루프 조건으로 사용

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

int main() {
   ifstream myFile("myfile.txt");
   string x;

   while(myFile >> x) {
      // x를 가지고 원하는 작업 수행
      // 별도의 검사가 필요 없음!
   }
}

반면 위 코드처럼 추출 연산자(>>)의 반환값인 스트림 객체를 조건식에 직접 사용하면 훨씬 깔끔합니다. 스트림은 읽기에 실패하면 자동으로 실패 상태가 되어 false로 평가되므로, 루프가 실패한 읽기를 처리하지 않고 즉시 종료됩니다. 추가 검사 없이도 안전하고 관용적인(idiomatic) C++ 코드가 완성됩니다.

정리하면, eof()는 과거의 상태만 알려줄 뿐 다음 읽기의 성공 여부를 보장하지 못하기 때문에 루프 조건으로 부적합하며, 대신 스트림 자체를 조건으로 사용하는 것이 올바른 방법입니다.