-1

I have a weird problem when I test C++ STL features.

If I uncomment the line if(eee), my while loop never exits.

I'm using vs2015 under 64-bit 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;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • @Christophe - How can this be an exact duplicate? It seems very different as both `peek` and `fail` are used. Further, the question is about an if-statement not related to EOF. – Support Ukraine Apr 22 '16 at 17:00
  • @4386427 You're right it's not an exact duplicate. I reopened – Christophe Apr 22 '16 at 17:04
  • Dennis, can you please explain how this relates to the Standard Template Library (STL) ? – Christophe Apr 22 '16 at 17:05
  • @Christophe long time...... well.. I think istringstream is implemented with STL underhood. I was wondering operator << has done some magic on this class. : ( – Bing Dennis Jun 03 '21 at 11:38

2 Answers2

1

I think that

int eee = myinput.peek();

at some point returns zero.

Then due to

if (eee)

you stop reading from the stream and never reach EOF.

Try to do

if (eee >= 0)

instead

As an alternative you could do:

    if (eee < 0)
    {
        break;
    }

    // No need for further check of eee - just do the read
    myinput >> myfunclist[i++];
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • thanks so much. furthermore, it does return a zero when meet the \r\n in the istringstream, i using this if statement because the same code under xcode have a extra 0 output to myfunclist, it's weird ... the xcode's stl version have different behavior with $ms visual studio. when running this code under vs , the 0 never output to funclist even i do not use this if statement. (xcode version is 7.3) – Bing Dennis Apr 23 '16 at 00:05
0

The root cause of your problem is a misunderstanding about the way streams set their flags: fail() and eof() are only set once a reading operation fails or tried to read after the last byte was reached.

In other words, with C++ streams you may perfectly have read the last byte of your input and be at the end of file, yet eof() will stay false until you try to read more. You will find on StackOverflow many questions and answers about why you should not loop on eof in a C++ stream.

Consequences:

  • You will always enter into the loop, even if there is no character to read in myinput.
  • You therefore have to check for the special case of peek() returning EOF.
  • If you're still in the loop after the peek, then there are still characters to read. Keep in mind that peek() does not consume the characters. If you do not read it in a proper way, you stay at the same position in the stream. So if for any reason you do no reach myinput >> myfunclist[i++];, you're stuck in an endless loop, constantly peeking the same character over and over again. This is the 0 case that is well described in 4386427's answer : it's still there and you do not progress in the stream.

Other comments:

  • since your input can be 128 bytes long, and you read integers in text encoding, you could have evil input with 64 different words, causing your loop to go out ov bounds and cause for example memory corruption.
  • It is not clear why at all you try to peek.

I'd suggest to forget about the flags, use the usual stream reading idiom and simplify the code to:

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

while (i<9 && myinput >> myfunclist[i++])
{
   cout << myinput.rdstate() << endl; // if you really want to know ;-)    
}
Christophe
  • 68,716
  • 7
  • 72
  • 138