Home > database >  When does feof(stdin) next to fgets(stdin) return true?
When does feof(stdin) next to fgets(stdin) return true?

Time:03-25

int main(void){


    char cmdline[MAXLINE];
    while(1){
        printf("> ");
        fgets(cmdline, MAXLINE, stdin); 
        if(feof(stdin)){            
            exit(0); 
        }
        eval(cmdline); 
    }
}

This is main part of myShell program that professor gave to me.

But there is one thing I don't understand in code.

There says if(feof(stdin)) exit(0);

What is the end of the standard input?

fgets accept all characters until the enter key is input. The end of a typical "file"(e.g.txt) is intuitively understandable, but what does the end of a standard input mean?

In what practical situations does the feof(stdin) actually return true?

Even if you enter a space without entering anything, the IF statement does not pass.

CodePudding user response:

feof tests the stream’s end-of-file indicator and returns true (non-zero) iff the end-of-file indicator is set.

For regular files, attempting to read past the end of the file sets the end-of-file indicator. For terminals, a typical behavior is that when a program attempts to read from the terminal and gets no data, the end-of-file indicator is set. In Unix systems with default settings, a way to trigger this “no data, end-of-file behavior” is to press control-D at the beginning of a line or immediately after a prior control-D.

The reason this works is because control-D is used to mean “send pending data to the program immediately.” That is described further in this answer.

Thus, if you want to end input for a program, press control-D (and, if not at the beginning of a line, press it a second time).

For input from terminals, while this does cause an end-of-file indication, it does not actually end the input or close the stream. The program can clear the end-of-file indicator and keep reading. Even for regular files, the program could clear the end-of-file indicator, reset the file context to a different position, and continue reading.

CodePudding user response:

The confusion is to assume stdin = terminal. It is not necessarily true.

What stdin is depends on how you run your program. For example, assuming your executable is named a.out, if you run it like this:

echo "foo" | ./a.out

Stdin is an output of a different process, in this example this process simply outputs the word "foo", so stdin will contain "foo" and then EOF.

Another example is:

./a.out < file.txt

In this case, stdin is "file.txt". When the file is read to the end, stdin gets EOF.

Stdin can also be a special device, for example:

./a.out < /dev/random

In this specific case it is infinite.

Last, when you simply run your program and stdin is terminal - you can generate EOF too - just press CTRL-D, this sends a special symbol meaning EOF to the terminal.

P.S. There are other ways to execute a process. Here I only gave examples of processes executed from the command line shell. But process can be executed by a different process, not necessarily from the shell. In this case the creator of the process can decide what stdin will be - terminal, pipe, socket, file or any other object.

  •  Tags:  
  • c
  • Related