I'm new to programming and I was trying to make a calculator and I'm adding a while loop, so that if you want to repeat you just type "1" and the program repeats. The problem is if I repeat it the scanf()
breaks and no longer allows me to type something into the command line. (I am using Visual C++ Windows Console Application)
I was trying to use fflush(stdin)
to clear the keyboard buffer, this did not work either.
#include "pch.h"
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
void main() {
char v;
int exit=1;
while (exit == 1) {
v = 0;
//Read what type of calcualtion the user wants to do.
printf("Type (+,-,*,/): ");
fflush(stdin);
scanf("%c", &v);
//system("cls");
//show the user for 2 sec what he chose
printf("Type you chose: %c", v);
Sleep(2000);
//system("cls");
//here the calcualtion will take place.
switch (v) {
case '+':
printf("\nTBD +");
break;
//Here are some more cases that i have excluded.
default:
printf("Please only use '+,-,*,/' above\n");
exit = 1;
break;
}
printf("\n do you want to repeat (1==yes|0==no): ");
scanf_s("%d", &v);
}
}
The result when this program runs looks like this:
Type (+,-,*,/): +
Type you chose: +
TBD +
do you want to repeat (1==yes|0==no): 1
Type (+,-,*,/): Type you chose:
Please only use '+,-,*,/' above
do you want to repeat (1==yes|0==no):
The result should look something like this:
Type (+,-,*,/): +
Type you chose: +
TBD +
do you want to repeat (1==yes|0==no): 1
Type (+,-,*,/): +
Type you chose: +
TBD +
do you want to repeat (1==yes|0==no): 1
To make your original code work
fflush(stdin)
asfflush()
is undefined for input streams.scanf("%c", &v);
toscanf(" %c", &v);
(mind the space before the conversion specifier%c
) to makescanf()
skip leading whitespace.scanf_s("%d", &v);
toscanf_s("%d", &exit);
. The compiler should have warned you about a type mismatch between conversion specifier%d
and the argument&v
(int*
vs.char*
). If it didn't you should increase the warning level of your compiler.Possible implementation with error checking on input using
scanf()
:void
in C, henceint main(void)
.scanf()
returns the number of successful assignments. Check that return value and handle input errors. Never trust the user.%*[^\n]
consumes all characters until a newline character is found and discards them. That way no garbage is left in the input buffer afterscanf()
. Note that this will consider successful conversions followed by garbage valid input. If you'd want to treat that as an input error you'd have to use more sophisticated methods.There's a lot of issues with your code. For one, you didn't need the windows header or needed to use
scanf_s
. Alsofflush(stdin)
results in undefined behavior. You should clear the input stream yourself. As an alternative toscanf
, usefgets
orfgetc
and perform the conversion yourself. The other issue in your code is you're resetting the value of v at the beginning of the loop. And then you give a default value of 1 to x, but checkwhile(x==1)
You're also trying to run the code at least once regardless of the initial condition anddo while
loops are a better alternative towhile
in this case. Also just for naming convention if you're continuing the loop atexit == 1
, that's misleading. Ifexit == 1
, then you should terminate the loop. it's very convoluted and confusing code. Let me try to clean it up for you.We give v a size of 32, although if we are only entering 1 character then a size of 3 is sufficient. Mainly because entering a single character with fgets will consume three bytes. But since we are taking an integer value at the end of the loop, we want to make sure there's enough room in the buffer. In case the user enters 123 for example, the buffer will still be fine and extra bytes will not remain in the stream.