How to clear input buffer in C?

2018-12-31 02:53发布

I have the following program:

int main(int argc, char *argv[])
{
  char ch1, ch2;
  printf("Input the first character:"); // Line 1
  scanf("%c", &ch1); 
  printf("Input the second character:"); // Line 2
  ch2 = getchar();

  printf("ch1=%c, ASCII code = %d\n", ch1, ch1);
  printf("ch2=%c, ASCII code = %d\n", ch2, ch2);

  system("PAUSE");  
  return 0;
}

As the author of the above code have explained: The program will not work properly because at Line 1, when the user presses Enter, it will leave in the input buffer 2 character: Enter key (ASCII code 13) and \n (ASCII code 10). Therefore, at Line 2, it will read the \n and will not wait for the user to enter a character.

OK, I got this. But my first question is: Why the second getchar() (ch2 = getchar();) does not read the Enter key (13), rather than \n character?

Next, the author proposed 2 ways to solve such probrems:

  1. use fflush()

  2. write a function like this:

    void
    clear (void)
    {    
      while ( getchar() != '\n' );
    }
    

This code worked actually. But I cannot explain myself how it works? Because in the while statement, we use getchar() != '\n', that means read any single character except '\n'? if so, in the input buffer still remains the '\n' character?

标签: c buffer
11条回答
与君花间醉酒
2楼-- · 2018-12-31 03:09

you can try

scanf("%c%*c", &ch1);

where %*c accepts and ignores the newline

one more method instead of fflush(stdin) which invokes undefined behaviour you can write

while((getchar())!='\n');

don't forget the semicolon after while loop

查看更多
唯独是你
3楼-- · 2018-12-31 03:11

A portable way to clear up to the end of a line that you've already tried to read partially is:

int c;

while ( (c = getchar()) != '\n' && c != EOF ) { }

This reads and discards characters until it gets \n which signals the end of the file. It also checks against EOF in case the input stream gets closed before the end of the line. The type of c must be int (or larger) in order to be able to hold the value EOF.

There is no portable way to find out if there are any more lines after the current line (if there aren't, then getchar will block for input).

查看更多
梦寄多情
4楼-- · 2018-12-31 03:11
char choice;
do{
    printf("\n *");
    printf("\n Do you want to continue? (y/n) ");
    choice = getchar();
    if(getchar() != '\n'){
        fflush(stdin);
    }
}while( choice != 'n' );
查看更多
谁念西风独自凉
5楼-- · 2018-12-31 03:14

Short, portable and declared in stdio.h

stdin = freopen(NULL,"r",stdin);

Doesn't get hung in an infinite loop when there is nothing on stdin to flush like the following well know line:

while ((c = getchar()) != '\n' && c != EOF) { }

A little expensive so don't use it in a program that needs to repeatedly clear the buffer.

Stole from a coworker :)

查看更多
牵手、夕阳
6楼-- · 2018-12-31 03:15

The lines:

int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
    ;

doesn't read only the characters before the linefeed ('\n'). It reads all the characters in the stream (and discards them) up to and including the next linefeed (or EOF is encountered). For the test to be true, it has to read the linefeed first; so when the loop stops, the linefeed was the last character read, but it has been read.

As for why it reads a linefeed instead of a carriage return, that's because the system has translated the return to a linefeed. When enter is pressed, that signals the end of the line... but the stream contains a line feed instead since that's the normal end-of-line marker for the system. That might be platform dependent.

Also, using fflush() on an input stream doesn't work on all platforms; for example it doesn't generally work on Linux.

查看更多
低头抚发
7楼-- · 2018-12-31 03:19

You can do it (also) this way:

fseek(stdin,0,SEEK_END);
查看更多
登录 后发表回答