В чем разница проверки eof () на getline, то есть while (! Getline (). Eof ()) и простой проверки while (getline ()) - PullRequest
2 голосов
/ 02 июля 2019

В чем разница между while (getline ()) и while (! Getline (). Eof ())?

Я анализирую входную строку.Я пытался проверить оба условия, и я вижу разницу в результате.

std::string testStr = "CN=Test, OU=XYZ, O=ABC";
std::stringstream inpStrStream(testStr);
std::string tempStr;
getline(inpStrStream, tempStr, '=');
std::cout<<"Hello:"<<tempStr<<std::endl;

//Let's call this as "Ex A"
while(getline(inpStrStream, tempStr, '='))
{
   std::cout<<tempStr<<std::endl;
}
    (OR)
//Let's call this as "Ex B"
while(!getline(inpStrStream, tempStr, '=').eof())
{
   std::cout<<tempStr<<std::endl;
}

Я ожидал одинакового результата в обоих случаях, но результаты для "Ex A" и "Ex B" различны.Я не вижу строку "ABC" в выходных данных "Ex B":

Ex Результат: Hello: тест CN, OU XYZ, O ABC

Результат Ex B: Hello: CNТест, OU XYZ, O

Ответы [ 3 ]

1 голос
/ 02 июля 2019

Ссылка: CppReference.com, "iostate"

getline() возвращает ссылку на поток, в котором он работает, т.е. inpStrStream.

inpStrStream.operator bool() (или while ( inpStrStream ) / while ( getline( inpStrStream, tempStr, '=' ) )) проверит, установлены ли failbit или badbit потока.

! inpStrStream.eof() проверит, установлен ли eofbit потока.(*)

Состояния CppReference,

... почти во всех ситуациях, если установлено eofbit, также установлено failbit.

Вы попали в одно из исключений здесь..operator!() проверяет failbit, , а не для eofbit - и что getline() из "ABC" устанавливает eofbit (при достижении EOF потока), , ноне failbit (так как эта последняя операция все еще была успешной).Это заставляет .eof() завершить цикл (не печатая "ABC"), в то время как .operator!() выполнит еще одну итерацию (печатая "ABC"), попробовав другую getline(), которая завершится неудачей (так как больше нечего читать),установка failbit и завершение цикла.

Итак ... .eof() будет явно проверять только для EOF * , т.е. будет пытаться продолжить, даже если что-тоПроизошла неприятная ситуация с базовым потоком, для которого был установлен один из двух других флагов.


(*): Обратите внимание, что есть еще тесты.Единственными симметричными являются .fail() и .operator!() (которые проверяют одно и то же), а их симметричная противоположность .operator bool().Остальные - .good(), .bad() и .eof() - проверяют разные вещи!

0 голосов
/ 02 июля 2019

Класс std::stringstream наследует класс std::basic_ios, который определяет оператор

explicit operator bool() const;

что

1 Возвращает:! Fail ().

Этот оператор используется в условии оператора while

while(getline(inpStrStream, tempStr, '=')) 

для контекстного преобразования объекта, возвращаемого вызовом std::getline, в тип bool.

Из стандарта C ++ (преобразования C ++ 17, 7 Standard)

4 Некоторые языковые конструкции требуют преобразования выражения к логическому значению. Выражение e, появляющееся в таком контексте: называется контекстно преобразованным в bool и хорошо сформирован, если и только если декларация bool t (e); хорошо сформирован, для некоторых изобретен временная переменная t (11,6).

0 голосов
/ 02 июля 2019

Посмотрите на этот простой тестовый код:

#define LOG(x) std::cout << __LINE__ << ": " #x " = " << x << '\n'

void test(char termChar)
{

    std::stringstream input;
    input << "lets try this!";
    std::string s;
    std::getline(input, s, termChar);

    LOG(!!input);
    LOG(input.eof());
    char ch = '?';

    input >> ch;
    LOG(!!input);
    LOG(input.eof());
    LOG(ch);
}

int main()
{
    test('!');
    std::cout << '\n';
    test('#');

    return 0;
}

И его вывод: https://wandbox.org/permlink/r4OSFnkG3ZFETgd4

14: !!input = 1
15: input.eof() = 0
19: !!input = 0
20: input.eof() = 1
21: ch = ?

14: !!input = 1
15: input.eof() = 1
19: !!input = 0
20: input.eof() = 1
21: ch = ?
  1. Помните, eof не означает, что вы находитесь в конце потока, но вы пытались прочитать поток вне его размера.
  2. Теперь при втором запуске test getline прошло успешно (!!input), но была попытка чтения за пределами размера потока, поэтому eof возвращает true. Теперь ваш цикл с eof может отклонять важные для вас вещи, поскольку eof установлен на true, но чтение прошло успешно.
...