0

I have been struggling to figure out a way to enhance the error checking in my simple menu driven C code shown below. The code works fine with the right inputs, but unfortunately it goes in an infinite loop when an incorrect argument is given. Can somebody please help me handle this case?

Here is my code:

#include<stdio.h>

int main()
{
    int choice, num, i;
    unsigned long int fact;
    system("clear");
    do
    {
        printf("1.Factorial\n");
        printf("2.Prime\n");
        printf("3.Odd/Even\n");
        printf("4.Exit\n");
        printf("\nYour choice?");
        scanf("%d",&choice);
        switch(choice)
        {
        case 1:
            printf("\nEnter number:");
            scanf("%d",&num);
            fact = 1;
            for(i=l;i<=num;i++)
                fact=fact*i;
            printf("\n Factorial value=%lu\n",fact);
            break;
        case 2:
            printf("\n Enter number:");
            scanf("%d",&num);
            for(i=2;i<num;i++)
            {
                if(num%i== 0)
                {
                    printf("\n Not a prime number.\n");
                    break; 
                }
            }
            if(i==num)
                printf("\n Prime number.\n");
            break;
        case 3:
            printf("\nEnter number:");
            scanf("%d",&num);
            if(num %2==0)
                printf("\n Even number.\n");
            else
                printf("\nOdd number.\n");
            break;
        case 4:
            break;
        default:
            printf("\nInvalid Argument.\n");
        }
    }while(choice != 4);
    return 0;
}

The code works fine with the inputs 1,2,3,4 and any other integer but when I enter a character or string, the code goes in an infinite loop. Why? How to handle this case?

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
Ben Williams
  • 109
  • 2
  • 11

1 Answers1

3

You can check for the return value of the scanf() function. Something like this:

if((scanf("%d", &choice)) != 1){
    printf("Invalid Argument\n");
    continue;
}
else
{
    //Your switch case logic
}
iqstatic
  • 2,322
  • 3
  • 21
  • 39
  • 5
    `fflush(stdin)` is undefined behavior in Standard C. – ad absurdum Mar 13 '17 at 18:28
  • Yes you are right. Its OP's choice to decide whether to terminate the program or continue to run. I have incorporated this in my answer. – iqstatic Mar 13 '17 at 18:29
  • @DavidBowling: Yes fflush is known to be inconsistent in the older glibc versions. But I think it should work on the newer versions. However, there is a warning that the code may have portability issues. – iqstatic Mar 13 '17 at 18:32
  • Thanks @DavidBowling. The discussion helped me understand many other things apart from a helpful answer. I appreciate it. – Ben Williams Mar 13 '17 at 18:38
  • Thanks @iqstatic for the answer. – Ben Williams Mar 13 '17 at 18:38
  • Well, `fflush(stdin)` has defined behavior in Windows, and as a GNU C extension, I believe, but is explicitly [undefined behavior in the Standard](http://port70.net/~nsz/c/c11/n1570.html#7.21.5.2). It is certainly not portable, and I would suggest never using it as an illustration of a code solution. – ad absurdum Mar 13 '17 at 18:39
  • 2
    What about `scanf` returning `EOF` (not 0)? I will use `if(scanf("%d", &choice) != 1){` – David Ranieri Mar 13 '17 at 18:40
  • @KeineLust Right. – iqstatic Mar 13 '17 at 18:44
  • @DavidBowling Thanks for the reference. Certainly a learning for me. – iqstatic Mar 13 '17 at 18:47