Habib Kazemi
Habib Kazemi

Reputation: 2190

confusing with buffer and EOF and getchar

I tested lot's of situations with getchar() and putchar() and '\n' and EOF (in Visual Studio) to understand better how buffering and getchar works.

If my code

int c;
printf("Enter character\n");
/* 1 - number for explaining steps */
c = getchar();
putchar(c);

/* 2 */
c = getchar();
putchar(c);

printf("hi");

In this code if I enter the character a and press Enter, it will show

 a
 hi

This means that when I when press enter the '\n' will be saved in the buffer too, and then the first item in the buffer (a) goes to the first c=getchar() and a is printed; then the second item in the buffer (\n) goes to the second c=getchar() and prints the new line.

I conclude that '\n' is saved in the buffer and it's not the result of the command's ability to go to a new line when pressing enter because I tested another code for this:

while ((c = getchar()) != '\n')
    putchar(c);
printf("hi");

In this code when I typed a and press enter it prints ahi and new line doesn't print it means that when a passed to getchar(), putchar() prints it then when getchar() gets the '\n', the loop terminated and putchar() inside the loop doesn't print the new line so the command is not the reason for the new line.

Now I want to test another code:

  int c;
  while ((c = getchar()) != EOF)
    putchar(c);
  printf("hi");
  return 0;

In this one if I pass it abc and the signal of EOF (in my system ^Z (Ctrl+Z)) it will show abc->. If we look at it like the previous code: abc-1(or every thing else shows eof)'\n' should have been saved in the buffer and first a go to the first getchar (first time loop works) the b passes to second getchar then c passes to the third — and then -1should have been passed to c=getchar() and it's against the condition and loop should terminate.

However, instead it prints -> and loop continued and new line (the last item in the buffer) doesn't print. Instead when I just ctr +z when c=getchar() reads the EOF sign from the buffer the loop terminated and new line printed so why it prints the new line? It reads the EOF and it should not read anything else in the buffer in this situation.

Upvotes: 1

Views: 1182

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753805

Your outline of how the input reads first a and then the newline in the first example is basically correct. Newline is a perfectly normal character as far as getchar() is concerned; indeed, there are no abnormal characters. getchar() can return any 8-bit value that fits in char, plus one additional value, known as EOF. That's why its return value must be stored in an int, as you did correctly.

The standard I/O functions return EOF when the underlying read() system calls return 0 bytes available to be read — or when there's an error.

When you type abcControl-Z on Windows (you'd type Control-D instead on Unix), then:

  1. The terminal driver makes the characters currently in its buffer (abc) available to the read() system call.
  2. The read() system call populates the standard I/O buffer with those characters.
  3. The successive getchar() calls return a, b and c.
  4. The next getchar() waits for more input.

This wasn't EOF; it was just flushing the characters on the line to the program. To get the effect of EOF, you'd have to type Control-Z twice in a row after the abc. The first would flush the abc; the second would generate a read() of 0 bytes, indicating EOF.

The terminal driver also makes input available when a newline (Enter) is pressed. If you type Control-Z immediately after typing Enter, all zero of the characters pending input are sent from the terminal to the program, so the read() returns 0, so the standard I/O package reports EOF.

Note that until you hit enter or the EOF indication, you can edit the data in the line with the backspace and other editing options, including deleting all the data. Once you've hit enter or the EOF indication, you can no longer edit the data that was made available to read().

The analogous behaviour occurs on Unix; you type the EOF indication twice to terminate the input mid-line; once to terminate the input at the start of a line.

There are many related questions on Stack Overflow, including these ones:

Upvotes: 2

Related Questions