1

On the first run, it works fine. The Program runs the last chosen case when you input a char

int x;
do{
printf("Input a number:");
    scanf("%d", &x);

switch(x){
    case 1: printf("A\n\n");
            break;
    case 2: printf("B\n\n");
            break;
    case 3: printf("C\n\n");
            break;
    case 4: printf("End");
            break;
    default: printf("Invalid.\n");
}

}while(x!=4);

how do I prevent this?

Rollo
  • 11
  • 6

2 Answers2

2

Check the return value of scanf and if it doesn't return 1 then you will know that either user inputted something not desired by the format specifier or some error occured.

if(scanf("%d", &x) != 1){
  fprintf(stderr,"Error occured\n");
  exit(1);
}

Better solution is to use fgets and parse for number using strtol. It will give a much more error handling and control over the whole procedure than scanf would.

As I said, you can also go for using fgets to read a line and then use sscanf to parse the integer input. Play a bit with this bare minimum function you will understand what I mean:-

#define MAXLEN 50
int f() {
  int v;
  char buff[MAXLEN];
  while (fgets(buff, sizeof buff, stdin)) {
    if (sscanf(buff, "%d", &v) == 1 ) {
      return v;
    }
  }
  return -1;
}
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • What if I want to just skip to the next iteration if an invalid input was given? Using `continue` doesnt work for me. It loops infinitely without asking for input later on. – Rishav Mar 04 '18 at 11:09
  • 1
    @Rishav.: You didn't see me using `continue` did you? That is why I mentioned that use `fgets` it would be easier. Now look here also you can solve the thing - whyit fails here? Becaus ethose bad inputs are still there. Now if you put a consecutive `getchar()` calls removing those bad inputs (easy to consider that they appear in line and we will delete it) then yes it would again wait for good input. – user2736738 Mar 04 '18 at 11:13
  • Great! Thanks I got it. – Rishav Mar 04 '18 at 11:14
0

The Program runs the last chosen case when you input a char.

This is because when scanf("%d", &x); failed it did not updated the variable x. xstill remembers the last chosen good number.

Check the standard 7.21.6.4 The scanf function.

You can read about behaviour of scanf here.

On success, the scanf returns the number of items successfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens. In the case of an input failure before any data could be successfully read, EOF is returned.

Knowing that you can check the return value of scanf and make appropriate decision. In the program below, bad scanf input is treated as case 4: and program ends:

#include <stdio.h>

int main(){
    int x;
    do{         
        printf("Input a number:\n");

        if(scanf("%d", &x) != 1){
            printf("Error - END.\n");
            break;
        }

        switch(x){
            case 1: printf("A\n\n");
                    break;
            case 2: printf("B\n\n");
                    break;
            case 3: printf("C\n\n");
                    break;
            case 4: printf("End\n");
                    break;
            default: printf("Invalid.\n");
        }

    }while(x!=4);

    return 0;
}

Output:

Input a number:                                                                                                                                  
0                                                                                                                                                
Invalid.                                                                                                                                         
Input a number:                                                                                                                                  
1                                                                                                                                                
A                                                                                                                                                

Input a number:                                                                                                                                  
2                                                                                                                                                
B                                                                                                                                                

Input a number:                                                                                                                                  
3                                                                                                                                                
C                                                                                                                                                

Input a number:                                                                                                                                  
N                                                                                                                                                
Error - END.   

Edit:

If OP requires program to continue to run after user bad input, that requires more work. The naive approach is to replace the break with continue.

That will not work! Any character that does not match the format string causes scanf to stop scanning and leaves the invalid character still in the buffer!

To continue we have to flush the invalid character out of the buffer.

The modified program is given below:

    #include <stdio.h>
    #include <ctype.h>

    int main(){

    int x;
    char c;
    int error = 0;

    do{
        c = '0';

        if(!error)
            printf("Input a number:\n");
        else
            error = 0;

        if(scanf("%d", &x) != 1)
        {    
            printf("No letters! Input a number:\n");
            do
            {
                c = getchar();
            }
            while (!isdigit(c));

            ungetc(c, stdin);
            error = 1;

            continue;
        }

        switch(x){
            case 1: printf("A\n\n");
                    break;
            case 2: printf("B\n\n");
                    break;
            case 3: printf("C\n\n");
                    break;
            case 4: printf("End\n");
                    break;
            default: printf("Invalid.\n");
        }

    }while(x!=4);

    return 0;
}

Output:

Input a number:                                                                                                                             
1                                                                                                                                           
A                                                                                                                                           

Input a number:                                                                                                                             
X                                                                                                                                           
No letters! Input a number:                                                                                                                 
1                                                                                                                                           
A                                                                                                                                           

Input a number:                                                                                                                             
4                                                                                                                                           
End
sg7
  • 6,108
  • 2
  • 32
  • 40
  • How do I make it so that the loop doesn't end? – Rollo Mar 05 '18 at 03:29
  • @Rollo You mean, does not end when there is an error? Then ` if(scanf("%d", &x) != 1){ continue;}` should do. Check it. – sg7 Mar 05 '18 at 03:32
  • It loops printf("Input a number:\n"); infinitely – Rollo Mar 05 '18 at 03:37
  • @Rollo I will work on your additional question tomorrow. But check this yourself: https://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code – sg7 Mar 05 '18 at 04:24
  • @Rollo OK! I tested it and it works for me: `printf("Input a number:\n"); char c = '0'; if(scanf("%d", &x) != 1) { printf("No letters! Input number:\n"); do { c = getchar(); } while (!isdigit(c)); ungetc(c, stdin); continue; }` Could you also check it? Thanks! – sg7 Mar 05 '18 at 13:54
  • It works! Thank you so much @sg7! I have a warning though.. [Warning] implicit declaration of function 'isdigit' [-Wimplicit-function-declaration] – Rollo Mar 06 '18 at 14:04
  • @Rollo You may want to include more include files: `#include ` – sg7 Mar 06 '18 at 14:09