End of File in stdin - c

A question about this has been asked here
End of File (EOF) in C
but it still doesn't completely solve my problem.
EOF makes sense to me in any datastream which is not stdin, for example if I have some data.txt file, fgetc() will read all the chars and come to the end of file and return -1.
What I don't understand is the concept of EOF in stdin. If I use getchar(), it will wait for me to enter something, so if there is NOTHING written, End of File, (EOF) is not returned automatically?
So is it that only the user can invoke EOF in stdin by pressing Ctrl+Z?
If so then what are some of the uses of EOF in stdin? I guess it tells the program to continue reading until the user invokes end of file? is this it?
Thank you

so if there is NOTHING written, End of File, (EOF) is not returned automatically?
No, it's not. It should be sent by the user.
So is it that only the user can invoke EOF in stdin by pressing Ctrl+Z?
Yes, you can set the EOF indicator for stdin with a special key combination you can input in the console, for linux console that is Ctrl+D and for windows it's Ctrl+Z.
If so then what are some of the uses of EOF in stdin? I guess it tells the program to continue reading until the user user invokes end of file? is this it?
The use of it depends on whether you instruct the user to input the EOF explicitly or not, for example, I think python console will tell you something like Press Ctrl+D or type quit() to exit.
And EOF is not necessarily -1 it's a macro and you should always use it to test for the EOF indicator. And more importantly EOF is not a character, it's a special value that indicates that the End Of File indicator is set.
Also, getchar() is equivalent to fgetc(stdin).

In linux bash, if you press CTRL+D, it will generate EOF.
In Windows, the equivalent is CTRL+Z
So, no, if nothing written to the terminal, that does not generate EOF automatically. The scanning function is in wait state then. So, without having any other inputs, in wait state, if CTRL+D is pressed, the key press is translated [by the terminal driver] to EOF.Note
Usually, once you key in some value and press the ENTER key, the scannning function starts scanning. To feed an input for producing EOF, you need to press CTRL+D.
Related: Please reaed the wiki entry for EOF
Note: With thanks to Mr Drew for the clarification.

stdin is a stream, data is not available until the user presses some keys. A file on the disk already has (a fixed amount of) content.
When reading from stdin, if getchar() doesn't wait for the user to input something then the program will always get EOF. That will make it impossible to use stdin as an input file.
Because getchar() waits for the user to input something there is no way to signal the input completed; that's why the operating systems provide a combination of keys that have this special meaning when they are pressed on the console.
Windows uses CtrlZ and Unix-like OSes (including OSX) use CtrlD for this purpose.

The file stdin is not always the user typing on the keyboard. If you redirect input to your program, it can be just a normal file.
program.exe <input-from-file.txt
What may be confusing you is that no giving input into a console window does not mark the end of the input. But think it the other way round: how could a user respond so quickly that the program would not terminate before it if the console would not do some buffering for the user? After pressing Enter the user says this is a line of input. In other words: a program running in a console window always waits for the next input to come.
Most programs define a special phrase to end a console session. You probably know exit.

Related

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

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.
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.
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.

How getchar() works when it is used as condition in while loop

I cant understand how the following code really works.
int main() {
char ch;
while((ch=getchar())!='\n')
{
printf("test\n");
}
return 0;
}
Lets say we give as an input "aaa". Then we get the word "test" as an output in 3 seperate lines.
Now my question is, for the first letter that we type, 'a', does the program goes inside the while loop and remembers that it has to print something when the '\n' character is entered? Does it store the characters somewhere and then traverses them and executes the body of the while loop? Im lost.
There are many layers between the user writing input into a terminal, and your program receiving that input.
Typically the terminal itself have a buffer, which is flushed and sent to the operating system when the user presses the Enter key (together with a newline from the Enter key itself).
The operating system will have some internal buffers where the input is stored until the application reads it.
Then in your program the getchar function itself reads from stdin which is usually also buffered, and the characters returned by getchar are taken one by one from that stdin buffer.
And as mentioned in a comment to your question, note that getchar returns an int, which is really important if you ever want to compare what it returns against EOF (which is an int constant).
And you really should compare against EOF, otherwise you won't detect if there's an error or the user presses the "end-of-file" key sequence (Ctrl-D on POSIX systems like Linux or macOS, or Ctrl-Z on Windows).
What you see is due to the I/O line buffering.
The getchar() functions doesn't receive any input until you press the enter. This add the \n completing the line.
Only at this point the OS will start to feed characters to the getchar(), that for each input different from \n prints the test message.
Apparently the printout is done together after you press the enter.
You can change this behavior by modifying the buffering mode with the function setvbuf(). Setting the mode as _IONBF you can force the stream as unbuffered, giving back each character as it is pressed on the keyboard (or at least on an *nix system, MS is not so compliant).

How does scanf determine whether to block?

When I redirect a file to stdin using MyProgram < cl.txt command from the command line, scanfs doesn't wait me to press Enter.
But when I use scanf in my program without doing so, it does block until enter key is pressed.
How exactly does it determine that? Does it keep reading the stream until \n is encountered? or does it really wait me to press a key?
When I don't write anything and press Enter it doesn't stop blocking either and keeps asking. I'm really confused.
Does it keep reading the stream until '\n' is encountered?
Normally stdin is in line buffering mode (_IOLBF, see setvbuf). Whenever the buffer is empty, stdin waits for a whole new line to be entered, i.e. waits until you press Enter and \n is inserted into the buffer:
On Input, the buffer is filled up to the next newline character when an input operation is requested and the buffer is empty.
Note: the console (terminal) is most often implementing a buffering on its own, and does not send any data to the stream until you press Enter - this allows you to edit the data (like use delete, and backspace keys) before you send them to the application. Therefore even with no buffering on the stdin side (like when you perform setvbuf(stdin, NULL, _IONBF, 0)), the scanf may still wait until the Enter is pressed.
scanf is just reading from its input stream. If the input stream is a pipe, and the other end of that pipe is associated with a tty (which is usually the case if you are interactively entering data by pressing keys on a keyboard), scanf will return as soon as it reads data that completes its format string (or fails to match it). The tty, however, if it is in cooked mode (which is the default, and unless you make some effort to put the tty into raw mode, you should assume it is cooking what you type), will not write any data into the pipe until you hit return.
In other words, it's not your scanf that is blocking. (Well, it is blocking, but it's not the source of the experienced delay.) Rather, the tty driver is waiting for you to hit return before it passes any data to your program.
When you call scanf it immediately waits for input. in your first example, input is provided in the form of "cl.txt". In your second example, no input is provided until you press a key. Synchronous IO will block on its executing thread until it receives input.

Why does getchar() recognize EOF only in the beginning of a line?

This example is from the K&R book
#include<stdio.h>
main()
{
long nc;
nc = 0;
while(getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
Could you explain me why it works that way. Thanks.
^Z^Z doesn't work either (unless it's in the beginning of a line)
Traditional UNIX interpretation of tty EOF character is to make blocking read return after reading whatever is buffered inside a cooked tty line buffer. In the start of a new line, it means read returning 0 (reading zero bytes), and incidentally, 0-sized read is how the end of file condition on ordinary files is detected.
That's why the first EOF in the middle of a line just forces the beginning of the line to be read, not making C runtime library detect an end of file. Two EOF characters in a row produce 0-sized read, because the second one forces an empty buffer to be read by an application.
$ cat
foo[press ^D]foo <=== after ^D, input printed back before EOL, despite cooked mode. No EOF detected
foo[press ^D]foo[press ^D] <=== after first ^D, input printed back, and on second ^D, cat detects EOF
$ cat
Some first line<CR> <=== input
Some first line <=== the line is read and printed
[press ^D] <=== at line start, ^D forces 0-sized read to happen, cat detects EOF
I assume that your C runtime library imitates the semantics described above (there is no special handling of ^Z at the level of kernel32 calls, let alone system calls, on Windows). That's why it would probably detect EOF after ^Z^Z even in the middle of an input line.
The program will read EOF only at the actual end of the input. If your terminal/OS/whatever only permit files to end at the start of a line then that's where you'll find them. I believe this is a throw-back to old-fashioned terminals where data was only transmitted a line at a time (for all I know it goes back to punched card readers).
Try reading your data from a file that you've preprepared with an EOF mid-line. You may even find that some editors make this difficult! Your program should work fine with that as input.
EOF indicates "end of file". A newline (which is what happens when you press enter) isn't the end of a file, it's the end of a line, so a newline doesn't terminate this loop.
Depending on the operating system, EOF character will only work if it's the first character on a line, i.e. the first character after an Enter. Since console input is often line-oriented, the system may also not recognize the EOF character until after you've followed it up with an Enter.
I happened to have the same question as you. When I want to end the function getchar(), I have to enter 2 EOF or enter a <ENTER> plus a EOF.
And here's an easier answer I searched about this question:
If there is characters entering in the terminal, EOF will play the role as stopping this entering, which will arouse a new turn of entering; while, if there is no entering happening, or in another word, when the getchar() is waiting for a new enter(such as you've just finished entering or a EOF), the EOF you are about to enter now equals "end of file", which will lead the program stop executing the function getchar().
PS: the question happens when you are using getchar(). I think this answer is easier to understand, but maybe not for you since it is translated from Chinese...

Read input from console in OSX

I'm using scanf() to read user input on terminal in a console application. scanf waits until the user hits the return key to read. Is there a way to read the user input on each keystroke?
The usual way would be to use the getch function from (the Mac port of) ncurses.
Note that while getchar reads a single character, it still normally does buffered reading, so you need to press 'return'/'enter' before it'll return.
getch() returns the character stream from stdin as it is typed.
char c = getchar();
It should do the trick.

Resources