9

Here is my code. I run it in ubuntu with terminal. when I type (a CtrlD) in terminal, the program didn't stop but continued to wait for my input.

Isn't CtrlD equal to EOF in unix?

Thank you.

#include<stdio.h>

main() {
    int d;
    while(d=getchar()!=EOF) {
        printf("\"getchar()!=EOF\" result is %d\n", d);
        printf("EOF:%d\n", EOF);
    }
        printf("\"getchar()!=EOF\" result is %d\n", d);
}
Vukašin Manojlović
  • 2,645
  • 2
  • 21
  • 26
Sam
  • 964
  • 3
  • 11
  • 24
  • 1
    That's not recursion. It's just an infinite loop until you EOL the input. Recursion = function calling itself directly or after some other intermediate number of steps. – Marc B Aug 14 '12 at 00:52
  • Compiled that with gcc, hitting `^D` stopped the loop for me. – Jon Lin Aug 14 '12 at 01:02
  • @JonLin Simply input ^D .It works for me,too. However, when the input is (a^D);the loop didn't stop. – Sam Aug 14 '12 at 01:11
  • @MarcB I made a stupid mistake. Thank you for your help. – Sam Aug 14 '12 at 01:12

2 Answers2

12

EOF is not a character. The EOF is a macro that getchar() returns when it reaches the end of input or encounters some kind of error. The ^D is not "an EOF character". What's happening under linux when you hit ^D on a line by itself is that it closes the stream, and the getchar() call reaches the end of input and returns the EOF macro. If you type ^D somewhere in the middle of a line, the stream isn't closed, so getchar() returns values that it read and your loop doesn't exit.

See the stdio section of the C faq for a better description.

Additionally:

On modern systems, it does not reflect any actual end-of-file character stored in a file; it is a signal that no more characters are available.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • 1
    I carefully read the website. In my opinion, if I type `^D` somewhere in the middle of a line, bash will tackle `^D`. As a result, the C program didn't get a command to close the stream. If I type `^D` in a single line, the C program will get the correct command. Am I right? – Sam Aug 14 '12 at 01:34
  • 2
    @qingfeng There's a bit more about `^D` here: http://www.c-faq.com/stdio/eofval.html But yeah, the stream won't get closed unless it's on a line by itself. Short explanation here: http://stackoverflow.com/a/1516177/851273 – Jon Lin Aug 14 '12 at 01:38
  • 8
    When the terminal is in canonical mode, lines aren't transmitted over the tty device until you press enter. Pressing the configured EOF key (^D by default) causes the data to be immediately transmitted and any `read` waiting on it to return with the number of characters available. If the line already has data on it, this will be a normal, non-zero-length read. If the line is empty, this will result in a zero-length read, which is the *definition* of end-of-file status on a file descriptor. Thus the stdio layer will interpret it as EOF status. – R.. GitHub STOP HELPING ICE Aug 14 '12 at 02:06
  • @qingfeng: bash has nothing to do with it; the input is being handled by the program that's currently running. – Keith Thompson Dec 03 '13 at 00:39
  • @R.., Your comment should be an answer, and it should be the top answer. It's getting hard to find the full "behind-the-scenes" information these days... – Neowizard Mar 17 '15 at 06:22
  • Note that the stream does not get closed when you indicate EOF; it goes into the error state, but that can be cleared with `clearerr()`, and you can try again. If the input device is a terminal, you may get new input. If you opened the file, you still need to close it (though exiting the program will also close it). – Jonathan Leffler Jun 22 '16 at 05:56
6

In addition to Jon Lin's answer about EOF, I am not sure the code you wrote is what you intended. If you want to see the value returned from getchar in the variable d, you need to change your while statement to:

    while((d=getchar())!=EOF) {

This is because the inequality operator has higher precedence than assignment. So, in your code, d would always be either 0 or 1.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • It's very kind of you to be so meticulous. But I just want to verify that the expression `d=getchar()!=EOF` is 0 or 1. – Sam Aug 14 '12 at 01:40
  • @Sam: You can make it clear that you are assigning the result of the comparison by writing: `while ((d = (getchar() != EOF)) != 0)` or as `while ((d = (getchar() != EOF)))` so that the compiler won't throw warnings at you. The more common alternative is `while ((d = getchar()) != EOF)` which assigns the result of `getchar()` to `d` and then compares it with EOF. That to avoids compiler warnings. Many modern compilers will generate a warning for what you wrote. – Jonathan Leffler Mar 25 '17 at 00:02