reading user command to continue does not work - c

I'm Writing a program for Billing System. I'm using do-while loop in my program. And the program is executed according to user input. If the user want to continue the execution, the program will be continue. But I Got a prob in Execution. I was trying my logic in simple do-while loop. The same Problem arises for simple do-while loop also.
Problem is: If the input is yes, the program does not get the further input from user.
That simple do-while loop is:
#include <stdio.h>
main()
{
int c;
char ch;
do
{
printf("enter the no less then 4:");
scanf("%d",&c);
switch(c)
{
case 1:
printf("In 1\n");
break;
case 2:
printf("In 2\n");
break;
case 3:
printf("In 3\n");
break;
}
printf("do u want to continue?:");
ch=getchar();
}while(ch=='y');
}
If i put while(ch != 'n') instead of while(ch=='y') the program working fine. I couldn't understand the problem behind this. Please Help me to rectify this. And Explain about this problem.Thank u in advance.

first run, 3 is printed, user types "y" and presses return
getchar() reads 'y' and program loops
second time, getchar() reads newline character from the previous key press
newline is not 'y' so program does not loop

Several problems:
getchar returns an int, not a char, so ch must be an int just like c.
scanf needs a pointer to go with the %d, so it should be scanf("%d", &c);
The while should rather test for EOF, as in while ((ch = getchar()) != EOF)
Note that the input will contain the newlines, which you should deal with (e.g. ignore).
This should be quite robust:
#include <stdio.h>
int main(void)
{
int c, ch;
for (;;) {
printf ("Enter a number (1, 2 or 3):");
fflush (stdout);
if (scanf ("%d", &c) == 1) {
switch (c) {
case 1:
printf ("In 1\n");
break;
case 2:
printf ("In 2\n");
break;
case 3:
printf ("In 3\n");
break;
}
printf ("Do you want to continue? [y/n]:");
fflush (stdout);
while ((ch = getchar ())) {
if (ch == 'y')
break;
else if (ch == 'n' || ch == EOF)
return 0;
}
} else {
printf ("That was not a number. Exiting.\n");
return 0;
}
}
}

While(ch=='y') or the character whatever in while() it will sent to case 3 as per your coding....y is pressing ,it wil sent to case 3 otherwise it wont work

Instead of reading the answer using getchar, use fgets.
As others explained, the second getchar call gives you the newline, which was typed after the first y.
With fgets, you'll get everything the user typed. Then you can check if it's y (just check the first character, or use strcmp).

Related

Having problems with creating menu in C using do..while and if..else statement

I am new in this world of programming. I am learning programming at my school. My teacher recently ask the class to create a menu with limited selection that will end with a sentinel value.
So here's my coding:
#include <stdio.h>
void menu(void);
void choice1();
void choice2();
void choice3();
char choice;
int main() {
do {
menu();
if (choice =='1')
choice1();
else if (choice =='2')
choice2();
else if (choice =='3')
choice3();
else if (choice =='4')
break;
else
printf("Invalid character.");
} while (choice != '4');
return 0;
}
void menu(void) {
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
scanf("%c", &choice);
}
void choice1() {
printf("\nChoice 1\n");
}
void choice2() {
printf("\nChoice 2\n");
}
void choice3() {
printf("\nChoice 3\n");
}
When I try to run it, by putting the number 1, 2, 3, the output came out but after that the function menu() and also the line "Invalid character." came out. As for as the other character, the menu() and the "Invalid character" came out twice. Number 4 does end the program. Is there any improvement that I can make to make sure the menu() and the line "Invalid character." does not come out unnecessarily?
In line-buffered input, the newline character lingers in the buffer after you read a single character for 'choice' and hence you get Invalid character. unintentionally.
You are required clear the buffer after reading the choice
scanf("%c", &choice);
while(getchar()!='\n')
/* Wasting the buffer
* Hence ensuring that the character you enter
* is indeed considered for 'choice'
*/
;; // Do nothing in particular
As a side note, your program looks like a typical use-case for the switch-case command and maybe your teacher expects you to use it.
Considering the scenario mentioned by #chqrlie in [ this ] comment, the workaround is to add after
scanf("%c", &choice);
the below lines
int c;
while ((c = getchar()) != EOF && c != '\n')
;; //Wasting the buffer
The problem is simple: the terminal is line buffered: you must press enter for the input to become available to your program, the first scanf("%c", &choice) retrieves the character typed and the second call retrieves the linefeed ('\n') that was generated by the enter key.
There are multiple ways to avoid this problem. You can add a space in the scanf format before the %c: scanf(" %c", &choice); or you can read characters after the first until you get a '\n'.
Note that you must check the return value of scanf to avoid undefined behavior if the user enters an end of file. It is also advisable to avoid global variables: the function menu() should return the choice specified. Using a switch statement is also more idiomatic for this.
Here is a corrected version:
#include <stdio.h>
int menu(void);
void choice1(void);
void choice2(void);
void choice3(void);
int main(void) {
int ch;
for (;;) {
switch (ch = menu()) {
case '1': choice1(); continue;
case '2': choice2(); continue;
case '3': choice3(); continue;
case '4':
case EOF: break;
default: printf("Invalid character %c\n", ch); continue;
}
break;
}
return 0;
}
int menu(void) {
char choice;
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf(" %c", &choice) == 1)
return choice;
else
return EOF;
}
void choice1(void) {
printf("\nChoice 1\n");
}
void choice2(void) {
printf("\nChoice 2\n");
}
void choice3(void) {
printf("\nChoice 3\n");
}
As already mentioned in other answers the problem is the newline character.
When you press 1 followed by enter, you'll get two chars, i.e. 1 and \n. So your loop runs twice and prints Invalid character when \n is processed.
Here is an alternative solution for your problem. Just add a space before %c.
scanf(" %c", &choice);
This works because the space will match any number of white-space characters and thereby match the \n and remove it.
From the man page:
A sequence of white-space characters (space, tab, newline,
etc.......). This directive matches any amount of
white space, including none, in the input.
Additional comments
You should always check the value returned by scanf to make sure you read the correct number of values.
if (scanf(" %c", &choice) != 1)
{
// Add error handling ....
// For instance you could terminate the program like
exit(1);
}
In your program choice is a global variable. In general global variables should be avoid if possible. In your case you could make choice a local variable in main and let menu return a char. Like:
// char choice; Remove global variable
int main() {
char choice; // Add local variable
do {
choice = menu(); // Assign to local variable
.....
}
char menu(void) { // Make the function return a char
char choice; // Add local variable
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf("%c", &choice) != 1) exit(1); // Assign to local variable
// On failure -> exit
return choice; // Return value of local variable
}
You can write scanf(" %c",&choice); (with whitespace) instead of scanf("%c",&choice);
When I try to run it, by putting the number 1, 2, 3, the output came
out but after that the function menu() and also the line "Invalid
character." came out.
It's happening because of the new line character you press after each number. It's itself a character and loop is iterated one more time for this. As it is an invalid character, that's why "Invalid character." is showing.
Try using getchar() after scanf().
Edit: fixed my previous while loop which may exit incorrectedly:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (1) {
char c = scanf("%d",&choice);
if (c == EOF || choice == 4) break;
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}
You can use function if you want, but not necessary in this case. You need to understand how many times your loop actually runs and compare it to that you expect.
My previous code:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (scanf("%d", &choice) && choice != 4) {
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}

How to stop infinite loop when character is pressed in place of int?

Here, user is asked to press respective key to perform particular function, but suppose I pressed any character value such as "g", it goes into an infinite loop.
How to solve this issue?
int item,choice;
clrscr();
while(1)
{
printf("QUEUE SIMULAtOR");
printf("\n1:Insert");
printf("\n2:Delete");
printf("\n3:Display");
printf("\nEnter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1:qinsert();
break;
case 2:item=qdelete();
if(item!=-1)
printf("Deleted item is %d",item);
break;
case 3:printf("\nElements in the queue are:");
qdisplay();
break;
case 4:exit(0);
default:printf("\nWrong choice try again:");
}
}
Add this after the scanf()
char ch;
while( ( ch = getchar() ) != '\n' && ch != EOF );
This should do the trick.
The problem was caused as scanf() does not store characters ( since you are using %d ) and thus they remain in the input buffer. The next scanf() tries to read this and again, instead of storing it, ignores it and it remains in the buffer. This process repeats, which causes the infinite loop.
The code I gave reads all the characters in the buffer, thus reomoving the infinite loop.
Cheers... Hope this helps you :)
This is a really awesome question.You must try to use a break statement inside a if().
Example:
void main()
{
int n;
printf("Enter the number 5\n");
while(1)
{
scanf("%d",n);
if(n==5)
{ break;
}
else
{
printf(" enter the correct num again \n");
}
}
printf(" you've entered the right number\n");
}
There you go this program will run until u enter the number 5
If you want any integer
you could use isdigit() function which is under the header file ctype

Reading expressions for postfixed notation calculator by using scanf

I have a problem with the input for a postfixed notation calculator in C.
My teacher asked me to use scanf("%s",token) to get the input. To stop reading tokens, I check if the value returned by scanf is EOF. It works if I use input redirection when testing, but if I write the expression on the Windows cmd I fall into an endless loop. How can I stop scanf when I simply press enter without entering a string?
Here's the code:
#include <stdio.h>
#include <ctype.h>
#include "stack.h"
int main(){
int a,b,t,stop;
char token[10],c;
do{
stop = scanf("%s",token);
if (stop == EOF){
break;
}
if (isdigit(token[0])){
t = atoi(token);
push(t);
}else{
a = top();
pop();
b = top();
pop();
c = token[0];
switch(c){
case '+': t = a + b;
break;
case '-': t = a - b;
break;
case '*': t = a * b;
break;
case '/': t = a / b;
break;
}
push(t);
}
} while(1);
printf("Result: %d\n",top());
}
The problem is in the if block after the stop variable inizialisation, I think. Sorry for my English, I'm an Italian student, I tried to be as neat as I can.
"How can I stop scanf when I simply press enter without entering a string?"
Using scanf() to read '\n' (Enter) is challenging. fgets() or fgetc() is a better approach. But the following shows how to nearly do it with scanf().
The %s in scanf("%s",token); first consumes leading white-space including '\n'. Code must first detect any potential '\n' before calling scanf("%s",token);.
char ws[2];
// Consume white-space, but not \n
scanf("%*[ \f\r\t\v]"); // Depending on locale, this may not be a complete list
if (1 == scanf("%1[\n]", ws) {
break;
}
stop = scanf("%s",token);
if (stop == EOF){
break;
}
A cleaner way to do this.
int ch;
while (isspace(ch = fgetc(stdin)) && ch != '\n');
if (ch == '\n') {
break;
}
ungetc(ch, stdin);
stop = scanf("%s",token);
if (stop == EOF){
break;
}
Only one more question: to stop the program, I had to type ctrl+z
twice. Can you tell me why?
Usually the C standard input in line buffered text mode is implemented by calling a system specific function which reads a line and returns the number of characters in it (including the newline character); when the number 0 is returned, this is considered EOF. Now, when you enter "3 5 +(crtl+z)(ctrl+z)", the first Ctrl-Z ends the input line and causes the reading function to return 5, but this does not indicate EOF to the standard input functions; only after the second Ctrl-Z ist pressed without intervening input, 0 is returned and recognized as EOF.

Designing a menu, repeated message

I'm working on a console application which is supposed to have a little menu to choose from different options. I came up with two ideas, in one of which I used int to be a choice variable and it gets me into an infinite loop whenever I enter a character other than numeric. Another one though seems clearer to me but I can't understand why I get "Choose an option Not a digitChoose an option" message even if I choose a valid theoretically option Please let me know what's the problem with my code. I enclose the second example I mentioned.
#include <stdio.h>
#include <ctype.h>
void F1()
{
printf("Function 1\n");
}
void F2()
{
printf("Function 2\n");
}
void F3()
{
printf("Function 3\n");
}
int main()
{
char c;
printf("MAIN MENU\n"
"1. Function 1\n"
"2. Function 2\n"
"3. Function 3\n"
"4. Exit\n");
while(1)
{
printf("Choose an option ");
scanf("%c", &c);
if(isdigit(c) == 0) printf("Not a digit");
else
{
if(c == '1') F1();
else if(c == '2') F2();
else if(c == '3') F3();
else if(c == '4') break;
else printf("Wrong option");
}
}
return 0;
}
You need to flush your input buffer to clear the \n character leftr behind by previous call of scanf. Place a space before %c in scanf
scanf(" %c", &c);
or in general you flush input buffer by placing this snippet after each call of scanf:
int c
while((c = getchar()) != '\n' && c != EOF);
The first call to scanf() will real your typed character, and the second one will read a newline character.
You need to finish reading the line after your call to scanf():
int c2;
while((c2=getchar()) != '\n' && c2 !=EOF) {}

Why %d is require before entering character?

I have tried following code there is require %d before entering character. That is an after switch loop in code.
#include<stdio.h>
#include<conio.h>
void sum();
void mul();
void main()
{
char ch;
int c;
clrscr();
do
{
printf("\n\n Enetr choice ");
printf("\n\n\t 1: SUM \n\n\t 2: MUL");
scanf("\n\n\t %d",&c);
switch(c)
{
case 1:
sum();
break;
case 2:
mul();
break;
default:
printf("\n\n hhhh..... ");
}
printf("\n\n Want u calcualte again");
//scanf("%d");
scanf("%c",&ch);
printf("\n ch value is %c",ch);
}while(ch=='y'|| ch=='Y');
getch();
}
void sum()
{
int s;
s=10+50;
printf(" SUM: %d",s);
}
void mul()
{
int s;
s=10*50;
printf(" SUM: %d",s);
}
Here in this code after switch I tried to input character but without the scanf statement which is in comment is require while you input character. without that scanf statement compiler does not take character input. so please give me solution.
Its because you have to "eat up" the newline from previous input
You don't have to use %d.
Instead use:
while((c = getchar()) != '\n' && c != EOF) ;
in place of
//scanf("%d");
to discard the newline.
this is the problem occurred due to the insertion of next line character i.e. '\n' instead of following statement
scanf("%c",&ch);
you should use
scanf("\n%c",&ch);
Now what will happen firstly control goes to new line and then it will insert or input the character, just change this statement you will find your program execute properly...
You have to consume new line character.
You can add space before %c in your scanf statement to ignore white space
You should change
scanf("%c",&ch);
to
scanf(" %c",&ch);//this makes scanf ignore white spaces like new line, space etc.
or use getchar() to do it.
c=getchar();
For more insight go to question:
scanf() function doesn't work?
Another method that tells scanf to consume or recognize white space (and a new line is considered white space) is to code:
char ch[2];
...
scanf("%1s", &ch);
...
if (ch[0] == 'x' etc.

Resources