Search code examples
cinputwhile-loopswitch-statementbuffer

Switch and while combination using scanf, how to avoid multiple input


In this switch and while combination, when I press 'a' or 'b' it's fine but I don't want the program to print 1 and 2 when user inputs 'ab'.

How can I print an error message when user enters an input with more than one character?

#include <stdio.h>

int main() {
    char move;

    while (move != 'd') {
        printf("enter a move :  ");
        scanf(" %c", &move);
        switch (move) {
            case 'a':
                printf("1\n");
                break;
            case 'b':
                printf("2\n");
                break;
            case 'c':
                printf("3 \n");
        }  // switch
    }      // while
}

Sample output :

enter a move : a
1
enter a move : b
2
enter a move : ab
1
enter a move : 2

The program should print error message when I input 'ab', 'ac' or 'bc', or similar.


Solution

  • I would recommend the use of fgets to parse inputs. Avoiding the common edge cases gets somewhat trickier, you need to handle the newline character that will also be parsed from your input as you press Enter, you need to clear the input to prepare for the next loop, since fgets also parses \n you need to avoid handling it in some cases, just to to mention a few common cases.

    Here's how you could do it:

    You can try it here: https://onlinegdb.com/S6Uh3mrHX

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char move[20] = {};
        while (move[0] != 'd') {
            printf("enter a move :  ");
            // parse and check fgets return to validate input
            if (fgets(move, sizeof move, stdin) != NULL) {
                // if we have more than 2 chars, error, fgets also parses \n and strlen counts it
                if (strlen(move) > 2) {
                    printf("Error, invalid input\n");
                    // if the \n character wasn't already parsed we need to handle it
                    if (!strchr(move, '\n')) {
                        int c;
                        // this just clears the stdin input buffer
                        while ((c = getchar()) != '\n' && c != EOF) {}
                    }
                    // Since we got an error, let's reset our target buffer
                    move[0] = 0;
                }
            }
            switch (move[0]) {
                case 'a':
                    printf("1\n");
                    break;
                case 'b':
                    printf("2\n");
                    break;
                case 'c':
                    printf("3 \n");
            }  // switch
        }      // while
    }
    

    If you have to use scanf, however, here's a possible solution:

    You can try it here: https://onlinegdb.com/Hcu8dlb04G

    #include <stdio.h>
    
    int main() {
        char move = 0;  // don't forget to initialize, accessing an unitialized
                        // variable is UB (1
        while (move != 'd') {
            printf("enter a move :  ");
            if (scanf(" %c", &move) == 1) {
                int c;
                if (getchar() != '\n') {  // if more character were inputed other than newline
                    printf("Error, invalid input\n");                // print error
                    while ((c = getchar()) != '\n' && c != EOF) {}   // clear input buffer
                    move = 0;  // reset target variable
                }
                switch (move) {
                    case 'a':
                        printf("1\n");
                        break;
                    case 'b':
                        printf("2\n");
                        break;
                    case 'c':
                        printf("3 \n");
                }  // switch
            }      // while
        }
    }
    

    You still may need to handle other edge cases, for exampe, let's say the user inputs j, no input error is issued, it just jumps to the next input loop (you can handle this in the switch), you may also want to add support for upper case letters.


    1 - UB: Undefined Behavior, definition: https://port70.net/%7Ensz/c/c11/n1570.html#3.4.3