Search code examples
cgetcharputchar

getchar buffered input, EOF and terminal driver


I'm trying to understand how the terminal driver works in conjunction with getchar. Here are a few sample codes i wrote while reading KandR:

Code 1:

#include <stdio.h>

int main(){

  int c = getchar();
  putchar(c);


  return 0;

}

Code 2:

    #include <stdio.h>

    int main(){

    int c = EOF;

    while((c=getchar()) != EOF){
    printf("%c",c);
    }
    return 0;
}

Code 3: //barebones program that emulates functionality of wc command

    #include <stdio.h>
    #define IN 1
    #define OUT 0

    int main(){
      //nc= number of characters, ns = number of spaces, bl=number of newlines, nw=number of words
      int c = EOF,nc=0,nw=0,ns=0,nl=0, state = OUT;

      while((c=getchar())!=EOF){
        ++nc;
        if(c=='\n'){
          ++nl;
          state = OUT;
        }
        else if(c==' '){
          ++ns;
          state = OUT;
        }

        else{
          if(state == OUT){
          state = IN;
          ++nw;}
        }

      }

      printf("\n%d %d %d %d",nc,nw,ns,nl); 
return 0;
}

I wish to understand when the terminal driver actually hands over the input string to the program. Assume my input is the string "this is a test" and i press enter, then here is how the above mentioned codes work:

code 1: outputs "t" (and the program ends)

code 2: outputs "this is a test", jumps to the next line (because it also outputs the enter i pressed) and waits again for input.

code 3: does not output anything for the above string followed by an enter. I need to press Ctrl+D for the output to be displayed (output is 15 4 3 1)

1) Why in case of code 3 do i need to press Ctrl+D (EOF) explicitly for the input to be sent to my program? To put this in other words, why was my input string sent to my program in case of code 1 and code 2 after i pressed enter? Why didn't it also ask for EOF?

2) Also, in case of code 3, if i do not press enter after the input string, i need to press Ctrl+D twice for the output to be displayed. Why is this the case?

EDIT:

For another input say "TESTING^D", here is how the above codes work:

1) outputs "T" and ends

2) outputs "TESTING" and waits for more input

3) ouputs nothing until another Ctrl+D is pressed. then it outputs 7 1 0 0.

In case of this input, the terminal driver sends the input string to the program when Ctrl+D is received in case of code 1 and code 2. Does that mean /n and Ctrl+D are treated the same way i.e. they both serve as a marker for the terminal driver to send the input to the program? Then why i need to press Ctrl+D twice for the second case?

This http://en.wikipedia.org/wiki/End-of-file says that the driver converts Ctrl+D into an EOF when it is on a newline. But in case of my "TESTING^D" input, it works fine even though the ^D is on the same line as the rest of the input. What can be the possible explanation for this?


Solution

  • General information:

    In case code 2: you also need to do ctrl+D in order to exit.

    In fact EOF is achieved by pressing ctrl+D, so what your while loop condition says:

    1. get input from keyboard
    2. store it in c
    3. if the input was not equal to EOF execute the body of the while loop

    EOF is nothing but the integer -1, and this can be achieved in the terminal by pressing ctrl+D. So taking this example:

    while((c=getchar()) != EOF){
       // execute code
    }
    
    printf("loop has exited because you press ctrl+D");
    

    The condition keeps taking input but stops when you press ctrl+D, then it continue to execute the rest of the code.

    Answering you questions:

    1) Why in case of code 3 do i need to press Ctrl+D (EOF) explicitly for the input to be sent to my program? To put this in other words, why was my input string sent to my program in case of code 1 and code 2 after i pressed enter? Why didn't it also ask for EOF?

    In code 2 and 3 (Not only 3), you need to press Ctrl+D because the while loop stops taking input from keyboard only when it reads EOF. In code 1 you are not looping, so when you enter one or more character, the program will read the characters entered but will store the first one only, then it will print it and terminate the program, so no need for EOF in that case because you are not asking for it anywhere in any condition.

    2) Also, in case of code 3, if i do not press enter after the input string, i need to press Ctrl+D twice for the output to be displayed. Why is this the case?

    If you started typing when the program is expecting input, then after typing at least one character you press ctrl+D, this will tell the program to stop taking input and return the entered characters. After that, if you press ctrl+D again without entering any character before, this will return EOF which will then not satisfy the condition of the while loop and skip to continue executing the rest of the code