18

Does stdin have any EOF? For example, if I start reading from stdin using fread or read, then will the following loop end?

while ((c = read(0, buffer, BUFSIZ)) > 0) {
    .
    .
    .
}

If the answer to this question is no, then is there any way to add EOF to stdin?

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
Ravi Gupta
  • 6,258
  • 17
  • 56
  • 79

6 Answers6

30

Speaking about EOF in stdin: when you redirect input from file, e.g.:

program <input.txt

the file already has an EOF, so this is not a problem. In console you can simulate EOF flag. In UNIX systems it is Ctrl+D, in Windows Ctrl+Z. When you type this in the console, program will behave like it has just reached end of input file.


Edit

According to a question asked by OP:

So does it means that stdin don't have EOF and we have to insert them manually using Ctrl+Z or Ctrl+D?

Actually -- yes. One may consider stdin (not redirected, but taken from the console) as infinite file -- no one can tell where does it end. The end of input file, where input ist stdin, must be told literally by Ctrl+D or Ctrl+Z.

Archie
  • 6,391
  • 4
  • 36
  • 44
  • 1
    As I've just learned myself, Ctrl+D does *not* 'send EOF' but sends EOT. EOT after not input (or after all input is already sent) makes stdin to have EOF. But when you input "ABC" and then Ctrl+D it will just send the buffer to the process and not 'signal' EOF. – ljrk Oct 24 '15 at 19:27
  • If you redirect input from `/dev/null` it will EOF immediately. – dashesy Dec 16 '16 at 04:57
4

I have never programmed C in windows so I can't tell you but in bash, the program will get an EOF when you type end of data (Ctrl+D)

sui
  • 120
  • 6
  • 1
    In MS-DOS the Ctrl+Z key will also signal an EOF condition. (But not on *nix systems). – Thomas Matthews Jul 07 '10 at 16:58
  • Yes, basically this is sending EOF to the stream – LukeN Jul 07 '10 at 16:58
  • @LukeN Actually it just closes the stream. There is no actual EOF character. – Bart van Heukelom Jul 07 '10 at 18:11
  • @Bart van Heukelom so after typing Ctrl+D, what should i do if i want to read more inputs from stdin later on? is it possible? – Ravi Gupta Jul 07 '10 at 18:16
  • 3
    If you're using stdio, you can call `clearerr(stdin);` to clear the EOF status and you will be able to continue reading. (If stdin is a file that hasn't grown since you got EOF, you'll just get a new EOF condition as soon as you try to read.) If you're using low-level `read()`, it returns 0 on when the terminal has EOF status, but if you try to read again it will block waiting for input. – R.. GitHub STOP HELPING ICE Jul 07 '10 at 18:26
2
while ((c = read(0, buffer, BUFSIZ)) > 0) { 

You don't say the type of c but using that name implies that it's a char. Note that the EOF value for iosteams is an (int) -1. Storing that into an unsigned char will get you a value of 255 which will not match EOF.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • ok ... `c` is of `int` type ... i was just giving the example .... now come back to the original problem and according to you, what is the ans? – Ravi Gupta Jul 07 '10 at 18:11
0

First getchar() is really getc(stdin) so getc(FILE) you can read more from that. getchar() gets you last unprocessed character from input stream or stdin pressing enter is '\n'. if the stdin is empty getchar forces a pause to get input. Say in a program I call getchar() at first the stdin is empty so it pauses for input. If I enter ab'\n' the first getchar() will get 97 the ascii of 'a'. the next time i call getchar() i will get b , then again getchar() will have '\n'.

To prove this write this code.

    int choice;

    do
   {
      cout << "Enter input:" ;
      choice = getchar(); 
      cout << "Last getchar(): " << choice << ":" << (char) choice ; 
       if( choice == '0' || choice == EOF)
         {
           cout << "Exited loop" << endl;     // EOF is ctrl+z in windows 
           break;
         }

   }while(true);

I do believe stdin is a global so until getchar() or similar function gets called it to clear the stream the characters remain there which can cause bugs later if you use getchar() elsewhere. As people have mentioned you can use gets(char[]) which puts all characters until newline into the character array. The problem with this is you need a char[] larger than input or you will get errors. The nice thing is gets(char[]) does clear stdin so you can make a dumby buffer to clear stdin or process it.

I hope this is informative.

user1364455
  • 29
  • 1
  • 2
0

The way to test for EOF is to check the return value of fread, and then use feof:

while( fread( ... ) ) {    // loop so long as fread does not return zero
    // do something
}

if ( feof( stdin ) ) {
   // read failed because of EOF
}
else {
   // some other error
}
  • @Ravi That should not happen. –  Jul 07 '10 at 17:22
  • why? ... you mean to say the `while` loop will return after a finite number of iterations ... if so the after how many? – Ravi Gupta Jul 07 '10 at 17:24
  • @Ravi fread() attempts t read data - if there is nothing to read, it returns zero. So the loop above will read standard input or a file until an EOF is encountered. –  Jul 07 '10 at 17:27
  • @Neil Butterworth ok ... i tried your code and it gives `some other errors`. So does it means that stdin don't have EOF and we have to insert them manually using Ctrl+Z or Ctrl+D? – Ravi Gupta Jul 07 '10 at 17:52
  • It could mean that stdin contained a 0 – Bart van Heukelom Jul 07 '10 at 18:13
  • @Neil Butterworth actually i filled the other details to make it a complete program. Here is the entire code. `#include #include #include #define SIZE 65536 int main() { char buffer[SIZE]; int c; while ((c = fread(buffer, 1, SIZE, stdin)) > 0) { printf("Inside while\n"); } if ( feof( stdin ) ) { printf("read failed because of EOF\n"); } else { printf("some other error\n"); } return 0; } ` – Ravi Gupta Jul 07 '10 at 18:22
  • @Neil: Indeed. I wrongly assumed fread() returns 1 read byte (as read() on Java streams does). – Bart van Heukelom Jul 07 '10 at 18:29
0

Your solution is tagged C++, so here's some C++.

std::string lols;
while(!(std::cin >> lols).eof()) { // This loop will end when EOF is reached
    // Process string
}
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • will the loop ends? .... that what i am asking ... i am not asking different ways of writing the same code. – Ravi Gupta Jul 07 '10 at 17:29
  • 3
    You have overcomplicated that and in doing so broken it. If the read fails for some other error then the stream will be marked bad and not read anymore but the EOF will not be reached and thus loop forever. The simpler and correct way to loop would be: 'while( std::cin >> lols) {}' – Martin York Jul 07 '10 at 17:32
  • @Martin York: I did originally have it without the EOF, but the OP's comment shows that he could really use the hint about what's going on. @Ravi Gupta: It will keep going until EOF. That's why I put in the EOF function check. So that it's goddamn obvious that the code executes until EOF. And there's a comment there, telling you that the loop will end when EOF is reached. I mean, this code is pretty self explanatory. – Puppy Jul 07 '10 at 18:24