1

I have some problem with the loop I trying to do. My code will prompt user for the value 1, 2 to do something, and 3 to exit. When I try to add the check for the input if it is not integer the loop will just loop non stop. I wonder is my if( !input) is wrongly used here? Can someone guide me? thanks.

do
{
    printf ("Input no\n");
    scanf ("%d", &input);

    if (input)
    {
        if ( input == 1)
        {
            printf ("do wat u wan if is 1\n");
        }

        if ( input == 2)
        {
               printf ("do wat u wan if is 2\n");
        }
    }

    else if (!input)
    {
        printf("error\n");
    }
}
while(input !=3 );

if ( input == 3)
{
    printf ("exiting\n");
}
leo
  • 11
  • 2
  • This is because of `scanf`. If you have "%d" and you enter something else that a digit `scanf` acts like this. – Jabberwocky Oct 22 '14 at 16:30
  • Here, `scanf` directive just fails. See this post: http://stackoverflow.com/questions/20655381/what-happens-if-c-tries-to-scan-character-in-integer-variable – Ludovic Feltz Oct 22 '14 at 16:30
  • BTW: `if ( input == 3)` is not necessary, because when the program gets there, `input` is forcibly `3`. – Jabberwocky Oct 22 '14 at 16:31

4 Answers4

1

You have to clear the input buffer if scanf() doesn't read correctly.

int res = scanf ("%d", &input);
if( res == 0 )
{
    int clear = 0 ;
    while( ( clear = getchar() ) != EOF && clear != '\n') ;
}

In this case if res is not 1, scanf didn't read an integer and you have some characters left in stdin.

Also set input to 0 before passing it to scanf(), so that your if statement can handle the result correctly.

2501
  • 25,460
  • 4
  • 47
  • 87
1
do
{
   printf ("Input no\n");
   if(scanf ("%d", &input)==1) //if `scanf` is successfull
      {
        if ( input == 1)
        {
            printf ("do wat u wan if is 1\n");
        }
         else if ( input == 2)
        {
               printf ("do wat u wan if is 2\n");
        }        
     }else //scanning an integer failed
     {
       printf("Invalid input(non-numeric value entered). Breaking loop...\n");
      scanf("%*s"); //discarding previous input
      break; //or use `continue;` for looping once more
      }
  }
while(input !=3 );
printf ("exited loop\n");

The above code will do what you want and I've also removed uneccessary stuff from it.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
0

The problem here is not your loop, but the format specifier in your call to scanf, if you call scanf with %d it expects an integer, if it doesn't receive one it will not be happy. Try calling scanf with %c instead and convert the read character to the corresponding integer value, this fixes your problem and should be managable to do by you.

simon
  • 1,095
  • 6
  • 11
  • I see. so if I were to use %c (using char to store the choice value) then how can I check the input whether character or integer? I have tried isdigit() and it do not work. – leo Oct 22 '14 at 16:45
  • @leo see my answer how to use `isdigit()` – rubber boots Oct 22 '14 at 17:12
  • You can do it like this @leo, since you only care if it is between one and three you can use the ASCII-table (http://www.asciitable.com/) to translate the numbers as we can see in the table I linked, the character 1 ('1') has the value 49, so to get the integer value 1 you just do "if '1' - 49 == 0", "if '2' - 50 == 0", etc. An even easier way to do it is to just do "if input == '1'", this way you don't even have to bother with the ASCII-table – simon Oct 22 '14 at 18:06
0

Change the first part of your code to:

...
int input;
do
{
    char line[256];
    printf("Input no\n");
    fgets(line, sizeof(line), stdin);
    sscanf(line, "%d", &input);
    if (input) 
    ...

Never ever use scanf! This is almost unusable. It may lack consistent behavior across compilers.

The problem is: if scanf() encounters an item which is not usable according to the format %d, the item will stay in the input buffer forever. You can avoid this by using %s and converting afterwards. Better: on line-input use line-reading (gets()/fgets())

If you want to detect digits/non-digits in the incoming string, you could use the isdigit() function from <ctype.h>. Your code would end up in the following form:

int input;
do {
    char line[256];
    printf("Input no\n");
    fgets(line, sizeof(line), stdin);
    if (isdigit(line[0])) {                /* check if first char is a number */
        sscanf(line, "%d", &input);        /* scan this number from string */
        if (input == 1)  {
           printf("do wat u wan if is 1\n");
        }
        if (input == 2) {
           printf("do wat u wan if is 2\n");
        }
    }
    else {
        input = 0;                        /* reset input to any value != 3 */
        printf("error\n");
    }
} while (input != 3);

Don't forget to #include <ctype.h>.

rubber boots
  • 14,924
  • 5
  • 33
  • 44