0

I' am using goto statement inside switch statement to take the input from the user one more time if its Invalid. Here is the code

#include<stdio.h>

int main(void)
{
 int choice;

 input:
 printf("Enter Your Choice: ");
 scanf("%d", &choice);

 switch(choice)
 {
    case 1:
        /* do something */
        break;
    case 2:
        /* do something */
        break;
    case 3:
        /* do something */
        break;
    default:
        printf("Invalid Input");
        goto input;
}
}

code works just fine when the input is numeric. But when I enter alphabet or some character code runs infinitely as if scanf is not there. I could not understand this behaviour.Why is it happening that way?

  • 3
    When you enter non-numeric input, it is not consumed but stays in the input stream to be read again. You need to check the return value of `scanf()` to find out if input was as expected, and clear the input stream if not. – ad absurdum Feb 09 '18 at 06:10
  • 3
    `scanf()` leaves the non-digit in the input ready for the next input operation. The next input operation tries to read a number, but encounters the non-digit, leaves it ready for the next input operation to read, and goes to the label again. It keeps doing this for a while, and does it rather fast. – Jonathan Leffler Feb 09 '18 at 06:10
  • 2
    Note that you should probably add a newline to the end of the error message. You should also detect when `scanf()` fails to convert and decide what to do about it. One minimal step is to use `getchar()` to read the one character that is causing things to fail, and then go back to the loop. It may take a while if you typed an essay, but it will at least change the state of the input stream, unlike the code you show. Often you should read to the next newline: `static inline gobble(void) { int c; while ((c = getchar()) != EOF && c != '\n') ; }` — and call `gobble()` in the `default:` clause. – Jonathan Leffler Feb 09 '18 at 06:18
  • @Mustafa: nice call on the candidate duplicate. Thanks. There might well be an earlier question on the topic, but what you chose was apposite and fairly old. – Jonathan Leffler Feb 09 '18 at 06:19
  • Thank You. I understood what's happening. @DavidBowling – Shrinath Raje Bhosale Feb 09 '18 at 06:21
  • Thanks a lot @JonathanLeffler – Shrinath Raje Bhosale Feb 09 '18 at 06:22
  • @JonathanLeffler -- I think you meant `static inline void gobble(void) { /* ... */ }`. BTW, is `static inline` very useful anymore, i.e., isn't it likely that this will get inlined anyway? – ad absurdum Feb 09 '18 at 06:31
  • 1
    @DavidBowling: Yup; I missed the (lack of) return type — I should have added the first `void` in `static inline void gobble(void) { … }`. I use `static inline` sometimes as an extra hint, but there's a chance that a simple static function will suffice. One advantage of `static inline`; you don't get compiler warnings about unused functions that way, but you do if you omit the `inline`. OTOH, some might argue that's not a benefit. It depends on context — I find it useful for debugging functions that I don't normally need, but I don't want to delete and have to recover from version control. – Jonathan Leffler Feb 09 '18 at 08:04

0 Answers0