Link to home
Start Free TrialLog in
Avatar of Sandeep Sood
Sandeep SoodFlag for India

asked on

problem in using scanf

Hello experts,
i have a small problem in getting input of variable of char type after getting input of variable of int. It does not wait for char input.
Please look at the code given below.
Thanks.


main( )
{
      char choice;
      int num1, num2, choice;    
      float ans;
      clrscr();

      printf("Pls enter two numbers  ");
      scanf("%d",&num1);
      scanf("%d", &num2);

      printf("\n*  *  * M E N U *  *   *  *\n");
      printf("\n1. Enter + to Add\n2. Enter - to Subtract \n3. Enter x to Multiply");

      printf("\n\n\tEnter Your Chioce : ");

      scanf("%c",&choice);         /* PROBLEM : DOES NOT WAIT FOR THIS */
      /* or choice=getchar();*/
      /* choice = getche(); */

      switch(choice)
      {
            case '+' :
                  ans=num1 + num2;
                  printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                  break ;

            case '-' :
                  ans=num1 - num2;
                  printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                  break ;            
      }
}
Avatar of Infinity08
Infinity08
Flag of Belgium image

>>       scanf("%c",&choice);         /* PROBLEM : DOES NOT WAIT FOR THIS */

The scanf is reading whatever character is still on the input stream. And there is likely a newline character there (because you pressed ENTER after the previous input).

To avoid this, it's better to use fgets to read the input one line at a time into a line buffer, and then use sscanf to get whatever data you need out of that line buffer.

For example :
char line[256] = { 0 };                     /* the line buffer */

int value = 0;
fprintf(stdout, "Give an int value : ");
if (fgets(line, sizeof(line), stdin)) {
    sscanf(line, "%d", &value);
}
else {
    fprintf(stderr, "ERROR : failed reading input !");
    /* handle this error appropriately */
}

/* any reads from stdin should be replaced by something like the above */

Open in new window

Avatar of phoffric
phoffric

I would replace this
      char choice;
      int num1, num2, choice;
with below since you don't want to define choice twice.
      char choice;
      int num1, num2;     

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of shajithchandran
shajithchandran
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
main( )
{
      char choice;
      int  num1, num2, choice;    
      float ans;
      clrscr();

      printf("Pls  enter two numbers  ");
      scanf("%d",&num1);
      scanf("%d",  &num2);

      printf("\n*  *  * M E N U *  *   *  *\n");
      printf("\n1.  Enter + to Add\n2. Enter - to Subtract \n3. Enter x to Multiply");

      printf("\n\n\tEnter  Your Chioce : ");

      scanf("%c",&choice);         /*  PROBLEM : DOES NOT WAIT FOR THIS */
      /* or choice=getchar();*/
      /*  choice = getche(); */

      switch(choice)
      {
             case '+' :
                  ans=num1 + num2;
                   printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                   break  ;

            case '-' :
                  ans=num1 - num2;
                   printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                   break  ;            
      }
getchar(); //add this to make compiler wait
}

Avatar of Sandeep Sood

ASKER

Thanks Infinity08 for your reply, but its acually very complex. Kindly suggest some simple solution.

Thanks phoffric, for your suggestion, but that was actually at typo.

Thanks shajithchandran, i am trying it.
will be back.

You have to flush the input stream. This can be done by the flushall().
Use the following code:


void main( )
{
        char choice;
        int num1, num2;
        // choice;
        float ans;
        clrscr();

        printf("Pls enter two numbers  ");
        scanf("%d",&num1);
        scanf("%d", &num2);

        printf("\n*  *  * M E N U *  *   *  *\n");
        printf("\n1. Enter + to Add\n2. Enter - to Subtract \n3. Enter x to Multiply");

        printf("\n\n\tEnter Your Chioce : ");
        flushall();//flush input stream
        scanf("%c",&choice);         /* PROBLEM : DOES NOT WAIT FOR THIS */
        /* or choice=getchar();*/
        /* choice = getche(); */

        switch(choice)
        {
                  case '+' :
                          ans=num1 + num2;
                          printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                          break ;

                  case '-' :
                          ans=num1 - num2;
                          printf("\n %d %c %d =  %f ", num1, choice, num2, ans);
                          break ;
        }
getch();//add this to make compiler wait
}
>> give a space before %c..
This works and allows even extra white-spaces and returns to be skipped.
ashishgamre11, i tried fflush() but it didnt work.
will try flushall() also.
Thanks.
>> Thanks Infinity08 for your reply, but its acually very complex. Kindly suggest some simple solution.

It's not really complex. If you take away the error handling (which you shouldn't in any case), you just keep :

        fgets(line, sizeof(line), stdin);
        sscanf(line, "%d", &value);

instead of this :

        scanf("%d", &value);

It's a simple matter of replacing all your scanf's with the fgets-sscanf combination.

Trust me, doing this will avoid you so many headaches, it's worth the trouble to learn to do this early.

It's a lot more robust, and avoids a lot of problems.
Don't use fflush on stdin (or any input stream for that matter). It has undefined behavior. Only use it for output streams.
flushall is non-standard, and should not be used either.
Add getchar after scanf like this,


scanf("%c",&choice); 
getchar();

Open in new window

Thanks infinity for your reply.
i have tried,
Solution given by shajithchandran, i.e use one space before %c is working
and also solution given by ashishgamre11 to use flushall() is also wokring.

>> Don't use fflush on stdin (or any input stream for that matter). It has undefined behavior. Only use it for output streams

is flushall( )  safe to use ?

Thanks.
Infinity08,  ok, i was late in posting.
you already replied this.
Thanks.

Since shajithchandran gave a solution first, so points go to him.

I am learning many new things from you experts !
Thanks All !
Thanks Experts-Exhange !!
>> Solution given by shajithchandran, i.e use one space before %c is working

It works, because it skips whitespace, yes.

The approach I showed will solve that problem and several others too though (like extra input and corrupted streams eg.), so I still recommend using it over any other approach !


>> and also solution given by ashishgamre11 to use flushall() is also wokring.
>> is flushall( )  safe to use ?

It's non-standard. If you're not worrying about portability, you have to check your compiler documentation to see what its behavior is.
BUT, since this is to learn C, you should not be using it, since it's not part of the C language.


>> Since shajithchandran gave a solution first, so points go to him.

I'd say that I was first, but that doesn't matter lol ;)

I trust that at some point in the future (and probably very soon), you'll encounter more problems with reading input. I hope that at that point, you'll think of what I said, use my approach, and live happily ever after ;)

This technique is one of the most useful lessons I learned over all the years I've been using C, but it's apparently the hardest to convince people with lol. So be it.
Infinity08, i was looking for a very simple answer so i liked solution given by shajithchandran.
There is no doubt that the solution provided by you is better, and certainly i will try to adapt to use it.
Sorry for the points, already given.

>>This technique is one of the most useful lessons I learned over all the years I've been using C, but it's apparently the hardest to convince people with lol. So be it.

Thanks a lot for teaching the things so easily, that u learned over the years.

Hats Off !!

Thanks a lot.
Don't worry, thetechguy. The question has been closed just fine. Do keep the technique in mind though, because if you continue with C, you'll be happy you know it ;)