У меня есть задание по программированию для курса C ++, включающего потоки, и я пытаюсь лучше понять, почему некоторые функции работают так, как они работают.
Я читаю ввод из istringstream с пробелами после текста. Почему последнее слово повторяется в выводе?
istringstream is;
string inputstring = "The cliched statement regarding the big brown dog and foobar or something ";
string outputstring;
is.str(inputstring);
while (is.good())
{
is >> outputstring;
cout << outputstring << endl;
}
Итак, вместо того, чтобы зацикливаться на хорошем флаге, я сейчас выполняю извлечение как условие while:
while (is >> outputstring)
...
Это хорошо работает и не повторяет последнее слово. Что такого в этом утверждении, которое выходит из цикла while, когда оно завершает чтение? Извлечение возвращает ссылку на тот же поток, но он проверяет флаги или что-то?
Есть ли один заголовок, который позволяет включать все потоки?
Что такого в этом утверждении, которое выходит из цикла while, когда оно завершает чтение? Извлечение возвращает ссылку на тот же поток, но он проверяет флаги или что-то?
Вы абсолютно правы в том, что оператор извлечения возвращает ссылку на поток. Любое выражение, используемое в качестве условия управления while
петля (также for
а также do
—while
петля и if
заявление) принуждается к bool
тип. Это считается explicit
преобразование, так ios_base::operator bool()
называется, который возвращает !this->fail()
, И вот как флаги проверяются.
Почему последнее слово повторяется в выводе?
Вот что происходит: потому что у вас есть пробелы в конце inputstring
чтение последнего слова не переворачивает бит good (). Программа находит пробел после последнего слова, думает, что есть больше слов, поэтому is.good()
все еще возвращается true
, is.good()
возвращает ложь только в том случае, если программа пыталась прочитать после конца строки; этого еще не произошло.
Затем в следующий раз, когда вы пройдете через цикл и прочитаете is
, программа понимает, что больше нет слов, не переписывает outputstring
и так вы еще раз напишите, что было в outputstring
до того, что последнее слово.
попробуйте распечатать результат is.good()
до и после прочтения is
и удалите пробелы в конце inputstring
чтобы увидеть, что меняется …
Вы всегда должны проверить после чтение, потому что поток может быть в хорошем состоянии, но попытка что-то прочитать может дать сбой: в конце концов, поток не может знать, что вы собираетесь прочитать. Таким образом, когда вы проверяете поток после последнего элемента, он все еще good()
, Затем вы пытаетесь прочитать, что не удается и good()
является false
но вы все равно печатаете значение.
Вас также не хочу использовать .good()
в качестве условия, поскольку это может повернуться к false
даже после успешного чтения, если достигнут конец потока. Например, если число прочитано и после номера в конце файла нет пробелов, то std::ios_base::eofbit
установлено. Просто используйте idomatic цикл как это:
while (in >> value) {
std::cout << "read value='" << value << "'\n";
}
Это выглядит слишком просто, чтобы быть правильным, но на самом деле делает правильно!