1

i was making a menu with 3 int choices, if the input is a wrong int it reprints the menu and the input. The problem is that when instead of an integer the input is a char the program get stuck in an infinite loop, how can i solve this?


#include <stdio.h>
#include <stdlib.h>

int main(){
    
    int menu_choice;

do{
    printf("\n\t\t...PHALSOPHOBIA...\t\t");
    printf("\n\tMenu\t\n1. Imposta gioco.\n2. Gioca\n3. Termina gioco\n");

    scanf("%d", &menu_choice);

    switch (menu_choice)
        {
        case 1:
        break;

        case 2:
        break;

        case 3:
        break;

        default:
            printf("Comando errato.\n");
        }
}while (menu_choice < 1 || menu_choice > 3);
}
  • It's because `scanf("%d")` reads an integer from stdin. If there's a (non integer) character sitting in the buffer, it returns 0, and _does not consume the character_. Always check the return value from `scanf()`, it will return how many input fields it converted. It could be zero. – pmacfarlane Feb 21 '23 at 23:13
  • What should happen if the user does not enter a valid integer? Should the program exit with an error message? Or should the user be reprompted for input? If it is the latter, then I suggest that you take a look at this question: [Validate the type of input in a do-while loop](https://stackoverflow.com/q/31633005/12149471) – Andreas Wenzel Feb 22 '23 at 02:16

2 Answers2

2

You need to clear the input buffer if it doesn't contain a digit, and you probably want to handle EOF:

#include <stdio.h>
#include <stdlib.h>

int flush() {
    for(;;) { int ch = getchar();
        if(ch == EOF || ch == '\n')
            return ch;
    }
}

int main(){
    int menu_choice;
    do {
        printf("\n\t\t...PHALSOPHOBIA...\t\t");
        printf("\n\tMenu\t\n1. Imposta gioco.\n2. Gioca\n3. Termina gioco\n");
        if(scanf("%d", &menu_choice) != 1) {
            if(flush() == EOF)
                break;
            menu_choice = 0;
        }
        switch (menu_choice) {
            case 1:
            case 2:
            case 3:
                break;
            default:
                printf("Comando errato.\n");
        }
    } while (menu_choice < 1 || menu_choice > 3);
}

example session:

                ...PHALSOPHOBIA...
        Menu
1. Imposta gioco.
2. Gioca
3. Termina gioco
x
Comando errato.

                ...PHALSOPHOBIA...
        Menu
1. Imposta gioco.
2. Gioca
3. Termina gioco
1

Consider introducing an enum so you constants to switch instead of just numbers.

Allan Wind
  • 23,068
  • 5
  • 28
  • 38
1

A simple solution is to use fgets() to handle the input, then, if you want, sscanf() to handle the conversion to an integer.

#include <stdio.h>
#include <stdlib.h>

int main( void ) {
    int menu_choice;

    for( ;; ) {
        // C allows continued strings with only whitespace intervening
        printf("\n\t\t...PHALSOPHOBIA...\n"
            "\tMenu\n"
            "1. Imposta gioco.\n"
            "2. Gioca\n"
            "3. Termina gioco\n" );

        char buf[100];
        if( fgets( buf, sizeof buf, stdin ) == 0 ) // handle input
            return 1;

        if( sscanf( buf, "%d", &menu_choice ) == 1 // conversion & validation
        &&  1 <= menu_choice
        &&  menu_choice <= 3 )
            break;

        printf("Comando errato.\n"); // error and loop
    }

    // Based on your code, processing can/should be separated from the user selection
    switch( menu_choice ) {
        case 1: puts( "1" ); break;
        case 2: puts( "2" ); break;
        case 3: puts( "3" ); break;
    }

    return 0;
}
                ...PHALSOPHOBIA...
        Menu
1. Imposta gioco.
2. Gioca
3. Termina gioco
foobar
Comando errato.

                ...PHALSOPHOBIA...
        Menu
1. Imposta gioco.
2. Gioca
3. Termina gioco
2
2  <== Notice the processing generates some output...
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • 1
    `fgets()` for input and `sscanf()` or whatever for parsing usually end up with cleaner code (while handling EOF). The buffer limit is arbitrary, and with sufficiently long input you still have handle left-over from previous call(s). Not a critique just reflecting. – Allan Wind Feb 22 '23 at 00:33
  • @AllanWind "Users are a problem..." `:-)` – Fe2O3 Feb 22 '23 at 00:37