3

Can someone enlighten how to make this work? So now i have a do/while loop with a switch inside. The switch is handled by a int choice and scanf is "%d". But if I write an char symbol different from number like a,b,c... it goes into infinity loop. Changing int to char and %d to %c works but if something wrong is entered the menu repeats x2 and it becomes messy. Sorry for bad english :) With int:

int main() {
 int choice;
    do{
        menu();
        scanf("%d", &choice);
    switch(choice) {
        case 1:
            // 1-vo poduslovie
            ReadSave();
            break;
        case 2:
            // 2-ro poduslovie
            ShowResult();
            break;
        case 3:
            // 3-to poduslovie
            SavetoScreen();
            break;
        case 4:
            // 4-to poduslovie
            PrinttoScreen();
            break;
        case 5: // exit
            return 0;
        default:
            printf("Wrong choice.\n");
    }
}while(choice!=5);

With char:

int main() {
 char choice;
    do{
        menu();
        scanf("%c", &choice);
    switch(choice) {
        case '1':
            // 1-vo poduslovie
            ReadSave();
            break;
        case '2':
            // 2-ro poduslovie
            ShowResult();
            break;
        case '3':
            // 3-to poduslovie
            SavetoScreen();
            break;
        case '4':
            // 4-to poduslovie
            PrinttoScreen();
            break;
        case '5': // exit
            return 0;
        default:
            printf("Wrong choice.\n");
    }
}while(choice!='5');
MESA
  • 85
  • 6
  • 1
    Show a sample input sequence for each case. – Mad Physicist Dec 27 '16 at 17:19
  • Also, fix your parens and indentation. – Mad Physicist Dec 27 '16 at 17:20
  • `scanf("%c", &choice);` ==> `scanf(" %c", &choice);` please note that extra space. `%c` format otherwise reads the *next character* while other formats filter out whitespace. – Weather Vane Dec 27 '16 at 17:21
  • 1
    Better yet, use `fgets` and apply `sscanf` and *always* check its return value. What is the return value of `scanf` family? Read the man pages. Using `fgets` it is easier to dump the string and try again, than to try clearing the bad input which will otherwise continue to block the buffer. – Weather Vane Dec 27 '16 at 17:24
  • You should always check the return value from `scanf` to make sure it read the number of items you expected and didn't fail or hit eof. – Retired Ninja Dec 27 '16 at 17:36

2 Answers2

4

With %d, if you enter a non-integer, scanf ignores it and does not remove it from the input buffer. Each time through the loop, the non-character is still there, so scanf ignores it, choice never changes, and the loop never exits.

Edit You can tell that this is happening by checking the return value from scanf. If the return value is 1, scanf matched the %d which is the single (1) item in your format string. If the return value is 0, scanf couldn't match the %d, e.g., because of character data being present. I presume this is what is happening in your code.

How to clear input before the scanf is discussed in detail in this answer. However, as @WeatherVane said in a comment, you are probably better off to use fgets to get a whole line, then use sscanf to extract the integer (if any) from the string you got. See, e.g., this answer.

Sources:

  • The scanf manpage says:

    Reading of characters stops ... when a nonmatching character is found

    Hence the non-number is left in the input stream, e.g., for a future scanf to try to match.

  • The fgets manpage

Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81
  • Okay thanks for the answers people :) Will see what to choose to fit my use. because I am a total beginner and maybe I will make it with fgets. Here is the full code(I have to change that too because I used scanf more than once. https://drive.google.com/file/d/0B5H_NO3oeuLZNjJ2bjdzcWJsNzQ/view?usp=sharing – MESA Dec 27 '16 at 18:27
  • @MESA Glad to hear it! If you found my answer helpful, would you please hit the upward-pointing triangle to mark it as such? --- Also, welcome to the site! Check out the [tour](https://stackoverflow.com/tour) for more information to help you participate most effectively on Stack Overflow. – cxw Dec 27 '16 at 19:06
-2

I ended using this:

int choice;
 char string[20];
    do{
        menu();
        fgets(string, sizeof(string), stdin);
        sscanf(string, "%d", &choice);
     switch(choice) { /*menu......*/}

The full code:(havent edited it there yet). https://drive.google.com/file/d/0B5H_NO3oeuLZNjJ2bjdzcWJsNzQ/view

MESA
  • 85
  • 6
  • 1
    to use stackoverflow as everyone else does you should upvote the person who told you how to do this -- not post a new answer. This is not form. Please read the FAQ for more information on how SO works. – Hogan Dec 27 '16 at 19:31
  • 1
    Your "solution" contains undefined behaviour. You *must* check return values of functions you call. – n. m. could be an AI Dec 27 '16 at 19:48
  • This is a code-only answer and does not explain why it solves the problem. It has weaknesses in not checking the return value of `fgets()` and `sscanf()` before using `string` and `choice` in the next lines. – chux - Reinstate Monica Dec 27 '16 at 20:22
  • Sorry people :). Will read the rules and FAQ now on how to use stackoverflow. – MESA Dec 28 '16 at 00:09