Thread: trying to get back into it

  1. #1
    5|-|1+|-|34|) ober's Avatar
    Join Date
    Aug 2001
    Posts
    4,429

    trying to get back into it [Resolved]

    Ok, so I'm brushing up on my C and trying to get other language nuances out of my head. I tried the following code:

    Code:
     int main(void)
    {
       
       printf("Hello world!");
       while(getc(stdin) != '\n')
    	   printf("I'm not exiting yet!\n");
       return 0;
    }
    ... which I thought would print the statement in the printf everytime a user hit a key that wasn't the Enter key. But it doesn't print all the statements until I hit Enter. Do I need to flush stdout after each print?
    Last edited by ober; 03-19-2004 at 09:52 AM.

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >But it doesn't print all the statements until I hit Enter.

    FAQ > How do I... (Level 2) > How can I get input without having the user hit [Enter]?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User char's Avatar
    Join Date
    Apr 2002
    Posts
    31
    The terminal driver returns when a line has been entered. Until then the OS keeps the input in a buffer located in its memory space. When the driver returns (like when user hits <enter>) the buffer is passed to the program. This is how it works when in "canonical mode". In UNIX you can switch to "noncanonical mode" by turning off the ICANON flag in the c_flag field of the termios structure. In noncanonical mode the input data is not assembled into lines. At least this is how it works in UNIX. For more info:

    Advanced programming in the UNIX environment

    Here is an example program that shows how you can set up a terminal device to read single characters in noncanonical input mode, without echo.


    Code:
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <termios.h>
    
    /* Use this variable to remember original terminal attributes. */
    
    struct termios saved_attributes;
    
    void 
    reset_input_mode (void)
    {
      tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
    }
    
    void 
    set_input_mode (void)
    {
      struct termios tattr;
      char *name;
    
      /* Make sure stdin is a terminal. */
      if (!isatty (STDIN_FILENO))
        {
          fprintf (stderr, "Not a terminal.\n");
          exit (EXIT_FAILURE);
        }
    
      /* Save the terminal attributes so we can restore them later. */
      tcgetattr (STDIN_FILENO, &saved_attributes);
      atexit (reset_input_mode);
    
      /* Set the funny terminal modes. */
      tcgetattr (STDIN_FILENO, &tattr);
      tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
      tattr.c_cc[VMIN] = 1;
      tattr.c_cc[VTIME] = 0;
      tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
    }
    
    int
    main (void)
    {
      char c;
    
      set_input_mode ();
    
      while (1)
        {
          read (STDIN_FILENO, &c, 1);
          if (c == '\004')          /* C-d */
            break;
          else
            putchar (c);
        }
    
      return EXIT_SUCCESS;
    }
    Last edited by char; 03-19-2004 at 09:46 AM.

  4. #4
    5|-|1+|-|34|) ober's Avatar
    Join Date
    Aug 2001
    Posts
    4,429
    Ok... thanks. I guess I just need to use getch instead of getc.

  5. #5
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by ober
    Ok... thanks. I guess I just need to use getch instead of getc.
    No, not getch() but getchar(). getchar() is equivalent to getc(stdin);

    And the answer to your original question is simply "Yes, flush stdout"

    Both responses above are confusing you. Dave misinterpreted your question, and char was explaining how a Linux keyboard driver works.
    Last edited by WaltP; 03-19-2004 at 12:47 PM.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  6. #6
    5|-|1+|-|34|) ober's Avatar
    Join Date
    Aug 2001
    Posts
    4,429
    Thanks Walt. I kinda ignored their posts anyways. I figured it out on my own. And thanks for the getchar() advice. I'll use that instead.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    This is the question I answered:
    ... which I thought would print the statement in the printf everytime a user hit a key that wasn't the Enter key. But it doesn't print all the statements until I hit Enter. Do I need to flush stdout after each print?
    The I/O buffering of the shell may be such that getc(stdin)/getchar() waits until [Enter] is pressed, whether you type one character or many. If at that point getchar() finally takes a look at the input buffer, then the while loop is entered.

    Whether or not you have a fflush(stdout), the first printf() may not be executed until after you have pressed [Enter] because the first getchar() call may have yet to return. If you had pressed multiple keys, those would then immediately be available to susbsequent loop iteration evaluations of getchar() without further user input. And the end result might be as follows.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
       printf("Hello world!");
       while ( getchar() != '\n' )
       {
          printf("I'm not exiting yet!\n");
          fflush(stdout);
       }
       return 0;
    }
    Running the program, I type several numbers, but no [Enter]
    Code:
    Hello world!123456
    Then I press [Enter] which is followed by this.
    Code:
    I'm not exiting yet!
    I'm not exiting yet!
    I'm not exiting yet!
    I'm not exiting yet!
    I'm not exiting yet!
    I'm not exiting yet!
    So if the question really was, "I want to display the text, "I'm not exiting yet!\n" immediately whenever any key is pressed," then fflush(stdout) may do nothing for you. In order to immediately respond to keypresses, you would need to go nonstandard and do something like getch() as shown in the FAQ. I might then add something about possible issues with checking for a getch() for a newline, but apparently my posts are kinda being ignored anyway.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by WaltP
    No, not getch() but getchar(). getchar() is equivalent to getc(stdin);

    And the answer to your original question is simply "Yes, flush stdout"

    Both responses above are confusing you. Dave misinterpreted your question, and char was explaining how a Linux keyboard driver works.
    I stand humbly before all and ask forgiveness. Dave, you were correct. I read the post wrong multiple times

    Yes, the getc() and getchar() will not let the program continue until a return is entered. Then the program will print one statement for each character after the return. getch() is in fact what you want.

    My misteak was in reading
    which I thought would print the statement in the printf
    and interpreting "the printf" as the first printf. Note to posters -- ambiguity sux
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. "if you love someone" :D
    By Carlos in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 10-02-2003, 01:10 AM
  2. UInt to CString and back
    By xlnk in forum Windows Programming
    Replies: 6
    Last Post: 08-27-2003, 03:08 PM
  3. Some woman back ended my car today, and back hurts
    By Terrance in forum A Brief History of Cprogramming.com
    Replies: 19
    Last Post: 08-20-2003, 12:42 AM
  4. Returning a Tree node back to void main()
    By gazza in forum C++ Programming
    Replies: 2
    Last Post: 07-07-2002, 02:48 AM
  5. I am back!
    By Betazep in forum A Brief History of Cprogramming.com
    Replies: 19
    Last Post: 03-02-2002, 06:22 PM