getchar not working in switch case (c) - c

Using a very simple calculator program that prompts a user for an operation to perform, followed by a prompt for two integers on which to perform this operation. The program is supposed to loop after these operations, except in the case where the user enters the character 'q', at which point the program is supposed to quit.
#include <stdio.h>
int main (void)
{
char c;
int number[2], num1, num2, result;
double num1d, num2d, resultd;
int done=1;
while(done)
{
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
c = getchar();
printf("\tplease enter a number \n");
scanf("%d",&number[0]);
printf("\tplease enter another number \n");
scanf("%d",&number[1]);
num1 = number[0];
num2 = number[1];
switch(c)
{
case('-'):
result = num1-num2;
printf("\nThe first number you entered subtracted by the second number is %d.\n", result);
break;
case('+'):
result = num1+num2;
printf("The first number you entered added to the second number is %d.\n", result);
break;
case('*'):
result = num1*num2;
printf("The first number you entered multiplied with the second number is %d.\n", result);
break;
case('/'):
num1d = (double) num1;
num2d = (double) num2;
resultd = num1d/num2d;
printf("The first number you entered divided by the second number is %g.\n", resultd);;
break;
case('q'):
printf(" Now Exiting...\n");
done=0;
break;
default:
puts("Invalid key pressed. Press q to exit");
break;
}
}
return 0;
}
Works correctly for a single calculation, but subsequently performs oddly; in particular it prints
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
printf("\tplease enter a number \n");
altogether.
The standard method of clearing the input buffer while (getchar() != '\n'); doesn't fix this. One out of two times that this text displays incorrectly the user can still use the program as if the instructions were displaying as they should (so the user can type an operation such as +, carriage return, and then some integer and a carriage return, and the program will perform correctly from that point on) Every other time however the program will put "Invalid key pressed. Press q to exit" regardless of input.

What everyone else here is saying is true, getchar() returns an int but that's not your problem.
The problem is that getchar() leaves a newline character after you use it. If you're going to use getchar() you must always consume the newline char afterwards. This simple fix:
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
c = getchar();
getchar(); //<-- here we do an extra getchar for the \n
printf("\tplease enter a number \n");
scanf("%d",&number[0]);
printf("\tplease enter another number \n");
scanf("%d",&number[1]);
and that will eliminate the problem. Every time you type <somechar><enter> it's really putting two characters on the buffer, for example if I hit + and enter I'm getting:
'+''\n' // [+][\n]
getchar() will only get the first of these, then when getchar() is called again it won't wait for your input it will just take that '\n' and move on to the scanf()

You shouldn't mix character-by-character with more high-level input functions such as scanf(). It's better to use scanf() to input the command character too, but of course then you will have to press enter after the command. I believe this it the root cause of your problems.
As an aside, note that getchar(), despite it's name, returns int, not char. This is because it can return EOF which is a special constant whose value is different from that of all characters.
Further, you should always check the return value of I/O functions like scanf(), they can fail if the input doesn't match the pattern string.
As a debugging hint, you can of course print the value of c before interpreting it, so you can easier see and understand the flow of the program.

I'm guessing it works the first time, but not the next time. This is because the scanf calls leaves the newline in the input buffer so the next time getchar is called in the loop it will return the newline character. Add a space after the format in the scanf calls
scanf("%d ",&number[0]);
and it will discard remaining whitespace from the buffer.
Use a debugger to step through the code and check the variables to verify.

Your getchar should return int. The reason is as below
getchar reads characters from the program's standard input
and returns an int value suitable for storing into a char.
The int value is for one reason only: not only does getchar
return all possible character values, but it also returns an
extra value to indicate that end-of-input has been seen.
The range of a char might not be enough to hold this extra value,
so the int has to be used.
So basically you need to change char c to int c in your code

Related

why the below code is taking two input on single execution of scanf funcion

#include<stdio.h>
#include<conio.h>
int main()
{
int Dividend,divisor;
printf("Checking Divisiblity of 1st number with 2nd number \n\n") ;
printf("Enter Number \n") ;
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
if(Dividend % divisor == 0)
{
printf("Number %d is divisible by %d",Dividend,divisor) ;
}
else
{
printf("Number %d is not divisible by %d",Dividend,divisor) ;
}
getch();
return 0;
}
Above is my code that i have written in C ;
on running this program . Only on first execution of scanf function if i give two input space seperated , the second input is going on right variable . and on hitting enter i am getting result . I am not understanding how is this happing .
When space is pressed, scanf doesn't see anything yet. Something happens only after enter is pressed. It then takes everything to the left of the space character and assigns it to the first variable, and everything to the right of the space character and assigns it to the second variable.
If you don't press the spacebar, scanf will interpret everything you type as a single number and will assign it to the first variable.
Instead what you may want to do is use the %c format specifier to read a single character at a time. You can then check if the character is a space character and if it is, you can break out of the loop. Otherwise, you can keep reading characters until you reach a space character.
stdin is line based by default. Your program gets nothing until you press enter. Then your program has the entire line of text available.
Result of this is, that scanf, getchar, fgets, etc calls will not return until you press enter. After enter press, entire line is available and the function starts to process it.
scanf is kinda special, that if you have int parsed_count = scanf("%d%d", &a, &b);, it will read two integers, no matter how many times you press enter, so you can either do
1 2<enter>
Or you can do
<enter>
1<enter>
<enter>
2<enter>
and scanf will still read these two integers (it returns early if there is parse error, which is why you need to check the return value!).
And vice versa, if there is already input available, then scanf may return immediately, so if you have this code
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
and enter text
1 2<enter>
Then first scanf will wait for enter press, then consume the first integer, leaving 2<enter> still unread. Then there's print, and then 2nd scanf starts reading, skipping the whitespace and immediately getting 2nd integer. So you see
1 2 <- this is your typing echoed, not print from your program
Enter Divisor = <- printf printed this
If you want to take only one input per enter press, you can simply read characters until newline, because scanf leaves them there. Example loop to read until newline, or exit program at end of file/error:
while(true) {
int ch = getchar();
if (ch == EOF) exit(1);
if (ch == '\n') break;
}

Why are the if conditions not being executed?

This is a menu driven program asking for user's choice.
Why are if conditions not executed?
Output is attached.
Creating a program asking for user's input:
void main()
{
float a,b,ans=0;char ch,choice;
choice='y';
while(choice=='Y'||choice=='y')
{
printf("Enter two numbers \n");
scanf("%f %f",&a,&b);
printf("1.+for Addition\n");
printf("2.-for subtraction \n");
printf("3.*for multiplication \n ");
printf("4./for Division \n");
printf("Enter your choice of operation \n");
scanf("%c",&ch);
if(ch=='+')
ans=a+b;
else if (ch=='-')
ans=a-b;
else if(ch=='*')
ans=a*b;
else if(ch=='/')
ans=a/b;
else
{
printf("wrong choice entered\n");
}
printf("Answer is %f \n",ans);
printf("Do you want to coninue (Y/N)\n");
scanf("%c",&choice);
}
printf("program Terminated\n");
}
Output:
/* Enter two numbers
1010
22
1.+for Addition
2.-for subtraction
3.*for multiplication
4./for Division
Enter your choice of operation
wrong choice entered
Answer is 0.000000
Do you want to coninue (Y/N)
n
program Terminated
*/
The above is the output screen.
It doesn't perform operations.
When you input first 2 numbers, they are placed into variables a and b. BUT after entering those 2 numbers, you pressed enter. Computer sees that as new input and place it in first next appropriate variable that requires input. In this case it's your variable ch, and instead of +,-./ or *, ch has value of "new line". If you try to write value of ch on standard output as an integer, it will write number 10. It's ASCII character of new line. Simply adding getchar() after inputting first 2 numbers will collect that new line sign, and your next scanf will work properly.
By the way, you have same problem with your last input scanf("%c",&choice); because pressing enter after previous operation decision, will also cause your program not to work properly. Do the same thing for this part, or simply leave blank character before %c.
Try the following
scanf(" %c",&ch);
^^
and
scanf(" %c",&ch);
^^
Otherwise a next character is read that can be a white space character.
Take into account that according to the C Standard function main without parameters shall be declared like
int main( void )
scanf() does not consume trailing newlines. The skipped scanf() receives the newline from the previous line typed by the user and terminates without receiving more input as you would expect...
scanf() is a bit cumbersome with newlines. A possible solution would be to use fgets() to get a line from the console and then employ sscanf() to parse the received string.
Another, more targeted, solution would be to use " %c" in the format string of the last scanf() call. The %c format specifier does not consume leading whitespace on its own, which is why it gets the remaining newline, rather than a character typed by the user.

How to enter a letter to quit a program in C

I am new to C programming. I have been writing this code to add numbers and I just need help with this one thing. When I type the letter 'q', the program should quit and give me the sum. How am I supposed to do that? It is currently the number 0 to close the program.
#include <stdio.h>
int main()
{
printf("Sum Calculator\n");
printf("==============\n");
printf("Enter the numbers you would like to calculate the sum of.\n");
printf("When done, type '0' to output the results and quit.\n");
float sum,num;
do
{
printf("Enter a number:");
scanf("%f",&num);
sum+=num;
}
while (num!=0);
printf("The sum of the numbers is %.6f\n",sum);
return 0;
}
One approach would be to change your scanf line to:
if ( 1 != scanf("%f",&num) )
break;
This will exit the loop if they enter anything which is not recognizable as a number.
Whether or not you take this approach, it is still a good idea to check the return value of scanf and take appropriate action if failed. As you have it now, if they enter some text instead of a number then your program goes into an infinite loop since the scanf continually fails without consuming input.
It's actually not as straightforward as you'd think it would be. One approach is to check the value returned by scanf, which returns the number of arguments correctly read, and if the number wasn't successfully read, try another scanf to look for the quit character:
bool quit = false;
do
{
printf("Enter a number:");
int numArgsRead = scanf("%f",&num);
if(numArgsRead == 1)
{
sum+=num;
}
else // scan for number failed
{
char c;
scanf("%c",&c);
if(c == 'q') quit = true;
}
}
while (!quit);
If you want your program to ignore other inputs (like another letter wouldn't quit) it gets more complicated.
The first solution would be to read the input as a character string, compare it to your character and then convert it to a number later. However, it has many issues such as buffer overflows and the like. So I'm not recommending it.
There is however a better solution for this:
char quit;
do
{
printf("Enter a number:");
quit=getchar();
ungetc(quit, stdin);
if(scanf("%f", &num))
sum+=num;
}
while (quit!='q')
ungetc pushes back the character on the input so it allows you to "peek" at the console input and check for a specific value.
You can replace it with a different character but in this case it is probably the easiest solution that fits exactly what you asked. It won't try to add numbers when the input is incorrect and will quit only with q.
#Shura
scan the user input as a string.
check string[0] for the exit condition. q in your case
If exit condition is met, break
If exit condition is not met, use atof() to convert the string to double
atof() reference http://www.cplusplus.com/reference/cstdlib/atof/

Program pauses at loop

I've got a simple C program, which loops to get an indefinite amount of numbers from the user (it's a CAS of sorts). I'm working on the program in multiple languages, and while the C++ version works perfectly, the C version stalls at the end of the loop, when the program asks for another user operation, requiring the user to input the operation twice. Here's how the program should work:
Enter an operation
4+2
6
6+2 // User adds 2 to the previous answer
8+x // User can continue adding like this indefinitely
Instead, here's what happens:
Enter an operation
4+2
6+2
// nothing happens until user enters "+2" again
+2
8+x
+x
[sum of 8+x]
and so on.
I initially thought this pause was caused by the program asking for user input twice, once at the start of the loop, and then at the end before looping. I put an iteration counter in the loop to determine what kind of input the program should get (either &num1,&op,&num2 or &op,&num2). For some reason, that didn't make a difference. Here's the relevant part of the code:
int opnubmer;
opnumber = 0;
printf("Enter an operation\n");
while(op != '=')
{
if (opnumber == 0)
{
scanf("%d%c%d",&num1,&op,&num2);
}
else if (opnumber != 0)
{
scanf("%s%d",&op,&num2);
}
switch(op)
{
case '+':
num2 += num1;
break;
case '-':
num2 -= num1;
break;
case '*':
num2 *= num1;
break;
case '/':
num2 /= num1;
break;
default:
printf("%s%c%s", "Unknown op: ", op, "\n");
exit(1);
}
printf("Solution: ");
printf("%d",num2);
opnumber++;
num1=num2;
}
Can anyone help me out?
It looks like you made a typo in the second scanf call, where you used %s instead of %c to read the op.
Furthermore, when using scanf to read input, you have to be very careful with whitespace. Trailing whitespace (including newlines) is left on the input stream, so the next time you read from the input stream, the whitespace is the first thing it'll see.
Instead of using scanf, use fgets to read the input one line at a time into a buffer, and then parse what you need out of that buffer. Eg. :
char line[256];
fgets(line, sizeof(line), stdin);
sscanf(line, "%d%c%d", &num1, &op, &num2);
It behaves absolutely fine, when you are not in the first iteration, you are looking for a string, even if you fix it with a change to %c your program expects only a character and a number not a number character number sequence.

scanf ignoring, infinite loop

int flag = 0;
int price = 0;
while (flag==0)
{
printf("\nEnter Product price: ");
scanf("%d",&price);
if (price==0)
printf("input not valid\n");
else
flag=1;
}
When I enter a valid number, the loop ends as expected. But if I enter something that isn't a number, like hello, then the code goes into an infinite loop. It just keeps printing Enter Product price: and input not valid. But it doesn't wait for me to enter a new number. Why is that?
When you enter something that isn't a number, scanf will fail and will leave those characters on the input. So if you enter hello, scanf will see the h, reject it as not valid for a decimal number, and leave it on the input. The next time through the loop, scanf will see the h again, so it just keeps looping forever.
One solution to this problem is to read an entire line of input with fgets and then parse the line with sscanf. That way, if the sscanf fails, nothing is left on the input. The user will have to enter a new line for fgets to read.
Something along these lines:
char buffer[STRING_SIZE];
...
while(...) {
...
fgets(buffer, STRING_SIZE, stdin);
if ( sscanf(buffer, "%d", &price) == 1 )
break; // sscanf succeeded, end the loop
...
}
If you just do a getchar as suggested in another answer, then you might miss the \n character in case the user types something after the number (e.g. a whitespace, possibly followed by other characters).
You should always test the return value of sscanf. It returns the number of conversions assigned, so if the return value isn't the same as the number of conversions requested, it means that the parsing has failed. In this example, there is 1 conversion requested, so sscanf returns 1 when it's successful.
The %d format is for decimals. When scanf fails (something other a decimal is entered) the character that caused it to fail will remain as the input.
Example.
int va;
scanf("%d",&va);
printf("Val %d 1 \n", val);
scanf("%d",&va);
printf("Val %d 2 \n", val);
return 0;
So no conversion occurs.
The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure
7.19.6. The scanf function - JTC1/SC22/WG14 - C
So you should note that scanf returns its own form of notice for success
int scanf(char *format)
so you could have also did the following
do {
printf("Enter Product \n");
}
while (scanf("%d", &sale.m_price) == 1);
if(scanf("%d", &sale.m_price) == 0)
PrintWrongInput();
Also keep in the back of your head to try to stay away from scanf. scanf or scan formatted should not be used for interactive user input. See the C FAQ 12.20
After the first number, a '\n' will be in the input buffer (the return you pressed to input the number), so in the second iteration the scanf call will fail (becouse \n isn't a number), scanf will not remove that \n from the buffer, so in the next iteration it will fail again and so on.
You can fix that by reading the '\n' with a getchar() call after scanf.
The "answers" that say it will because there is a '\n' in the buffer are mistaken -- scanf("%d", ...) skips white space, including newlines.
It goes into an infinite loop if x contains 0 and scanf encounters a non-number (not just whitespace) or EOF because x will stay 0 and there's no way for it to become otherwise. This should be clear from just looking at your code and thinking about what it will do in that case.
It goes into an infinite loop because scanf() will not consumed the input token if match fails. scanf() will try to match the same input again and again. you need to flush the stdin.
if (!scanf("%d", &sale.m_price))
fflush(stdin);
Edit: Back when I first wrote this answer, I was so stupid and ignorant about how scanf() worked.
First of all let me clear something, scanf() is not a broken function, if I don't know how scanf() works and I don't know how to use it, then I probably haven't read the manual for scans() and that cannot be scanf()'s fault.
Second in order to understand what is wrong with your code you need to know how scanf() works.
When you use scanf("%d", &price) in your code, the scanf() tries to read in an integer from the input, but if you enter a non numeric value, scanf() knows it isn't the right data type, so it puts the read input back into the buffer, on the next loop cycle however the invalid input is still in the buffer which will cause scanf() to fail again because the buffer hasn't been emptied, and this cycle goes on forever.
In order to tackle this problem you can use the return value of scanf(), which will be the number of successful inputs read, however you need to discard the invalid inputs by flushing the buffer in order to avoid an infinite loop, the input buffer is flushed when the enter key is pressed, you can do this using the getchar() function to make a pause to get an input, which will require you to press the enter key thus discarding the invalid input, note that, this will not make you press the enter key twice whether or not you entered the correct data type, because the newline character will still be in the buffer. After scanf() has successfully finished reading the integer from input, it will put \n back into the buffer, so getchar() will read it, but since you don't need it, it's safe to discard it:
#include <stdio.h>
int main(void)
{
int flag = 0;
int price = 0;
int status = 0;
while (flag == 0 && status != 1)
{
printf("\nEnter Product price: ");
status = scanf("%d", &price);
getchar();
if (price == 0)
printf("input not valid\n");
else
flag = 1;
}
return 0;
}

Resources