Thread: Strange bug with Input stream

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    9

    Strange bug with Input stream

    Hi,

    Ive been stuck on this bug for a while now, Ive tried googling the answers etc but everything I try seems to fail:

    Code:
    string yytext;
    char ch;
    
                instream.get(ch);
                yytext += ch;                      // Puts character from stream on the end of the string
    
                while(isalnum(ch))              // loop while character is alpha-numeric
                {
                    instream.get(ch);            // needs to call the next character in the stream
                    yytext += ch;                  // add character to end of string
                }
    instream is streaming a text file into the program; this part of my function needs to stick alphanumeric characters together in to a word.

    Whats happening is the instream.get(ch); is just pulling the same character off the instream, and going into an infinite loop

    is there a nice simple call I can use to increment the steam position?
    Any suggestions would be awesome,

    thanks,

    Pete
    Last edited by Chazij; 11-18-2008 at 02:19 PM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I think that you need to incorporate the reading of the character with the loop, e.g.,
    Code:
    while (instream.get(ch) && isalnum(ch))
    {
        yytext += ch;
    }
    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

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I think that you need to incorporate the reading of the character with the loop, e.g.,
    Code:
    while (instream.get(ch) && isalnum(ch))
    {
        yytext += ch;
    }
    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

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Chazij
    Its ignoring the while loop when written like this.
    I thought that I might have made a mistake, but this sample program shows that I did not:
    Code:
    #include <iostream>
    #include <string>
    #include <cctype>
    
    int main()
    {
        using namespace std;
    
        string yytext;
        char ch;
        while (cin.get(ch) && isalnum(ch))
        {
            yytext += ch;
        }
        cout << yytext << endl;
    }
    Now it's your turn to come up with the smallest and simplest compilable program that demonstrates the problem.
    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

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Um, but you did not change your code as I suggested.
    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

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    9
    I did, but like I said it for some unknown reason it just skips the while loop.


    Thanks very much for your help laserlight

    Code:
                yytext += ch;
    
                while(isalnum(ch) && target_code.get(ch))
                {
                    cout << ch << endl;
                    yytext += ch;
                    cout << yytext << endl;
                    system("PAUSE");
                }
    with it changed.
    Last edited by Chazij; 11-18-2008 at 03:28 PM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Chazij
    I did, but like I said it for some unknown reason it just skips the while loop.
    Check that the input at that point really is what you expect.

    Incidentally, the loop condition should be reversed as in my example:
    Code:
    while (target_code.get(ch) && isalnum(ch))
    If you have reached EOF, you want to end the loop immediately. What you are doing now is checking if the previous char is alphanumeric instead.
    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

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Before the loop ch has to be initialized. Therefore it might make sense to switch the order of the arguments, so that get() puts some good value into the variable.

    You need to know that if the stream fails to read a character (end of input), it leaves the character unmodified and goes into a fail state, meaning that all subsequent reads will fail too.

    Similarly, it is also wrong to control input loops with eof(). The fact that eof() returns true doesn't mean the next read from the stream is going to succeed (and if it doesn't you'll process the last input twice). Again, make the input statement the condition of the loop.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > target_code.eof()
    See the FAQ for why this is bad.

    > while(old_c != '*' && c != '/')
    You don't test for the input returning eof.
    If the input fails, c remains unchanged, and you get stuck.

    Ideally, you should only read the file in ONE place. Consider reading up on state machines.
    Code:
    typedef enum states {
        ST_INITIAL,
        ST_COMMENT1,
        ST_MAX
    } states;
    
    
        states state = ST_INITIAL;
        while ( target_code.get(c) ) {
            switch ( state ) {
                case ST_INITIAL:
                    if ( c == '/' ) state = ST_COMMENT1;
                break;
                case ST_COMMENT1:
                    if ( c == '*' ) state = ST_COMMENT2;
                    else state = ST_INITIAL;
                break;
            }
        }
    Adding states like "IN_COMMENT" and "IN_STRING" etc.

    http://en.wikipedia.org/wiki/Finite_state_machine

    Once you know what all your parser states are, implementing the code to walk around the FSM is pretty easy.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Nov 2008
    Posts
    9
    Still skips it when I swap them round :P

    It goes infinite, since the same char is called from the stream (for no reason it seems).

    It's stuc on 'v' from the first void in the txt file, so I'm guessing the stream refuses to progress when I call the target_code.get(ch).

    I know the code is inefficent in some places, but as the stream its dealing with has been modified such that the eof character will never be next to an alphanumeric character, I think I'll skip modifying the structure anon.

    Thanks salem for the info, I might modify the code once I get it working correctly. I've never seen that done before, but I like it


    But still the problem/bug is messing it up I am totally boggled, it seems to defy all logic.
    Last edited by Chazij; 11-18-2008 at 03:20 PM.

  11. #11
    Registered User
    Join Date
    Nov 2008
    Posts
    9
    Thanks for all the replies, they really helped,
    I've worked out why everything was going wrong:

    Basically because I defined the stream in a different function, everytime I tried to call the next character it failed, making the while loop skip and the character stay as v.

    All I need to do is make the stream available to this function, either by declaring it globally or sending a pointer to the function.

    Could anyone tell me how to make a pointer of my stream, my brain is jelly now :<,

    thanks,

    Pete

  12. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It's quite typical to pass streams as references:

    Code:
    void foo(std::istream& is);
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  13. #13
    Registered User
    Join Date
    Nov 2008
    Posts
    9
    You are a true legend,

    thankyou

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. Input class project (again)
    By Elysia in forum C++ Programming
    Replies: 41
    Last Post: 02-13-2009, 10:52 AM
  3. How to declare a global input stream
    By Chazij in forum C++ Programming
    Replies: 2
    Last Post: 11-18-2008, 04:53 PM
  4. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  5. clearing input stream
    By Sub in forum C++ Programming
    Replies: 2
    Last Post: 01-21-2002, 08:59 PM