Thread: Resetting stdin after EOF

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    2

    Resetting stdin after EOF

    I have a piece of code that looks like this:

    ---example.c---

    Code:
    #include <stdio.h>
    
    int main() {
            char c;
            while ((c = getchar()) && (c != EOF))
                    ;
            putchar('\n');
            c = getchar();
            printf("%c\n", c);
    }
    Entering input from the keyboard, this program works fine.
    However, if I then redirect input to this program (e.g. dmesg | ./example), then I get a garbage character printed to the console, and the program does not wait for input from the keyboard.
    I assume this is something to do with resetting stdin - how can I pass input back to the keyboard?

    Thanks,
    Rob

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Code:
    #include <stdio.h>
    
    int main()
    {
        int c;
        while ((c = getchar()) != EOF ) {
            putchar(c);
        }
        printf( "EOF from file, now reading stdin\n" );
        clearerr(stdin);
        while ((c = getchar()) != EOF ) {
            putchar(c);
        }
        printf( "All done\n" );
        return 0;
    }
    Points to note
    1. c is declared as int - which you need if you're ever going to separate the value of EOF from any character.
    2. main returns a value.

    Now the clearerr(stdin); is only going to work if your input starts off with the keyboard (you can press ctrl-D twice, and it will execute both loops).
    However, redirected input ( via < or | ) isn't going to work like that, once EOF is detected, that's it.

    So in order to process some input, then process stdin, you need to do something like this
    Code:
    cat hello.c - | ./a.out
    ( dmesg ; cat - ) | ./a.out
    Use "cat -" to read from stdin and copy it to the pipe to your program.
    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.

  3. #3
    Registered User
    Join Date
    May 2005
    Posts
    2
    But what if I can't do that? I need the user to be able to simply redirect input to the program, rather than to have them execute a complicated expression in doing so.
    Take the program "less" as an example - it can get redirected input, and then perfectly happily accept keyboard input from the user, so there must be some way of doing it

    Is there any way I could reset the terminal and so set stdin to keyboard input again, as it were?

  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
    Well I suggest you read the source code to less then.

    But the answer is almost certainly far from portable, since it's likely to read from the terminal directly rather than from stdin.
    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
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    There is a way, but like Salem said, it's definitely not portable. This works on my Linux box though:
    Code:
    itsme@itsme:~/C$ cat filethenstdin.c
    #include <stdio.h>
    
    int main(void)
    {
      char buf[BUFSIZ];
    
      puts("Reading from stdin...");
      while(fgets(buf, sizeof(buf), stdin))
        fputs(buf, stdout);
    
      freopen("/dev/tty", "rw", stdin);
    
      puts("Reading from stdin again...");
      while(fgets(buf, sizeof(buf), stdin))
        fputs(buf, stdout);
    
      return 0;
    }
    Code:
    itsme@itsme:~/C$ cat search.txt
    a
    b
    c
    d
    e
    f
    g
    itsme@itsme:~/C$ ./filethenstdin < search.txt
    Reading from stdin...
    a
    b
    c
    d
    e
    f
    g
    Reading from stdin again...
    this is a test
    this is a test
    yay
    yay
    ^d
    itsme@itsme:~/C$
    It works because /dev/tty always points to the user's terminal.
    Last edited by itsme86; 05-22-2005 at 08:06 AM.
    If you understand what you're doing, you're not learning anything.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using fread on stdin
    By nadroj in forum C Programming
    Replies: 29
    Last Post: 10-23-2008, 02:03 PM
  2. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  3. EOF or not EOF?
    By CornedBee in forum Linux Programming
    Replies: 2
    Last Post: 09-14-2007, 02:25 PM
  4. EOF messing up my input stream?
    By Decrypt in forum C++ Programming
    Replies: 4
    Last Post: 09-30-2005, 03:00 PM
  5. files won't stop being read!!!
    By jverkoey in forum C++ Programming
    Replies: 15
    Last Post: 04-10-2003, 05:28 AM