Thread: infinit loop on istream test

  1. #1
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446

    infinit loop on istream test

    The following code loops forever once I enter the failbit test.

    Code:
        int ival;
        while (cin >> ival, !cin.eof()) {
            if (cin.bad())
                throw runtime_error("Corrupted IO Stream.");
            if (cin.fail()) {                        
                cerr << "bad data, try again...";    
                cin.clear(istream::failbit);
                continue;
            }
            /* ... */
        }
    After some reading I entered cin.ignore() before the continue statement and even tried to pass gcount() to ignore() first argument. To no avail. Also, literal integers passed to ignore() seem to have the effect of only working if I match the exact lenght of the string introduced...

    What should be done?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #2
    geek SilentStrike's Avatar
    Join Date
    Aug 2001
    Location
    NJ
    Posts
    1,141
    The comma in the if is really odd.

    Instead of

    Code:
       while (cin >> ival, !cin.eof()) {
    Did you mean

    Code:
       while (cin >> ival && !cin.eof()) {
    Prove you can code in C++ or C# at TopCoder, referrer rrenaud
    Read my livejournal

  3. #3
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    No. I meant to evaluate eof() only, while still taking cin input. The comma operator evaluates both expressions but takes only the rightmost as the result.

    Code:
    int i = 0;
    while (i++, i != 6) {
       cout << i;  //outputs 12345
    }
    I could probably place my code inside a do statement and not do that comma thing, but the result will be the same. The problem seems to be that when continue executes the stream still contains whatever input was there and that caused the failbit to be set.

    Hence my tries with ignore() and gcount(). Ignore() works when I feed it with a literal integer representing the exact size of the input that causes the failbit.

    Code:
    ($ is my prompt)
    
    $ 1
    //works fine
    $ bord
    // works fine if I introduce cin.ignore(4); just before continue.
    //for some reason I cannot understand, it doesn't when i pass cin.gcount() as an argument to ignore()
    Last edited by Mario F.; 06-09-2006 at 05:51 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Why are you using gcount? What do you think that will do? Is it returning 4?

    Normally, you would just ignore everything in the stream:
    Code:
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    The loop will only break if std::cin has a problem entering a number into ival or if you simulate EOF on your keyboard. I know that on Windows you have to press ctrl+z.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, there are two problems here. The first is what Daved pointed out, that you need to discard what's left on the buffer after the cin.clear() by using cin.ignore(), perhaps with numeric_limits from <limits>. The next problem lies with your use of cin.clear(istream::failbit). This actually sets the stream's status to istream::failbit, hence entering an infinite loop. What you actually want to do is use cin.clear(istream::goodbit), or more simply, cin.clear().

    The loop will only break if std::cin has a problem entering a number into ival or if you simulate EOF on your keyboard.
    No, the loop will only terminate if the stream is in an EOF state after the read, which in this means simulating EOF as you have mentioned. The reason for this is that the comma operator returns the latter of the arguments passed, hence !cin.eof() is in question.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I didn't remember testing the value of gcount(), which is really silly of me. It returns 0.

    The documentation I have, describes gcount() as returning the number of characters read by the last input operation. It seemed a good argument to pass to ignore(). However, judging by that return value, it is far from it. I'll be reading on the web about this member function...

    It is working now. Thank you all. My use of ignore() was a joke

    Only one thing I didn't understand...
    I thought clear(istream::failbit) would reset failbit to a valid state. Failbit was ON when clear() was called, correct? So why didn't it reset when I requested specifically for that bit to be reset? Or... better yet, how can I gain fine grain access to condition states both to set and clear their respective bits?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Actually a strange name for the function if used with a parameter
    The function clear() does two things:

    * it clears all io stream state flags associated with the current stream,
    * and sets the flags denoted by flags
    Kurt

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    You are right. Thanks Kurt.

    That information is actually on my source (Herbert Schildt's C/C++ Programmers Reference, Osborne - McGraw-Hill). I didn't read it carefully enough.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    According to the standard, gcount works on unformatted input, but operator>> reads formatted input. I've never used it so I can't say I know what it is really meant for.

    You should consider using multiple references. Schildt's books have a reputation for containing errors or misleading information due to glossing over more advanced details.

  11. #11
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    It is actually a very poor reference book, if my opinion matters.

    - The STL is honored with a whooping 6 pages,
    - Some inconsistencies like C++ Strings and Exceptions being dealt in the... same chapter(!),
    - Confusing structure like Standard C I/O functions being discussed 4 chapters before we being yet again introduced to it with chapters devoted to old style and new style C++ IO.
    - Some important omissions. There's no discussion on <limits> for instance or not describing all existing overloads for getline().

    Oh well, I should have know better... 344 pages can't possibly constitute a reference to both C and C++
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can a "switch" be inside a loop?
    By gmk0351 in forum C Programming
    Replies: 5
    Last Post: 03-28-2008, 05:47 PM
  2. syntax question
    By cyph1e in forum C Programming
    Replies: 19
    Last Post: 03-31-2006, 12:59 AM
  3. How to test for a char when reading and int on a loop
    By Nazgulled in forum C Programming
    Replies: 2
    Last Post: 03-25-2006, 08:12 AM
  4. when a while loop will stop ?
    By blue_gene in forum C Programming
    Replies: 13
    Last Post: 04-20-2004, 03:45 PM
  5. Stupid compiler errors
    By ChrisEacrett in forum C++ Programming
    Replies: 9
    Last Post: 11-30-2003, 05:44 PM