Ваше условие в цикле while неверно. ios::eof()
не предсказывает; он будет установлен только после того, как поток попытается (внутренне) прочитать за пределами конца файла. Вы должны проверять после каждого ввода
.
Классический способ обработки вашего случая состоял бы в том, чтобы определить функцию >>
для GTable
в соответствии с строками:
std::istream&
operator>>( std::istream& source, GTable& dest )
{
std::string line;
while ( std::getline( source, line ) && line.empty() ) {
}
if ( source ) {
std::istringstream tmp( line );
std::string name;
int count;
if ( !(tmp >> name >> count) ) {
source.setstate( std::ios::failbit );
} else {
std::vector< char > adjactentOnes;
char ch;
while ( tmp >> ch ) {
adjactentOnes.push_back( ch );
}
if ( !tmp.eof() || adjactentOnes.size() != count ) {
source.setstate( std::ios::failbit );
} else {
dest.Name = name;
dest.Out = count;
for ( int i = 0; i < count; ++ i ) {
dest.AdjacentOnes.addFront( adjactentOnes[ i ] );
}
}
}
}
return source;
}
(Это было написано довольно поспешно. В реальном коде я бы почти наверняка выделил внутренний цикл в отдельную функцию.)
Обратите внимание, что:
Читаем построчно, чтобы проверить формат (и разрешить повторную синхронизацию в случае ошибки).
Ставим failbit
в исходном потоке на случай ошибки ввода.
Мы пропускаем пустые строки (поскольку ваш ввод явно их содержит).
Мы не изменяем целевой элемент, пока не убедимся, что ввод правильный.
У нас есть это, легко перебрать все элементы:
int slot = 0;
while ( slot < GTable.size() && fin >> GTable[ slot ] ) {
++ slot;
}
if ( slot != GTable.size )
// ... error ...
РЕДАКТИРОВАТЬ:
Я укажу на это прямо, потому что другие ответившие люди, кажется, пропустили это: абсолютно необходимо убедиться, что у вас есть место для чтения, перед попыткой чтения.
РЕДАКТИРОВАТЬ 2:
Учитывая количество неверных ответов на этот вопрос, я хотел бы подчеркнуть:
Любое использование fin.eof()
до того, как известно, что ввод не пройден, является неправильным.
Любое использование fin.good()
, точка, неправильно.
Любое использование одного из значений, считанных до проверки успешного ввода, является неправильным. (Это не предотвращает такие вещи, как fin >> a >>
b
, если ни a
, ни b
не используются до проверки успеха.)
Любая попытка прочитать Gtable[slot]
без проверки того, что slot
находится в границах, неверна.
Что касается eof()
и good()
:
Базовый класс istream
и ostream
определяет три бита ошибки: failbit
, badbit
и eofbit
. Важно понимать, когда они установлены: badbit
устанавливается в случае неисправимой аппаратной ошибки (фактически, практически никогда, так как большинство реализаций не могут или не обнаруживают такие ошибки); а failbit
устанавливается в любом другом случае сбоя ввода, будь то отсутствие доступных данных (конец файла), или ошибка формата ("abc"
при вводе int и т.п.). eofbit
устанавливается в любое время, когда streambuf
возвращает EOF
, независимо от того, приводит ли это к сбою ввода или нет! Таким образом, если вы читаете int
, а поток содержит "123"
без завершающих пробелов или новой строки, будет установлено eofbit
(поскольку поток должен читать вперед, чтобы знать, где заканчивается int
); если поток содержит "123\n"
, eofbit
не будет установлен. Однако в обоих случаях ввод выполняется успешно, и failbit
не будет установлено.
Для чтения этих битов есть следующие функции (в виде кода, так как иначе я не знаю, как получить таблицу):
eof(): returns eofbit
bad(): returns badbit
fail(): returns failbit || badbit
good(): returns !failbit && !badbit && !eofbit
operator!(): returns fail()
operator void*(): returns fail() ? NULL : this
(typically---all that's guaranteed is that !fail() returns non-null.)
Учитывая это: первая проверка всегда должна быть fail()
или одной из operator
(которые основаны на fail
). Как только fail()
возвращает значение true, мы можем использовать другие функции, чтобы определить, почему:
if ( fin.bad() ) {
// Serious problem, disk read error or such.
} else if ( fin.eof() ) {
// End of file: there was no data there to read.
} else {
// Formatting error: something like "abc" for an int
}
Практически говоря, любое другое использование является ошибкой (и любое использование good()
является ошибкой, не спрашивайте меня, почему эта функция существует).
person
James Kanze
schedule
23.11.2011
eof()
илиgood()
устанавливается только после сбоя чтения, и что обычно вы должны проверять, успешно ли прочитано чтение, и после что спросить причину черезeof()
? - person PlasmaHH   schedule 23.11.2011eof()
илиgood()
до или после последней ошибки чтения. Еслиeof()
равно true, следующее чтение завершится ошибкой, но не сообщается, было ли предыдущее чтение успешным или неудачным. И еслиeof()
ложно, предыдущее чтение было успешным, но следующее чтение может быть успешным или неудачным.good()
страдает от той же проблемы, потому что включает в себяeofbit
. - person James Kanze   schedule 23.11.2011