I made a switch statement, however, it only works with constants already set. If I try to use it with user input, only one of the cases work, every other one doesn't. Now no matter what I enter, it always uses the default case. I tried adding another getchar() to clear the \n character from the buffer but this isn't making a difference. Ill post the entire switch statement here :
char option=' ';
option=getchar();
switch(option){
//Parallel resistance calculations
case 'p':
CLEAR
//PResistance();
printf("RESISTANCE");
getchar();
break;
//Ohm's Law calculations
case 'o':
CLEAR
printf("OHM");
//Ohm();
break;
//Exits program
case 'q':
printf("Good bye! Stay safe in the laboratory! :)\nPress any key to exit");
getchar();
exit(0);
break;
//Error checking
default :
printf("Invalid input, Try again");
break;
}
}
while (option!='q');
I commented out the functions so I could use the print statements to test if its working.
Whenever you input a character or string from stdin in C, always make sure there is no \n in the input buffer. To do this, always getchar() after taking integer or float inputs.
In your case, maybe you've inputted an integer before inputting the character. So try to write a getchar() before taking the character input.
Related
I tried to calculate the tot(total fee) in the do-while loop, but all I get is tot=0.00?! Why is this happening? And after that I get a message: it said the variable fee is not being initialised?
#include<stdio.h>
int main(void)
{
int cofno;
float tot=0.0;
float fee;
char option;
do{
printf("Enter cofno: ");
scanf("%d",&cofno);
if(cofno>0)
{
printf("Key in (h/c): ");
scanf("%c",&option);
getchar();
switch(option)
{case 'h':fee=cofno*1.80;
break;
case 'c': fee=cofno*2.50;
break;
}
tot=tot+fee;
//the program will repeat until the user key in negative value or zero
}
}while(cofno>0);
printf("\ntot=RM%.2f \n\n",tot);
return 0;
}
scanf(" %c",&option); This will solve the problem for you. The reason the ' ' is provided in the scanf so that it can consume the white space characters.
What happened earlier was that your character input got the \n from previous input.
To check the thing that it inputted \n try outputting the option like this
printf("[%c]",option); you will see output
[
]
Also the break statement you provide is breaking for the case staement. Not the while loop. You have infinite loop now. You can solve this with a added condition.
...
tot=tot+fee;
if(option == 'c' || option =='h')
break;
...
Even more simply, you could have changed the while condition overall and make it like this
while(cofno<=0);
this conforms to your idea the program will repeat until the user key in negative value or zero more suitably.
I'm trying to write a simple menu in C.
This is my proposed code:
while (end == 0) {
printf("Main menu\n");
printf("=========\n");
printf("1) Option 1.\n");
printf("2) Option 2.\n");
printf("3) Option 3.\n");
printf("4) Option 4.\n");
printf("0) Exit");
printf("\n");
printf("Choose an option: ");
fgets(&menu_option,1,stdin);
switch (menu_option) {
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
}
}
However, when executing this code, the loop never ends.
What's wrong?
Thank you.
EDIT: when I say "the loop never ends", I want to say that I can't write any option because the menu appears again and again.
From fgets
The fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, or a is read and transferred to s, or an end-of-file condition is encountered. The string is then terminated with a null byte.
Since you give a length of 1, n-1 will be 0 and so your input is never stored in menu_option. Change it to a char array
char menu_option[10];
// ...
fgets(menu_option, sizeof(menu_option), stdin);
switch (menu_option[0]) {
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
}
Update:
It is necessary to use char arrays, because you need enough space to store the input. The minimum size for a buffer is two characters, e.g. char buf[2], because fgets stores your input plus a terminating NUL character.
The loop iterates twice or even more times, because when you input e.g. 1 return or 1 3 2 return, it will first return 1, then 3, 2 and finally return. If you want to read the whole line and use the first digit only, your buffer must be larger than just 2, like e.g. 10 or even 256.
fgets reads a string instead of character. The statement
fgets(&menu_option,1,stdin);
Will store a string to menu_option but to store a string you need a size at least 2 bytes.
char menu_option[2];
...
fgets(menu_option,2,stdin);
int c;
while((c = getchar()) != '\n' && c != EOF); // This will be needed to flush your input buffer
switch (menu_option[0]) {
...
...
}
From: http://www.cplusplus.com/reference/cstdio/fgets/
fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream.
Reads characters from stream and stores them as a C
string into str until (num-1) characters have been read or either a
newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a
valid character by the function and included in the string copied to
str.
A terminating null character is automatically appended after the
characters copied to str.
Since you have specified 1 for the number, 0 bytes are read, and the only thing that happens is that a terminating null character is appended. The result is an infinite loop in which nothing is read.
Since in the comments you expressed dislike for using strings, here's alternative implementation with minimal changes to the question code:
while (end == 0) {
printf("...menu print snipped...\n");
int ch = getchar();
switch (ch) {
case EOF: // end of file or error, fall through to exit option
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
// default: // add error message?
}
// ignore any extra chars in the same line
while ((ch = getchar() != '\n') {
// test for end of file and set end to true
if (ch == EOF) {
end = 1;
break;
}
}
}
Note the extra loop, which will read and discard rest of the input line. Without it, user can enter several options on one line, which is probably not desirable. Also note, if the option functions read more user input, consider how you handle long lines then. For example move the extra loop to be before switch (and add another variable to read discarded chars). Actually you should probably put the extra loop to it's own function discard_until_newline.
I face problem in my code below. When I enter any integer, that is (0-9), then it is OK. But when I enter some other characters like A, B or any other letter scanf() fails. Then it doesn't wait for any further input.
I've attached a code snippet for this. I highly require error handling using only the C standard library.
#include <stdio.h>
int main()
{
int choice;
while(1)
{
printf("Enter your choice: ");
if(0 == scanf("%d", &choice))
{
printf("Some error occured\n");
//break;/*I did not want to break this loop as I use this to show menu*/
}
switch(choice)
{
case 0:printf("Case 0\n");break;
case 1:printf("Case 1\n");break;
case 2:printf("Case 2\n");break;
case 3:printf("Case 3\n");break;
case 4:printf("Case 4\n");break;
case 5:printf("Case 5\n");break;
case 6:printf("Case 6\n");break;
case 7:printf("Case 7\n");break;
case 8:printf("Case 8\n");break;
case 9:printf("Case 9\n");break;
default:printf("Default case\n");break;
}
}
}
Question more clearly is: why doesn't it wait after failure?
With scanf, if the input given doesn't match the format specification, then the input isn't consumed and remains in the input buffer. In other words, the character that doesn't match is never read.
So when you type, e.g. an a character, your code will loop indefinitely as scanf continues to fail on the same character.
When scanf returns an error, you need to get rid of the offending character(s).
You can't know how many characters will be typed, but one simple way to consume any offending characters is to try and read a string when scanf fails:
char junkChars[256];
printf("Enter your choice: ");
if (scanf("%d", &choice) == 0)
{
printf("Some error occured\n");
scanf("%s", junkChars);
}
This will clear the input buffer, but relies on an upper-bound. If the user types more than 256 characters, the scanf will continue to consume them on the next iteration(s).
Clearly this is an ugly solution, but scanf isn't really a great input mechanism for this reason. Better to use fgets to get the input line as a string, then control the parsing of that string yourself.
That is by design.
Don't use break, use continue.
Can someone tell me why the gets in the case 1 is being completely ignored?
// #define M 50 is at the top
char product[M] = {0};
int choice = -1;
printf("Command: ");
scanf("%d", &choice);
switch(choice){
case 0:
break;
case 1:
printf("Product: ");
gets(product);
insert_product(warehouse, price, product);
break;
case 2:
// print_all();
break;
default:
printf("Scelta non valida\n");
break;
}
The gets might be skipped by an ending char from a previous input. Try adding a getchar() before the gets to see if that is the problem.
The problem is that the newline you input when reading choice:
scanf("%d", &choice);
is being taken as input for the next gets(product); and so it reads an empty string. Try to add an artificial getchar after scanf to absorb the newline:
scanf("%d", &choice);
getchar();
Should work now.
First, the important bit...
NEVER NEVER NEVER NEVER NEVER use gets. Ever. Even for practice code. Even if someone else tells you to. It's like the movie Highlander II; it's just best to pretend it never existed. It was deprecated in C99 and has been completely removed from C2011. Don't use it. Don't try to justify using it by claiming this is just practice code. If someone else demands you use it, push back and tell them you'll use fgets instead. If they give you grief, send them to me and I'll straighten them out. With a baseball bat if necessary.
Okay, now that I've cleared that up...
gets is picking up the trailing newline from the input you entered for the previous scanf call. You have several choices:
Use another scanf call instead of gets, this time with the %s conversion specifier (along with a field width); unlike gets, it will skip over any leading newline characters;
Call getchar() (or equivalent) to consume the newline before calling gets;
Instead of reading choice as an integer using scanf, read it as text using fgets and convert it to an integer using strtol.
Option 3 is the best IMO. Mixing calls to scanf/fscanf and fgets is usually a recipe for heartburn, precisely because of the trailing newline issue. Better to stick with one or the other for everything. The advantage of using fgets to read everything as text is that it makes input validation easier, especially for numeric input.
// #define M 50 is at the top
char product[M] = {0};
int choice = -1;
printf("Command: ");
scanf("%d", &choice);
switch(choice){
case 0:
break;
case 1:
printf("Product: ");
getchar();
gets(product);
insert_product(warehouse, price, product);
break;
case 2:
// print_all();
break;
default:
printf("Scelta non valida\n");
break;
}
Use fflush(stdin) before using gets as input as the gets is taking newline character as input after the use of scanf("%d", &choice);
fflush(stdin) clears the output buffer and moves the buffered data to console.
I've been writing a simple program to check if input letter is a vowel, and my code doesn't work.
The program should take characters as input one by one until % is entered, which will make it exit. It checks if input chars are vowels, and prints the result. Also it reports an error if input is not a letter.
The problem is, it breaks out of the loop on the second step.
Thank you for help, in advance.
PS Sorry, didn't write that there's no error message, it just breaks out of the loop.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char processed='q';
while(processed != '%')
{
printf("Enter letter to check if it's a vowel, %% to quit.\n");
char input = getchar();
processed = tolower(input);
printf("%c\n", processed);
if (processed == '%')
break;
if (processed < 'a' || processed > 'z')
{
fprintf(stderr, "Input should be a letter\n");
exit(1);
}
switch(processed)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'y':
printf ("Vowel\n");
break;
default:
printf ("Non-vowel\n");
}
}
exit(0);
}
Presumably you're entering a character and then hitting [ENTER]. So, in actuality you are entering two characters -- the letter you typed and a line feed (\n). The second time through the loop you get the line feed and find that it's not a letter, so you hit the error case. Perhaps you want to add something like:
if (processed == '\n') {
continue;
}
Someone else mentioned that you're hitting enter after each letter of input, and thus sending a newline ('\n') into your program. Since your program doesn't have a case to handle that, it isn't working right.
You could add code to handle the newline, but using scanf would be easier. Specifically, if you replaced
char indent = getchar();
with
char indent;
scanf("%c\n", &indent);
scanf() would handle the newline and just return back the letters you're interested in.
And you should check scanf()'s return value for errors, of course.