Beginners find that the scanf function behaves strangely when you input a character when scanf expects an integer or float. When used inside a loop (taking options), it loops infinitely. Here is a short post which explains what it happens, and how to solve this,

For example consider the simple code below describing the situation of scanf in a loop.

#include <stdio.h>

int main (void)
{
  int x;

  do
  {
    printf ("\n\nEnter a number: ");
    scanf ("%d", &x);
    printf ("\nEntered number: %d", x);
  } while (x != -1);


  printf ("\n");
  return 0;
}

Enter an integer it will keep on asking for integer while you do not enter -1. When you enter a character it will go to an infinite loop.

This is because the scanf did not match an integer in stdin, and that is why it did not read the characters from stdin, which still remain in the input buffer, and the call returned. In the next iteration it will again encounter the unmatched characters in the buffer from the previous iteration and fail matching again and go into another iteration, where it will again fail for the same cause and like this it will infinitely loop trying to match the same set of characters and fail.

To detect if scanf has matched the input or not, check the return value of scanf. Check out what the manual has to say about the return value:

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

Therefore check the return value of scanf to know how many parameters has been matched. In the above case check if it returns 1 or not. Check the fixed code below:

#include <stdio.h>

int main (void)
{
  int x, retval;

  do
  {
    printf ("\n\nEnter a number: ");
    retval = scanf ("%d", &x);
    printf ("retval = %d", retval);
    if (retval != 1)
    {
      printf ("\nEnter again");
      scanf ("%*c");
      continue;
    }
    printf ("\nEntered number: %d", x);
  } while (x != -1);


  printf ("\n");
  return 0;
}

Now if you enter a character in the input, scanf will not match it and return 0 (as none was matched). But we still have the unmatched character in the stdin buffer. Depending on the need we can handle this in different ways. In the above code the next character in the buffer is simply discarded. The * in “%*c” , is the assignment-suppression character. This simply tells that to read the next character from the stdin, but discard it. There is no need to associate corresponding argument in the scanf argument list. Therefore this line simple will read the next character from the standard input and discard it, reveiling the next character in the stdin and will make progress instead of looping infinitely.

In a similar way you can detect the presence of more than one input elements in a scanf as per needed. Some related content could be found in this post:

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s