tldr; Да, это гарантированно работает, если поток изначально пуст.
Есть два бита учитывать следующие аспекты: fail
бит и eof
бит. std::getline
делает из [string.io]:
После построения sentry
объекта, если караул превращается в истинный, вызывает str.erase()
, а затем извлекает символы из это и добавляет их к str
как при вызове str.append(1, c)
[. ..] Если функция не извлекает никаких символов, он вызывает is.setstate(ios::failbit)
И sentry
делает из [IStream :: часового]:
Эффекты: если is.good()
- false
, звонки is.setstate(failbit)
. В противном случае готовится форматированный или неформатированный ввод. [...] Если is.rdbuf()->sbumpc()
или is.rdbuf()->sgetc()
возвращает traits::eof()
, функция вызывает setstate(failbit | eofbit)
Поэтому, учитывая все это, давайте разберем два примера:
Случай 1: "hello\n"
. Первый вызов getline()
, the_stream.good()
истинен, мы извлекаем символы вверх через \n
, поток по-прежнему good()
, и мы вводим тело цикла с line
, установленным в "hello"
.
Второй вызов getline()
, поток по-прежнему good()
, поэтому sentry
объект превращается в истинное, и мы называем str.erase()
. Попытка извлечь последующие символы не удалась, так как мы закончили с потоком, поэтому установлен failbit
. Это приводит к возврату getline()
для преобразования в false, поэтому мы не вводим тело цикла во второй раз. В конце цикла line
пуст.
Дело 2: "goodbye"
, no newline. Первый вызов getline()
, the_stream.good()
правдив, мы извлекаем символы, пока не нажмем eof()
.Поток failbit
еще не установлен, поэтому мы по-прежнему вводим тело цикла, с линией, установленной на "goodbye"
.
Второй вызов getline()
, строительство sentry
объекта не удается, потому что is.good()
является ложным (is.good()
проверяет как eofbit
и failbit
). Из-за этого отказа мы не переходим на первый шаг getline()
, который вызывает str.erase()
. И из-за этого отказа, failbit
установлен таким образом, чтобы мы снова не вошли в тело цикла.
В конце цикла line
по-прежнему "goodbye"
.
Дело 3: ""
. Здесь getline()
не извлекает никаких символов, поэтому устанавливается failbit
, и цикл никогда не вводится, а line
всегда пуст. Есть несколько способов, чтобы дифференцировать этот случай от случая 1:
- Вы можете, фронт,
peek()
, чтобы увидеть, если первый символ traits::eof()
, прежде чем делать что-нибудь еще.
- Вы можете подсчитать, сколько раз вы вводите цикл и убедитесь, что оно отличное от нуля.
- Вы можете инициализировать
line
некоторому неточному значению часового. В конце цикла линия будет пустой, если поток заканчивается делителем.
файлов должны заканчиваться символом новой строки. Этот тест обнаружит поток, который либо ** ** ** только одна новая строка, либо заканчивается ** двумя или более символами новой строки. –
Текстовый поток, который не заканчивается символом новой строки, не является допустимым входным потоком в C или C++. Операции ввода в этом потоке не требуются для разумного обращения. –
Итак, с std :: stringstream the_stream (""); the_stream << "привет!"; является входным сигналом the_stream? Я считаю, что это то, что я получаю, если читаю в файле (используя ifstream), который не заканчивается новой строкой. – Jens