결론 : 공백을 올바르게 처리하면 다음을 eof
사용 하는 방법을 알 수 있습니다 ( fail()
오류 검사 보다 더 안정적 임 ).
while( !(in>>std::ws).eof() ) {
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
( 답변을 강조해 줄 것을 제안 해준 Tony D에게 감사합니다. 이것이 더 강력한 이유에 대한 예는 아래의 주석을 참조하십시오. )
사용에 대한 주요 주장 eof()
은 공백의 역할에 대한 중요한 미묘함이 누락 된 것 같습니다. 내 제안은 eof()
명시 적으로 검사 하는 것이 " 항상 잘못 " 일뿐 만 아니라 이것과 비슷한 SO 스레드에서 가장 중요한 의견 인 것 같습니다. 그러나 공백을 올바르게 처리하면 더 깨끗하고 신뢰할 수 있습니다. 오류 처리이며 항상 올바른 솔루션입니다 (반드시 가장 열악한 것은 아니지만).
"적절한"종료 및 읽기 순서로 제안되는 내용을 요약하면 다음과 같습니다.
int data;
while(in >> data) { /* ... */ }
// which is equivalent to
while( !(in >> data).fail() ) { /* ... */ }
eof 이후의 읽기 시도로 인한 실패는 종료 조건으로 간주됩니다. 이는 성공적인 스트림과 eof 이외의 이유로 실제로 실패한 스트림을 쉽게 구별 할 수있는 방법이 없음을 의미합니다. 다음 스트림을 취하십시오.
1 2 3 4 5<eof>
1 2 a 3 4 5<eof>
a<eof>
while(in>>data)
세 입력 모두에 대해 세트 failbit
로 종료됩니다 . 첫 번째와 세 번째 에도 설정됩니다. 따라서 루프를 지나면 적절한 입력 (1)과 부적절한 입력 (2 및 3)을 구별하기 위해 매우 추한 추가 논리가 필요합니다.eofbit
반면 다음을 수행하십시오.
while( !in.eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
여기에서 in.fail()
읽을 것이있는 한 올바른 것이 맞는지 확인합니다. 목적은 단순한 while 루프 터미네이터가 아닙니다.
지금까지는 좋지만 스트림에 후행 공간이 있으면 어떻게 eof()
되나요?
우리는 오류 처리를 포기할 필요가 없습니다. 그냥 공백을 먹으십시오.
while( !in.eof() )
{
int data;
in >> data >> ws; // eat whitespace with std::ws
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
std::ws
상기 설정 상태 공간 스트림 후행 잠재적 (0 개 이상) 스킵 eofbit
하고, 하지를failbit
. 따라서 in.fail()
읽을 데이터가 하나 이상있는 한 예상대로 작동합니다. 모두 공백 스트림도 허용 가능한 경우 올바른 형식은 다음과 같습니다.
while( !(in>>ws).eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
/* this will never fire if the eof is reached cleanly */
// now use data
}
요약 : 올바르게 구성된 while(!eof)
것은 가능하고 잘못되지 않았을뿐 아니라 데이터를 범위 내에서 현지화 할 수있게 해주 며 평소와 같이 비즈니스에서 오류 확인을 명확하게 분리 할 수 있습니다. 말하자면 while(!fail)
, 더 일반적이고 간결한 관용구이며, 간단한 (읽기 유형별 단일 데이터) 시나리오에서 선호 될 수 있습니다.
scanf(...) != EOF
scanf
구문 분석 및 할당 된 필드 수를 반환 하므로 C에서도 작동하지 않습니다 . 정확한 조건은scanf(...) < n
어디n
형식 문자열 필드의 수입니다.