Это оператор stl >> функция магия происходит?

У меня странная проблема, когда я тестирую возможности C++ STL. Если я раскомментирую строку if(eee), мой цикл while никогда не завершится.
Я использую vs2015 под 64-битной Windows.

    int i = 0;
    istream& mystream = data.getline(mycharstr,128);
    size_t mycount = data.gcount();
    string str(mycharstr,mycharstr+mycount);
    istringstream myinput(str);
    WORD myfunclist[9] = {0};
    for_each(myfunclist,myfunclist+9, [](WORD& i){ i = UINT_MAX;});
    CALLEESET callee_set;
    callee_set.clear();
    bool failbit = myinput.fail();
    bool eof = myinput.eof();
    while (!failbit && !eof)
    {
        int eee = myinput.peek();
        if (EOF == eee) break;
        //if (eee) // if i uncomment this line ,the failbit and eof will always be false,so the loop will never exit.
        {
            myinput >> myfunclist[i++];
        }
        //else break;
        failbit = myinput.fail();
        eof = myinput.eof();
        cout << myinput.rdstate() << endl;
    }

2 ответа

Я думаю что

int eee = myinput.peek();

в какой-то момент возвращается ноль.

Тогда из-за

if (eee)

Вы прекращаете чтение из потока и никогда не достигаете EOF.

Стараться сделать

if (eee >= 0)

вместо

В качестве альтернативы вы можете сделать:

    if (eee < 0)
    {
        break;
    }

    // No need for further check of eee - just do the read
    myinput >> myfunclist[i++];

Основная причина вашей проблемы - недопонимание того, как потоки устанавливают свои флаги: fail() и устанавливаются только после сбоя операции чтения или попытки чтения после достижения последнего байта.

Другими словами, с потоками C++ вы могли полностью прочитать последний байт вашего ввода и оказаться в конце файла, но все же eof()останется ложным, пока вы не попытаетесь прочитать больше. В StackOverflow вы найдете много вопросов и ответов о том, почему вам не следует использовать цикл eof в потоке C++.

Последствия:

  • Вы всегда будете входить в цикл, даже если в нем нет символа для чтения myinput.
  • Поэтому вам необходимо проверить особый случай возврата EOF.
  • Если вы все еще находитесь в цикле после просмотра, значит, еще есть символы для чтения. Имейте в виду, что peek()не потребляет персонажей. Если вы не прочитаете его должным образом, вы останетесь на том же месте в потоке. Итак, если по какой-либо причине вы не достигнете myinput >> myfunclist[i++];, вы застряли в бесконечном цикле, постоянно подглядывая одного и того же персонажа снова и снова. Это случай 0, который хорошо описан в ответе 4386427 : он все еще там, и вы не продвигаетесь в потоке.

Другие комментарии:

  • поскольку ваш ввод может иметь длину 128 байт, и вы читаете целые числа в текстовой кодировке, у вас может быть злой ввод с 64 разными словами, что приведет к выходу вашего цикла за границы ов и, например, к повреждению памяти.
  • Непонятно, зачем ты вообще пытаешься подглядывать.

Я бы посоветовал забыть о флагах, использовать обычную идиому чтения потока и упростить код, чтобы:

      ... 
callee_set.clear();  // until there, no change

while (i<9 && myinput >> myfunclist[i++])
{
   cout << myinput.rdstate() << endl; // if you really want to know ;-)    
}
Другие вопросы по тегам