1

The following is the code for a simple menu. If the user enters an invalid option (4 or 'o') the menu should be reprinted displaying an error message. The code works when the user inputs a number, however it fails (looping indefinitely) when the user inputs a letter or string into option. My guess is that memory is being overwritten in the looping cases generating the strange behavior. Could someone help me to fix it? Thank You

int inmenu = 1;
while (inmenu){
    //Menu
    printf("User: %s %s\n", user.firstname, user.lastname);
    printf("0) Exit\n1) List Friends\n2) Add Friend\n3) Delete Friend\nWhat would you like to do? ");
    int option;
    scanf("%i", &option);
    if(option == 0)
        inmenu = 0;
    else if (option == 1)
        defaultPrint(friends, numfriends, NULL);
    else if (option == 2){
        //addfriend
        char *name = (char *) malloc(sizeof(char) * 256);
        int birthdate;
        printf("Enter first name: ");
        scanf("%s", name);
        printf("Enter last name: ");
        scanf("%s", name);
        printf("Enter birthdate: ");
        scanf("%i", &birthdate);

    }
    else if (option == 3){
        //deletefriend
        defaultPrint(friends, numfriends, NULL);
        int n;
        printf("What friend would you like to delete? ");
        scanf("%i", &n);
    }
    else
        printf("ERROR: Invalid option %i\n", option);
}

Test input:

0) Exit
1) List Friends
2) Add Friend
3) Delete Friend
What would you like to do? 4
ERROR: Invalid option 4
0) Exit
1) List Friends
2) Add Friend
3) Delete Friend
What would you like to do? 

(correct behavior)

0) Exit
1) List Friends
2) Add Friend
3) Delete Friend
What would you like to do? o
What would you like to do? ERROR: Invalid option 4
0) Exit
1) List Friends
2) Add Friend
3) Delete Friend
...

(incorrect behavior keeps printing the same last 5 lines in an infinite loop)

ludo
  • 1,456
  • 2
  • 14
  • 26

3 Answers3

2

Why use scanf? How about use getchar, check the range, see if it's 0-4, and if not, error message.

tekknolagi
  • 10,663
  • 24
  • 75
  • 119
1

When you enter a number and press enter, scanf reads the number but leaves the newline in the buffer, when the loop loops, scanf will read the newline from the buffer, see that it doesn't match the format, and leave it there. This will repeat forever.

A quick fix could be to add the newline to the format:

scanf("%i\n", &number);

but this will fail if the user doesn't enter exactly the data you expect, newline isn't the only thing that will cause the behaviour, anything that doesn't match the format is left in the buffer.

Dumbfounded DM
  • 156
  • 1
  • 10
  • 1
    `scanf()` with a `%i` format will skip over whitespace, including newlines, until it finds a number (or something that definitely isn't a number). Newlines aren't the problem. – caf Jan 25 '12 at 07:11
1

The cause of your problem is that scanf() doesn't consume the input stream if it doesn't match the requested format.

This means that when you call:

scanf("%i", &option);

If the user enters something other than a number (like "o"), then that user input remains in the input stream - so when you loop around and call scanf() again, the "o" is still there, and still doesn't match the requested format.

This is why scanf() is not particularly suitable for taking user input - it's designed for consuming well-formatted data files. Instead, since you have a line-oriented user interface, you should read an entire line from the user with fgets(), then try parsing it with sscanf(). If it doesn't parse correctly, you can report an error and then read a new line from the user.

caf
  • 233,326
  • 40
  • 323
  • 462
  • @pretobomba for a more permanent solution (if you want to add more options, etc) check out my answer. also, you might want to accept his answer if it solved your problem. – tekknolagi Jan 26 '12 at 02:36