2

I was trying to ask for an input. If it is not an integer, then it should ask for the input again and that's why I use recursion as below.

#include <stdio.h>


void hi() {
    int a;
    printf("Input a: ");
    if(scanf("%d", &a) == 0)
        a = -1;
    switch(a) {
        case 1:
            printf("Hello!");
            break;
        case 0:
            return;
        default:
            hi();
            return;
            break;
    }
}

int main()
{
    hi();

    return 0;
}

The output is

Input a: *asd* Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a:

Why won't the scanf in hi() working when I input non-integer value (It doesn't stop the printf and ask for my input) How do I fix it?

tang216
  • 21
  • 2
  • 5
    Terrible idea to use a recursion for that. I would rather use a `do { ... } while();` – Cid Nov 22 '19 at 08:28
  • Have you checked it : https://stackoverflow.com/questions/17292545/how-to-check-if-the-input-is-a-number-or-not-in-c – cocool97 Nov 22 '19 at 08:28
  • For the reason that scans continue fails read this answer:https://stackoverflow.com/a/4016721/4562521 – christian mini Nov 22 '19 at 09:10

2 Answers2

5

For interactive program that need to handle invalid input, you do not want to use scanf, as it does not have the ability to recover from parsing errors. Use combination of fgets/sscanf instead.

Also, it better not to use recursion to address problems that can be solved using iteration. Much easier to maintain and debug. You will also get better grade!

   int a = 0 ;
   while ( 1 ) {
       char buff[200] ;
       printf("Enter ...") ;
       if ( !fgets(buff, sizeof(buff), stdin) ) { perror("EOF") ; exit(1) ; }
       if ( sscanf(buff, " %d", &a) == 1 ) break ; // All Good
   } ;      

The original code 'scanf' will fail repeatedly on the first parsing error, with the recursion causing the all stack to be used, and the program to crash.

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • 1
    Minor: `' '` not needed in `" %d"`. `"%d"` will skip leading spaces already. – chux - Reinstate Monica Nov 22 '19 at 08:47
  • I agree. I prefer to add an explicit space to clarify this to readers of the code, who might not be familiar with the exact details. For multiple fields "%d %f %d" easier to read vs. "%d%f%d". – dash-o Nov 22 '19 at 09:02
  • `NULL` return from `fgets` means EOF **or** error. `perror("EOF")` will print a strange error message like `EOF: Success` on EOF or `EOF: Some error message` in case of an error. (You can reproduce the error case with `./program < /tmp`.) I suggest to use `feof` and/or `ferror` to distinguish between EOF and error and use something like `perror("fgets(stdin)")` only in case of an error. – Bodo Nov 22 '19 at 09:16
0

scanf does not work in your example because it it reads from stdin which is bufferd. So scanf thinks you already entered something again, again ... again.. until the buffer is cleared. When the buffer is cleard is system dependend and can vary on every system.

So the best practice would be a while or do-while loop as the other users already mentiond.

To get your code to work somehow add fflush(stdin) after your if. BUT please do this only for testing and try to implment it as mentioned with as loop.

#include <stdio.h>    
void hi() {
    int a;
    printf("Input a: ");
    if(scanf("%d", &a) == 0){
        a = -1;            
    }
    fflush(stdin)
    switch(a) {
        case 1:
            printf("Hello!");
            break;
        case 0:
            return;
        default:
            hi();
            return;
            break;
    }
}

int main()
{
    hi();

    return 0;
}
soulflyman
  • 500
  • 1
  • 5
  • 16