0

Language : C

Compiler : Visual Studio 2017 / Win 32

So basically i'm tasked with making a multiplication game that takes two random, single digit numbers and prompts the user to multiply them together. The program has to be bullet proof so it has to loop the user until they enter a correct input (If they enter a letter, for example, it must loop them until they enter the correct NUMBER). I've tried a couple things out, and the do/while loop seems to work pretty well. However, when the user enters an incorrect answer, and tries again, the scanf in the 2ND do/while loop will make them enter two inputs (ignores the first one). I've had this problem in the past and tried countless times to fix it but I cant find a solution. Any help would be really appreciated.

Thanks!

Tried using fgets. Failed miserably. I removed getchar() != '\n'. That worked, but then the program would loop "Please enter an integer" infinitely.

    while (answer != correct)
    {
        srand(time(NULL));
        int wrong = 1 + rand() % 5;

        switch (wrong)
        {
        case 1:
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            printf("\n               ***\n");
            printf("              Wrong!\n");
            printf("               ***\n");
            SetConsoleTextAttribute(h, wOldColorAttrs);
            break;
        case 2:
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            printf("\n                ***\n");
            printf("               Nope!\n");
            printf("                ***\n");
            SetConsoleTextAttribute(h, wOldColorAttrs);
            break;
        case 3:
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            printf("\n                 ***\n");
            printf("              Not quite!\n");
            printf("                 ***\n");
            SetConsoleTextAttribute(h, wOldColorAttrs);
            break;
        case 4:
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            printf("\n              ***\n");
            printf("          Incorrect!\n");
            printf("              ***\n");
            SetConsoleTextAttribute(h, wOldColorAttrs);
            break;
        case 5:
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            printf("\n                 ***\n");
            printf("          Nope! Try again!\n");
            printf("                 ***\n");
            SetConsoleTextAttribute(h, wOldColorAttrs);
            break;
        }

        do {
        printf("Enter a number to represent your answer! ");
        while (getchar() != '\n');
        } while (scanf_s("%d", &answer) != 1);
        getchar();
    }

I just want the user to be able to smoothly enter a number without the confusing scanf bug.

  • 1
    Please post a complete program for us to consider. Also, you don't need to replicate 5 lines of code just to print a different string; try `printf(" %s", wrong_indication_strings[wrong])` with `wrong_indication_strings` being a constant, static array of literal strings. – einpoklum Apr 06 '19 at 21:39
  • https://repl.it/repls/AnchoredRecklessVolcano .... Everytime I use %s i get a crash. Quite odd. Ill post an image of the crash. EDIT just to show that im not able to use %s for some reason : https://imgur.com/a/u37zVdh – Noah Sinishtaj Apr 06 '19 at 21:53
  • regarding: `srand(time(NULL));` move this line to just after: `int main(...) {` – user3629249 Apr 06 '19 at 23:21
  • the posted code has nothing to do with "unable to open file" Please post a [mcve] so we can reproduce the problem and help you debug it – user3629249 Apr 06 '19 at 23:27
  • regarding: `while (answer != correct)` no where in the `while()` loop is the variable `answer` ever set to `correct`. BTW: for this to work, both `answer` and `correct` must be integers. – user3629249 Apr 06 '19 at 23:30
  • regarding: *Please enter an integer* No where in the posted code is that string being output. – user3629249 Apr 06 '19 at 23:33
  • the posted code is never trying to input two integers from the user – user3629249 Apr 06 '19 at 23:35
  • Confusing `scanf` bug? Could you elaborate? – Neil Apr 06 '19 at 23:46
  • Neil, the do/while loop including my scanf is requiring two inputs in order to execute. I believe the scanf is reading left over whitespace. Ill post an output in a minute. – Noah Sinishtaj Apr 07 '19 at 00:30
  • Full code : https://repl.it/repls/AnchoredRecklessVolcano – Noah Sinishtaj Apr 07 '19 at 00:32
  • `scanf` is not really intended for interactive processing; have you considered using `fgets`? – Neil Apr 15 '19 at 21:55

1 Answers1

0

You could obtain the input as in this example

#include <stdio.h>

int main(void)
{
    char anstr[100];
    int answer;
    do { 
        printf("Enter ... answer! ");
        if(fgets(anstr, sizeof anstr, stdin) == NULL) {
            return 1;
        }
    } while(sscanf_s(anstr, "%d", &answer) != 1);
    printf("The answer is %d\n", answer);
    return 0; 
}

on the grounds that %d format specifier will consume all leading whitespace, and bad input will be dumped by reading another string input.

Program session:

Enter ... answer! alice
Enter ... answer! bob
Enter ... answer! 42
The answer is 42
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • That looks like a better alternative. However, the program wont run when I try to debug it. It gives me Error: Unable to Open File. – Noah Sinishtaj Apr 06 '19 at 22:18
  • This program is not trying to open a file - `stdin` is already open. Why does it need debugging? Did you copy / paste the exact program and try it? – Weather Vane Apr 06 '19 at 22:19
  • Yeah i pasted it exactly as you put it. Here's my full source : https://repl.it/repls/AnchoredRecklessVolcano .... Keep in mind that compiler wont run the program since it doesn't use the header files. Thanks. – Noah Sinishtaj Apr 06 '19 at 22:23
  • Well, that's a different question, and I notice the question title says "One of my scanf loops..." and the code now linked is still using `scanf` elsewhere. You can't easily mix your methods, so replace all of the `scanf`s. Did you try this exact program as it is? It does work as intended. – Weather Vane Apr 06 '19 at 22:26
  • I also notice that your code is .cpp so it's using the C++ compiler. – Weather Vane Apr 06 '19 at 22:28
  • Your code has numerous compiler warnings such as the misuse of `scanf_s`: You are using `scanf_s` with `%c` specifier incorrectly. *"Unlike `scanf` ... `scanf_s` ... requires the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable."* Aside: you call `srand()` three times. Call it once, at the start of the program. – Weather Vane Apr 06 '19 at 22:34
  • To compile with C I turn off precompiled headers and go in the properties and compile it as C code. – Noah Sinishtaj Apr 06 '19 at 22:35
  • Yeah I saw the warnings with scanf_s. The program worked as it should though. In my noob opinion, I feel that something in my properties is off or im missing a header file. – Noah Sinishtaj Apr 06 '19 at 22:37
  • `scanf_s(" %d[^\n]%c", &answer)` has only one argument but requires ***five***! One for `%d`, two for `%[]` and two for `%c`. Fix every warning to your satisfaction, they are important. This one is an error, and causes *undefined behaviour*. Uh, the `%[]` is missing the `%`. – Weather Vane Apr 06 '19 at 22:39
  • You are tearing apart my baby haha. Jokes aside, I spent alot of time browsing around for a solution to this scanf problem. The first do/while loop works perfectly (if i enter a letter it keeps looping me.) I tried the same thing for the second one and it didn't work at all. As a beginner, I prefer to not fix what ain't broke. – Noah Sinishtaj Apr 06 '19 at 22:42
  • 1
    But it is broke, or you would not be here. I suggest replacing every occurrence of `scanf_s` with a string input and then `sscanf_s` as in my example. – Weather Vane Apr 06 '19 at 22:46
  • For two digit char string would I do something like int answer[]; then use %c for all my sscanf_s? Thanks for your help, really appreciate it. – Noah Sinishtaj Apr 06 '19 at 22:49
  • For a 2-digit string you already have a string from `fgets`. If needed, [remove the trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) and then check the string length. If that isn't quite what you want, pick them out with `answer[0] = instr[0] - '0'; answer[1] = instr[1] - '0';` . Experiment with my program away from your baby. – Weather Vane Apr 06 '19 at 22:51
  • Vane, I made a separate VS project and played around with your code. It worked, however, it isn't working when I apply the code to my multiplication game. – Noah Sinishtaj Apr 07 '19 at 00:41