Unwanted multiple menu prints in a while loop program in C [duplicate] - c

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 5 years ago.
C beginner here and I'm trying to learn to write a menu program. Below is my code
//A test file to test functions
#include <stdio.h>
#include <stdlib.h>
int enterChangeChar();
void printMenu();
char C = ' ';
int main()
{
char inputVal;
while (1)
{
printMenu();
scanf("%c", &inputVal);
switch (inputVal)
{
case 'c': enterChangeChar(); break;
case 'q': exit(0);
}
}
return 0;
}
int enterChangeChar()
{
int input;
printf("Would you like to Enter or Change the Character value?\n\n");
printf("Enter 1 to Assign OR 2 to Change the value of C: \n");
scanf("%d", &input); //input a integer value
if(input == 1)
{
printf("Enter a character: \n");
scanf(" %c", &C);
printf("You entered: %c", C);
}
else if (input == 2)
{
printf("Change Value option selected\n");
}
return 0;
}
void printMenu()
{
printf("Select a menu choice from the options below: \n\n");
printf(" OPTIONS INPUT\n");
printf("Enter/Change Character 'c'\n");
printf("Quit Program 'q'\n\n");
printf("Enter your CHOICE:\n");
}
when I run the program. The menu is printed twice after I input a character. Why is the program doing so?
Select a menu choice from the options below:
OPTIONS INPUT
Enter/Change Character 'c'
Quit Program 'q'
Enter your CHOICE:
c
Would you like to Enter or Change the Character value?
Enter 1 to Assign OR 2 to Change the value of C:
1
Enter a character:
v
You entered: v
Select a menu choice from the options below:
OPTIONS INPUT
Enter/Change Character 'c'
Quit Program 'q'
Enter your CHOICE:
Select a menu choice from the options below:
OPTIONS INPUT
Enter/Change Character 'c'
Quit Program 'q'
Enter your CHOICE:
q
EDIT: just added the printMenu() function code which I missed out earlier.
Edit 2: Maybe my question is not clear enough. The problem is not with getchar and scanf. The problem is that the menu prints twice after user inputs a character even though it's only called once in the whole program.
Edit 3: Final Edit: Guys I got it now. \n was in the input buffer and whenever choice was given, it was counted as input so the menu was printed multiple times. Thanks for the help.

There are unused newline characters '\n' in your input stream that need to be drained.
scanf() often causes confusion because it will leave the trailing '\n' in the input stream. In your case, the newline is getting picked up by the subsequent getchar().
int main()
{
while (1)
{
char inputVal;
printMenu();
do {
inputVal = getchar();
} while (inputVal == '\n');
switch (inputVal)
{
case 'c': enterChangeChar(); break;
case 'q': exit(0);
}
}
return 0;
}

Related

This C program does not work properly if I enter letters

If I enter numbers everything works fine. If I enter letters the program no longer works. What am I doing wrong?
P.s. Then I will connect other programs in the form of functions and I want them to be able to run from the menu and then return to the selection menu again
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
main ()
{
int a;
do {
printf("Enter number of programm: \n 1) First programm \n 2) Second programm \n 3) Third programm \n ");
scanf("%d", &a);
switch (a){
case 1: printf("Start My first programm \n"); break;
case 2: printf("Start My second programm \n"); break;
case 3:printf("Start My third programm \n"); break;
default: printf("There is no such program \n"); break;
}
} while (a != -1);
}
The problem is that scanf("%d", &a) only gets numbers because
a. int a can only store numbers and
b. "%d" only gets numbers
To get letter and number input you can do this:
char a[100];
fgets(a, sizeof(a), stdin); // Store input in a, read the buffer until sizeof(a), and finally read from stdin
However, you cannot compare strings in a switch so you will have to use if statements and strcmp from string.h

getchar() doesnt wait for enter press [duplicate]

This question already has answers here:
getchar does not stop when using scanf
(5 answers)
Closed 3 years ago.
I started C just a while ago (same as coding), so I`m a noob.
My Goal:
to state that the user hasn't entered a or b and then wait for the user to press enter to return to the calculator menu.
My problem:
getchar() doesn't wait for me to press enter. (Case 3)
#include <stdlib.h>
int main()
{
for (int i = 0;i == 0;){
int options=0,enteredA=0, enteredB=0;
float *a, A, *b, B, *c, C;
a=&A,b=&B,c=&C;
printf ("Calculator\nAvailable options:\n[1]Enter value for A\n[2]Enter value for B\n[3]Addition\n[9]Exit\n");
scanf ("%d",&options);
system ("clear");
switch (options) {
case 1:
printf("Enter a value for A:");
scanf ("%f",&*a);
enteredA++;
break;
case 2:
printf("Enter a value for B:");
scanf ("%f",&*b);
enteredB++;
break;
case 3:
if ((enteredA==0) | (enteredB== 0)){
printf("A and B are not initialized yet. Please enter a value in the menu.\nPress [Enter] to continue to the menu:\n");
fflush(stdin);
getchar();
break;
} else{
printf("%f+%f=%f\n",*a,*b,*c=*a+*b);
fflush(stdin);
getchar();
break;
}
break;
case 9:i++;break;
}
system("clear");
}
printf("Calculator Shut Down");
return 0;
}
In the following line:
scanf ("%d",&options);
you actually enter a number, and a newline character. The scanf function reads only the number. It leaves the newline (\n) in the input stream.
When you call getchar(), it will find a newline in the input stream. Hence, it will read it without waiting for user input. It only wait for user input if it didn't find anything in the input stream.
A possible workaround for this is to call getchar two times instead of one.
The first call will read the already existing newline in the stream. The second call won't find anything in the input stream. So, it will wait for user input as you expect.
I have some small comments that aren't related to your question:
You use scanf ("%f",&*a);. Why not just scanf("%f", a); or scanf("%f", &A); ?
Why you even create a pointer a for the variable A ?
I don't think you really need the variable c as well.
You don't need the variable i in the loop as well.
At the beginning of the loop, you keep re-initializing enteredA and enteredB variables to zero. That way, the condition in case 3: will be always true. You need to move these variables outside of the loop.
Your code also missing a #include <stdio.h>.
I'd simplify things like the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int enteredA = 0, enteredB = 0;
while (1)
{
int options;
float A, B;
printf ("Calculator\nAvailable options:\n[1]Enter value for A\n[2]Enter value for B\n[3]Addition\n[9]Exit\n");
scanf("%d", &options);
getchar(); // The extra getchar to read the newline left in the stdin.
system ("clear");
switch (options)
{
case 1:
printf("Enter a value for A:");
scanf("%f", &A);
enteredA++;
break;
case 2:
printf("Enter a value for B:");
scanf ("%f", &B);
enteredB++;
break;
case 3:
if (enteredA ==0 || enteredB == 0)
{
printf("A and B are not initialized yet. Please enter a value in the menu.\nPress [Enter] to continue to the menu:\n");
}
else
{
printf("%f + %f = %f\n", A, B, A + B);
}
getchar();
break;
case 9:
printf("Calculator Shut Down");
return 0;
}
system("clear");
}
}

Switch in C with while loop

I am new to C programming. I wrote a simple switch case but it is not executing as expected . Can some one tell me what is wrong here??
#include <stdio.h>
int main() {
int i;
char yes;
bool flag = true;
while(flag) {
printf("Enter the value");
scanf("%d",&i);
switch(i) {
case 1:
printf("Hi");
break;
case 2:
printf("Hello");
break;
}
printf("Enter Y or N to continue");
scanf("%c",&yes);
if (yes == 'N') {
flag = false;
}
}
return 0;
}
The result I am expecting is:
Enter the Value
1
Hi
Enter Y or N to continue
Y
Enter the Value
2
Hello
Enter Y or N to continue
N
But the result I am getting is :
Enter the value 1
HiEnter Y or N to continueEnter the value N
HiEnter Y or N to continue
When you hit Enter after typing in the first number, scanf read all numeric characters from the input stream except the newline character produced by that Enter hit. The newline character is not a part of the number. It is left in the input stream, unread, waiting for someone else to read it.
The next scanf("%c",&yes); discovered that pending newline charcter and it read it without waiting. The %c format specifier does not skip whitespace in the input, it just reads the first character it sees.
Replace your scanf with
scanf(" %c",&yes);
to make it skip whitespace. That way it will ignore that pending newline and actually wait for you to enter something.
In all your printf you need to add \n at the end.
For example on usage, see here: printf
This should work for you:
(You forgot all '\n' in your printf statements and add a space in your char scanf statements)
#include <stdio.h>
int main() {
int i;
char yes;
int flag = 1;
while(flag) {
printf("Enter the value\n");
scanf("%d",&i);
switch(i){
case 1:
printf("Hi\n");
break;
case 2:
printf("Hello\n");
break;
}
printf("Enter Y or N to continue\n");
scanf(" %c", &yes);
if (yes == 'N')
flag = 0;
}
return 0;
}
Output:
Enter the Value
1
Hi
Enter Y or N to continue
Y
Enter the Value
2
Hello
Enter Y or N to continue
N
It's not a problem with the switch statement. It's a problem with your output - there aren't line breaks ('\n'). For example, instead of printf("Hi"); you might want to have printf("Hi\n");, which adds a line space at the end.

My code repeats more than requried while loop

The problem is that when i type any character except for y or n it display this message two times instead to one)
This program is 'Calculator'
Do you want to continue?
Type 'y' for yes or 'n' for no
invalid input
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main ()
{
//program
//first to get two numbers
//second to get choice
int x=0,y=0,n=0;
char choice;
//clrscr(); does no work in devc++
system("cls"); //you may also use system("clear");
while(x==0)
{
puts("\t\tThis program is 'Calculator'\n\n");
puts("Do you want to continue?");
puts("Type 'y' for yes or 'n' for no ");
scanf("%c",&choice);
x++;
if(choice=='y')
{
y++;
puts("if this worked then we would continue to calculate the 2 no");
}
else if(choice=='n')
exit(0);
else
{
puts("invalid input");
x=0;
}
}
getch();
}
`
it looping twice because enter(\n) character is stored in buffer use scanf like this(add space before %c)
scanf(" %c",&choice);
That is because of the trailing new line after you enter y or n and hit enter key.
Try this out:
scanf("%c",&choice);
while(getchar()!='\n'); // Eats up the trailing newlines
If you input any character other than 'y' or 'n', control enters the :
else
{
puts("invalid input");
x=0;
}
block, which resets x to 0, Now the loop condition :
while(x == 0)
is true and hence it enters the loop again.
Also you may want to skip the trailing newline character while reading like :
scanf(" %c", &choice );

I cannot seem to loop again after selecting default in switch case in C

hello guys I coded something like kfc menu,and I got it to work(finally),but when I input something other than numbers for "menu",eg:the letter "A", I just can't get it to loop again to normal,instead it finishes the program
#include <stdio.h>
#include <stdlib.h>
int main()
{
char counter='y';
float totalprice=0;
while (counter=='Y' || counter=='y')
{
int menu;
float price=0;
printf("\nplease select from menu:");
scanf (" %i", &menu);
switch(menu)
{
case 1: {
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
}
case 2: {
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
}
case 3:{
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
}
default : {
printf ("\nplease enter proper number please:");
scanf("%2f", &menu);
break;
}
}
printf("\n\nadd order?(Y/N):");
scanf (" %c", &counter);
}
printf("\n\nThe total price is: %f", totalprice);
return 0;
}
You should use fgets() (reference here) first and then sscanf() (reference here), checking it's return value to see if it's a number.
char inputBuffer[MAX_BUFFER];
do
{
fgets(inputBuffer, MAX_BUFFER, stdin);
}
while(sscanf(inputBuffer, "%d", &menu) != 1)
You scanf with %f in the default case, I am fairly certain that is for floats. Use %d.
Remove scanf("%2f", &menu);
Switch in C does not support char in switch-case. Before you start switch-case validate the user input. If it is a number go into switch case otherwise display a user message to enter only numeric value
I recommend that you debug this by printing out the value of "counter" at various points in the loop (i.e. after you read it in, at the bottom of the loop, etc.). This will give you visibility into what your code is doing.
You can try something like this
#include <stdio.h>
int main()
{
char counter;
float totalprice=0;
int menu=0;
do
{
printf("\n1. one hotbox1=RM10.50");
printf("\n2. one hotbox2=RM10.60");
printf("\n3. one hotbox3=RM10.70");
printf("\nplease select from menu:");
scanf ("%d", &menu);
switch(menu)
{
case 1:
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
case 2:
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
case 3:
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
default :
printf ("\nplease enter proper number please:");
scanf("%d", &menu);
}
printf("\n\nadd more order?(Y/N):");
fflush(stdin); //to empty the input stream.
scanf("%c",&counter);
}while(tolower(counter) != 'n'); //tolower returns the lowercase character.
printf("\n\nThe total price is: %.2f", totalprice);
return 0;
}
When scanf("%i", &menu) tries to read an integer from the input, it finds A, which it cannot interpret as a number, so it does not read it(*). Then the next scanf continues reading the input from when the other left off and happily reads the letter 'A'. Since you loop as long as the read letter is either 'y' or 'Y' (which A is neither), it exits the loop.
(*) read up on the documentation of scanf to see how to tell if it encountered an error.
Note: scanf("%i", &menu) should be scanf("%d", &menu) as%d` is the formatting symbol for integers.
One solution would be to change the loop condition to:
while (counter!='N' && counter!='n')
{
...
}
This way you end the loop only if an explicit 'N' or 'n' is inputted.
Note: it won't help if you accidentally type 'n' for the menu item, so see the comment about the error handling above.

Resources