Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

how to flush stdin buffer between two scanf?

Hi,

I think this is a beginner-level question. Much appreciate your answers in advance!

The following is my simple C-code:

#include <stdio.h># include <string.h>
void main(void)
{
  char sex; 
  char area;
  
  do
  {
    printf("Please select your area (QLD, NSW, ACT, SA, WA, NT or TAS): ");
    scanf("%s", area);
  }  while(strcmp(area,"QLD")!= 0 && strcmp(area,"NSW")!= 0 && strcmp(area,"ACT")!= 0 &&
        strcmp(area,"SA")!= 0 && strcmp(area,"WA")!= 0 && strcmp(area,"NT")!= 0 && strcmp(area,"TAS")!= 0);
  do
  {
      printf("Please enter your sex (M/F): ");
      scanf("%c", &sex);    
  }    while(sex != 'M' && sex != 'F') ;
}

This problem is: the prompt "Please senter your sex (M/F)" always gets printed twice on the screen before a value is entered. I realized it is because when I enter the string for area, the last character ENTER gets stored in stdin buffer and is treated as the value for sex. To make the program function as expected, I have to insert another scanf("%c", &sex") between the two do-while loops to clear the stdin buffer.

I tried to find a neater way to do this. Some online results suggest fflush(stdin) is not a good thing to do.

Is there a better way to clear the stdin buffer, or a better coding structure to avoid such problem completely?

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I myself find another way to circumvent this problem. That is to declare sex as a string, that is char sex[2], as shown below:

    #include <stdio.h>
    # include <string.h>
    void main(void)
    {
      char sex; 
      char area;
      
      do
      {
        printf("Please select your area (QLD, NSW, ACT, SA, WA, NT or TAS): ");
        scanf("%s", area);
      }  while(strcmp(area,"QLD")!= 0 && strcmp(area,"NSW")!= 0 && strcmp(area,"ACT")!= 0 &&
            strcmp(area,"SA")!= 0 && strcmp(area,"WA")!= 0 && strcmp(area,"NT")!= 0 && strcmp(area,"TAS")!= 0);
    do  
    {
      	printf("Please enter your sex (M/F): ");
      	scanf("%s",sex);    
      }while(strcmp(sex,"M")!= 0 && strcmp(sex,"F")!= 0);	
    }

    In this way, a single ENTER character, even it is stored in sex, will not make strcmp TRUE and activate the do-while loop twice. And we don't need to clear stdin buffer.

    But this seems a waste. Every case for which we only need a character now needs to be replaced by a two-character string. Is there a better way?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Any if I now type "yes" the program will crash.

    The simple solution is never to use scanf, and especially never with a %s format.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you for your reply,dsl!

    Do you imply I should always use cin and cout instead of scanf and printf? What if I have to write some code in a pure C environment?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    AARGGGG cin/cout are an order of magnitude worse.

    Not quite as bad as the stringstream classes though.

    Use fgets(buf, sizeof buf, stdin) to read a line and parse it yourself - in this case that just means that you need to allow for the trailinf '\n'.

    Lighter weight is to use read(0, buf, sizeof buf) - but that relies on the device drive code to generate lines (which it may not do).