Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getchar() and buffer order

Tags:

c

getchar

A beginner's C book I'm reading has me confused with respect to getchar() and buffer order (especially as it relates to newline). It says,

Getting rid of the Enter keypress is a problem that all beginning C programmers must face. Consider the following segment of a program:

printf("What are your two initials?\n");
firstInit = getchar();
lastInit = getchar();

You would think that if the user typed GT, the G would go in the variable firstInit and the T would go in lastInit, but that's not what happens. The first getchar() doesn't finish until the user presses Enter because the G was going to the buffer. Only when the user presses Enter does the G leave the buffer and go to the program—but then the Enter is still on the buffer! Therefore, the second getchar() sends that Enter (\n) to lastInit. The T is still left for a subsequent getchar() (if there is one).

First, I don't understand the author's explanation as to why \n goes to lastInit rather than the T. I guess because I'm visualizing the buffer as “first in first out”. Either way I don't understand the logic behind the order the author is presenting—if the user enters G, then T, then Enter, how is it that the G is captured by the first getchar(), the Enter (newline) is captured by the second getchar(), and the T is captured by the third getchar()? Puzzling.

Second, I tried this myself (Ubuntu 14.04 running on VMWare under Windows 8.1, text editor Code::Blocks, compiler gcc), and I got the exact common-sense result that the author says doesn't happen!: The G goes to firstInit and the T goes to lastInit. Here is my code:

#include <stdio.h>

main()
{
  char firstInit;
  char lastInit;

  printf("What are your two initials?\n");

  firstInit = getchar();
  lastInit = getchar();

  printf("Your first initial is '%c' and ", firstInit);
  printf("your last initial is '%c'.", lastInit);

  return 0;
}

And the output is:

What are your two initials?
GT
Your first initial is 'G' and your last initial is 'T'.

I also created a follow-up program, which seems to confirm that newline comes out of the buffer last:

main()
{
  char firstInit;
  char lastInit;
  int newline;

  printf("What are your two initials?\n");

  firstInit = getchar();
  lastInit = getchar();
  newline = getchar();

  printf("Your first initial is '%c' and ", firstInit);
  printf("your last initial is '%c'.", lastInit);
  printf("\nNewline, ASCII %d, comes next.", newline);

  return 0;
}

And the output is:

What are your two initials?
GT
Your first initial is 'G' and your last initial is 'T'.
Newline, ASCII 10, comes next.

So am I missing something here or is the author wrong? (or is this compiler-dependent—even though the author didn't say so)?

Book: C Programming Absolute Beginner's Guide, 3rd edition, Greg Perry, ©2014, Ubuntu 14.04, gcc compiler version 4.8.4

like image 823
yroc Avatar asked Aug 03 '15 16:08

yroc


2 Answers

The author is describing the scenario where the user types "G<enter>T<enter>".

like image 85
David Schwartz Avatar answered Oct 11 '22 13:10

David Schwartz


This is a different example. The menu loop will iterate twice for each entered choice of 1, 2 or 3.
Remove the comment, //, from //while ( ( getchar ( ) != '\n')) {} and the buffer will be cleared after each entry and the menu will loop only once per entry.

#include <stdio.h>

int main()
{
    char *menu[] = { "1. first", "2. second", "3. third", "4. Exit"};
    int choice = 0;
    int each = 0;

    do {
        for ( each = 0; each < 4; each++) {
            printf ( "%s\n", menu[each]);
        }
        printf ( "\tenter choice 1-4\n");
        choice = getchar ( );
        //clear the buffer
        //while ( ( getchar ( ) != '\n')) {}
        printf ( "you entered %d %c\n", choice, choice);
    } while ( choice != '4');
    return 0;
}
like image 40
user3121023 Avatar answered Oct 11 '22 13:10

user3121023