Thread: stdin question

  1. #1
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489

    Talking stdin question

    Code:
    Hello world!
    ^
    getchar(); <-- returns 'H'
    
    Hello world!
     ^
    getchar(); <-- returns 'e'
    
    Hello world!
      ^
    getchar(); <-- returns 'l'

    1. How about:

    Code:
    Hello world!
     ^
    undochar() <-- returns 'e'
    
    Hello world!
    ^
    undochar() <-- returns 'H'

    2. Or something like:

    Code:
    Hello world!
        ^
    nextchar(5) <-- returns 'o'
    
    Hello world!
     ^
    prevchar(3) <-- returns 'e'


    3. Or something like Java:

    Code:
    Hello world!
    ^
    getchar(); <-- returns 'H'
    
    Hello world!
     |
    mark();
    
    Hello world!
     ^
    getchar(); <-- returns 'e'
    
    Hello world!
      ^
    getchar(); <-- returns 'l'
    
    Hello world!
     |
    reset();
    
    Hello world!
     ^
    getchar(); <-- returns 'e'
    Last edited by audinue; 01-10-2009 at 05:51 AM.
    Just GET it OFF out my mind!!

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    ungetc() allows (at least) one pushbask to the input stream.
    If it does not reply to the question, maybe it's because there is no explicit question...
    fseek(), fgetpos(), fsetpos() might do the work for the rest.
    Last edited by root4; 01-10-2009 at 06:00 AM.

  3. #3
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    So, it uses fgetc(stdin) and ungetc(stdin). Thanks root4!
    Just GET it OFF out my mind!!

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    On a file stream (not stdin), then mark() is ftell() and reset() is fseek()
    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.

  5. #5
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    Whoops! Something doesn't work here, could you give me some guide please?

    Code:
    char look;
    
    nextChar() {
      look = getchar();
    }
    
    prevChar() {
      //ungetc(look, stdin);
      look = ungetc(look, stdin);
    }
    
    main() { //for instance we will input abc
      nextChar();
      printf("%c\n", look); //print out a
      nextChar();
      printf("%c\n", look); //print out b
      prevChar();
      printf("%c\n", look); //print out b, it should print out a by the way
    }
    Last edited by audinue; 01-10-2009 at 11:23 AM.
    Just GET it OFF out my mind!!

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by audinue
    Something doesn't work here, could you give me some guide please?
    The 1999 edition of the C standard states that: "The ungetc function returns the character pushed back after conversion, or EOF if the operation fails."
    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
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    starting from 'abc', in your code, you read 'a', then 'b', then you apply ungetc(), which pushback 'b', so next time you read the stream you'll get 'b', in fact you should push back 'b' and 'a' to actually get 'a' but you're not allowed to do that (only one char can be pushed back). So switch to plan B and use fseek() or its friends.

  8. #8
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    Hmm.. I think there is no way to do this except using buffer. And yet quiet complex.

    Thanks in advance, I give up.
    Just GET it OFF out my mind!!

  9. #9
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    What you are getting is correct: ungetc() on success returns the byte that was pushed back onto the stream which in this case is "b" not "a".

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It's not clear (to me, anyway) why you expected to get 'a' out of that code. ungetc doesn't undo any assignments you made or anything; it just puts the most recent character back in the input stream.

  11. #11
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    It's not clear (to me, anyway) why you expected to get 'a' out of that code. ungetc doesn't undo any assignments you made or anything; it just puts the most recent character back in the input stream.
    However this one done with file stream but not stdin so I can't test it on the way.

    Code:
    void scan(void) {
      char c = fgetc(file); //fetch
      switch(c) {
        case '+':
          putchar(c); //collect
          c = fgetc(file);
          switch(c) {
            case '=':
            case '+':
              putchar(c); 
              putchar('\n'); return; //emit
            default:
              //for instance we support +?+ token
              c = fgetc(file);
              if(c == '+') {
                putchar(c);
                putchar('\n'); return;
              } else {
                fseek(file, -2, SEEK_CUR); //undo 2 step
              }
          }
          putchar('\n'); return;
        case '-':
          putchar(c);
          c = fgetc(file);
          switch(c) {
            case '=':
            case '-':
              putchar(c);
              putchar('\n'); return;
            default:
              fseek(file, -1, SEEK_CUR); //undo 1 step
          }
          putchar('\n'); return;
      }
    }
    Last edited by audinue; 01-11-2009 at 02:38 AM.
    Just GET it OFF out my mind!!

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    So do the exact same thing with stdin and be done with it:
    Code:
    void scan(void) {
        char c = fgetc(stdin);
        switch(c) {
            case '+':
                putchar(c);
                c = fgetc(stdin);
                switch(c) {
                    case '=':
                    case '+':
                        putchar(c);
                        break;
                    default:
                        ungetc(c, stdin);
                }
                break;
            case '-':
                putchar(c);
                c = fgetc(stdin);
                switch(c) {
                    case '=':
                    case '-':
                        putchar(c);
                        break;
                    default:
                        ungetc(c, stdin);
                }
        }
        putchar('\n');
    }
    Exactly the same code, except using stdin. Works exactly the same way, gives exactly the same results, etc.

  13. #13
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    Oh! Awesome! Thanks tabstop I didn't notice it.

    Code:
    void *stream; //init stream on main()
    
    #define fetch   c = fgetc(stream);
    #define collect putchar(c);
    #define emit    putchar('\n'); return;
    #define undo    ungetc(c, stream);
    
    void scan(void) {
      char fetch;
      switch(c) {
        case '+':
          collect;
          fetch;
          switch(c) {
            case '=':
            case '+':
              collect;
              fetch;
              switch(c) {
                case '+':
                  collect;
                  emit;
                default:
                  undo;
              }
              emit;
              break;
            default:
              undo;
          }
          emit;
        case '-':
          collect;
          fetch;
          switch(c) {
            case '=':
            case '-':
              collect;
              emit;
              break;
            default:
              undo;
          }
          emit;
      }
    }
    
    #undef undo
    #undef emit
    #undef collect
    #undef fetch
    EDIT: Do you have another proper name instead of undo, emit, collect and fetch?
    They looks ugly for me.
    Just GET it OFF out my mind!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. another do while question
    By kbpsu in forum C++ Programming
    Replies: 3
    Last Post: 03-23-2009, 12:14 PM
  2. struct question part 2
    By ronin in forum C Programming
    Replies: 4
    Last Post: 06-23-2003, 05:09 PM
  3. stdin question
    By SourceCode in forum C Programming
    Replies: 1
    Last Post: 04-10-2003, 08:50 PM
  4. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM
  5. stdin question
    By oomen3 in forum C Programming
    Replies: 6
    Last Post: 02-19-2003, 02:52 PM