1

I've got a program here which contains a do-while loop within a specified void method. I'm trying to exit the loop within the function, so that the do-while loop actually works as it is supposed to. Except after I run the program and one of the cases occurs, the program continues to run despite my while statement stating that it should only work while(userInput != 1). I cannot use global variables to solve this problem, as my assignment limits me on using such techniques, thus any help would be much appreciated!

Here is a snippet of my code:

void functionTest()
{
    int gameOver = 0;
    int userInput;

    do
    {
        printf("please enter a number 1-3");
        scanf("%d",&userInput);

        switch(userInput)
        {
            case 1:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;

            case 2:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;

            case 3:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;
        }
    }
    while(gameOver!= 1);
}
}
Egzy
  • 43
  • 8

2 Answers2

0

The problem probably lies when you use scanf(). Something that you're inputting before hitting enter is not 1, 2 or 3. Could you tell us exactly what you type when it asks you to enter a choice?

Sometimes, the standard output needs to be flushed before using a fresh scanf(). Try fflush(stdout) before the scanf line. See older question 1 and older question 2.

EDIT: I can reproduce the problem easily enough if I enter anything apart from "1","2" or "3"...

I would suggest, you do the following before executing the switch statement:

  1. Add fflush(stdout) before scanf()
  2. Accept the input as a string (%s) instead of a number. (char [] needed)
  3. Trim the string of trailing and leading white spaces.
  4. Convert to number using a library function
  5. Then switch-case based on that number
Community
  • 1
  • 1
Akshay Rao
  • 352
  • 1
  • 7
  • Hard to say without seeing full code but you are probably correct. scanf() can be a heartless beast sometimes :) – James H Nov 07 '14 at 16:53
  • It is easy enough to determine if `scanf` is successfully reading the input: check the return value. – clcto Nov 07 '14 at 16:57
  • I agree. The program certainly needs a lot of input verification/massaging before hitting the switch case, but that comes with some more experience than possibly what OP has currently. – Akshay Rao Nov 07 '14 at 17:01
  • by the way, @clcto, the website you mentioned in the comments above is very useful! Thank you! – Akshay Rao Nov 07 '14 at 17:06
  • 1
    "*Sometimes, the standard output needs to be flushed before using a fresh scanf()*" I doubt this. Why this? And if, why only "*sometimes*"? Out is out and in is in, they aren't coupled. – alk Nov 07 '14 at 17:49
  • A similar problem occurred here: http://stackoverflow.com/questions/16877264/c-c-printf-before-scanf-issue and here: http://stackoverflow.com/questions/8464620/program-doesnt-wait-for-user-input-with-scanfc-yn – Akshay Rao Nov 07 '14 at 18:21
  • 1
    Not flushing `stdout` before `scanf()` might lead to things being displayed out of order, but it wouldn't cause the infinite loop here. – Dmitri Nov 07 '14 at 19:49
0

The problem is that if other characters (that aren't part of an integer) are present in the input stream before an integer can be read, scanf() fails and unusable data is never cleared out... which leads to an infinite loop (where scanf() repeatedly fails to read the same characters as an integer, over and over).

So you need to read off the invalid characters when scanf() fails, or as part of the format.

A simple fix would be to change your scanf from:

scanf("%d",&userInput);

to:

scanf("%*[^0-9]%d",&userInput);

to read (and discard) any characters in the input stream that aren't digits 0-9 before reading your integer... but that still doesn't check whether scanf fails for any other reason (like a closed input stream).

You could replace it with something like this:

int scanfRes,c;
do {
    scanfRes = scanf("%d",&userInput); /* try to read userInput */
    /* ..then discard remainder of line */
    do {
        if ((c = fgetc(stdin)) == EOF)
            return; /* ..return on error or EOF */
    } while (c != '\n');
} while (scanfRes != 1); /* ..retry until userInput is assigned */

..which will retry scanf() until the field is assigned, discarding the remainder of the line after each attempt, and exiting the function if fgetc() encounters an error or EOF when doing so.

Dmitri
  • 9,175
  • 2
  • 27
  • 34