0

I've recently started learning C, and while trying to make a simple calculator, I encountered an issue while trying to clear the input stream. I tried using fflush(stdin); but apparently, it didn't do anything.

Operating System: macOS Sierra (Version 10.12.5 (16F73))

Apple LLVM version 8.1.0 (clang-802.0.42)

Editor Used: Sublime Text 3

Here is my code:

#include <stdio.h>

int main()
{
    int num1, num2;
    char opr;
    char choice = 'y';

    while (choice == 'y') {
        printf("Enter numbers separated with a comma: \n");
        scanf("%d, %d", &num1, &num2);

        printf("Enter an operator: \n");
        fflush (stdin);
        scanf("%c", &opr);

        switch (opr) {
            case '+':
                printf("The sum is %ld\n", (long int) num1 + num2);
                break;
            case '-':
                printf("The difference is %ld\n", (long int) num1 - num2);
                break;
            case '*':
                printf("The product is %ld\n", (long int) num1 * num2);
                break;
            case '/':
                printf("The quotient is %ld and the remainder is %ld\n",
                    (long int) num1 / num2, (long int) num1 % num2);
                break;
            default:
                printf("You've entered an undefined operator\n");
                printf("Please enter + - * or /\n");
                break;
        }

        printf("Do you want to repeat? (y/n):  \n");
        fflush(stdin);
        scanf("%c", &choice);
    }

    return 0;
}

Here is the terminal output:

$ ./calculator_basic
Enter numbers separated with a comma:
20, 30
Enter an operator:
You've entered an undefined operator
Please enter + - * or /
Do you want to repeat? (y/n):
n

An easy solution that I found out was to simply interchange the places of

printf("Enter numbers separated with a comma: \n");<br>
scanf("%d, %d", &num1, &num2);

and

printf("Enter an operator: \n");
fflush (stdin);
scanf("%c", &opr);

I understand that the problem is due to the enter key being stored in the input buffer after entering the numbers in scanf("%d, %d", &num1, &num2); and scanf("%c", &opr); then uses this stored enter key (in the buffer) as its input which creates the problem (ie: none of the cases in switch defined by me work and the default case runs, all this without even me being able to enter an operator)

I tried using fflush(stdin); before getting new character inputs but it doesn't seem to work.

The thing is that fflush(stdin); is working when I'm trying to run this code in a Windows system, but it's not working on macOS regardless of the editor I'm using (tried both Sublime Text 3 and Visual Studio Code)

Can anyone help me out regarding why fflush(stdin); might not be working. Also I've read about it on the internet and one solution was to use cin.get(); instead of getchar();. I tried it but this didn't work as well. I don't want to interchange those two pieces of codes (mentioned above) because that would be hit and trial. I want to run the code in the same order (entering the numbers first and then the operator)

Also, I know questions on fflush(stdin) have been asked previously, but I've read the answers and can't seem to figure out anything that works for me.

Community
  • 1
  • 1
Harshit Jindal
  • 621
  • 8
  • 26
  • 1
    I don't see any question in there. I also don't understand why you would use `fflush(stdin)`. Did some documentation tell you that would do something that would be helpful to you or did you just make it up? If the former, can you link to the documentation? (Short answer: If you want to read a *line* and then parse it, write code to do that.) – David Schwartz Jun 13 '17 at 15:29
  • 2
    Possible duplicate of [Using fflush(stdin)](https://stackoverflow.com/questions/2979209/using-fflushstdin) – Gam Jun 13 '17 at 15:31
  • 1
    @DavidSchwartz My instructor told me to use `fflush(stdin)` and it seems to work fine on her system. – Harshit Jindal Jun 13 '17 at 15:33
  • 1
    @DavidSchwartz Also, I've edited the question. Please have a look and let me know if i'm still not clear – Harshit Jindal Jun 13 '17 at 15:33
  • 6
    @HarshitJindal "My instructor told me to use fflush(stdin)" + "fflush(stdin); is undefined behavior." --> `flush(instructor)`. – chux - Reinstate Monica Jun 13 '17 at 15:38
  • 1
    @HarshitJindal If that's typical of how your instructor determines that things are safe and reliable, you need a new instructor. Code that "just happens to work when I tried it" often later happens not to work when someone else relies on it. – David Schwartz Jun 13 '17 at 15:44
  • 1
    don't edit your question once it has been answered. –  Jun 13 '17 at 16:01
  • 1
    `scanf("%c", &opr);` --> `scanf(" %c", &opr);` Add space. – chux - Reinstate Monica Jun 13 '17 at 16:02
  • 1
    @Binary_10 I didn't. I just added a tag which was somehow left when I originally wrote the question – Harshit Jindal Jun 13 '17 at 16:02
  • 1
    Adding the space worked. Thank you so much. Could you please post it as a solution so that I could mark it as the correct answer? – Harshit Jindal Jun 13 '17 at 16:06
  • 1
    This is really a dupe of many post like [this dupe](https://stackoverflow.com/a/20306692/2410359) – chux - Reinstate Monica Jun 13 '17 at 17:44
  • 1
    @HarshitJindal to avoid some very common errors, you might want to read my [document on `scanf()`](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html) –  Jun 13 '17 at 17:46

2 Answers2

2

fflush(stdin); is undefined behavior.

Per the C Standard:

7.21.5.2 The fflush function

...

If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
1

Newline character

To remove the (only) newline character ('\n') left in buffer, introduce a space (' ') in the format string of scanf(). This directive matches with any no of white spaces (even zero).

scanf(" %c", &opr);

or you could just use getchar() to read '\n' whenever needed, thus leaving the buffer with no characters.

Now the code will work properly as long as you enter the input correctly.

If there's more than a single character left in the buffer (for any reason), use the following code to flush i/p stream.


Flushing stdin

To flush the input stream try one of the following ways.

    scanf("%*[^\n]");
    getchar();

or

    int ch;
    while((ch = getchar()) != '\n' && ch != EOF);

use it only when you are certain that the buffer isn't empty otherwise in either case the code expects/prompts for an input.


scanf()

 scanf("%d, %d", &num1, &num2);

Unless you wrote it intentionally ',' and space (' ') are redundant. If that's the case scanf() expects two integers to be seperated by a comma and a possible whitespace(s).

  • Thank you. That worked. But can you please explain how adding a space before `%c` in `scanf(" %c", &opr);` in fixes the issue? – Harshit Jindal Jun 13 '17 at 16:19
  • "If that's the case scanf() expects two integers two be seperated with a comma and a possible whitespace(s)." The program is working in both the cases (with and without a space after a comma. It always does. – Harshit Jindal Jun 13 '17 at 16:20
  • So basically adding a space will still work even if i don't have any newline character in the buffer? – Harshit Jindal Jun 13 '17 at 16:24
  • yes, that's right. read man page of `scanf` for more info on its behaviour. –  Jun 13 '17 at 16:27