scanf() not returning the proper value? - c

I have a function as part of a larger program to determine the quantity of products sold on each day of the previous week. Here is the function that performs the case switch:
unsigned int switchfn()
{
int productNumber; // product 1 through 5
// only while product 1 through 5 is being entered.
while ((scanf("%d", &productNumber)) != EOF) {
// gather product data
switch (productNumber) {
case '1': // product one
++productOne;
break;
case '2': // product two
++productTwo;
break;
case '3': // product three
++productThree;
break;
case '4': // product four
++productFour;
break;
case '5': // product five
++productFive;
break;
case '\n': // ignore new line
case '\t': // ignore tab
case ' ': // ignore space
break;
default: // catch all other characters
printf("%s", "No such product exists.");
puts(" Please enter a valid product number.");
break;
}
}
return 0;
}
However, when the program runs, it always jumps to the default, even when entering numbers 1 through 5. Is this an issue with what scanf() is returning?

You appear to be getting confused between integers and ASCII digits. You're performing formatted extraction, but inspecting productNumber as if it were the actual ASCII character found in the input.
Remember, '1' is actually 49.
Since you want to cover cases like '\n' too, read into a char with %c instead. Then the extraction operation won't perform the formatting conversion for you as it is now, and your character literal comparisons will be correct.

Case '1' - at this moment you are asking compiler to check did you enter a character '1' - his ASCII value is 49 and that's the reason why he is just skipping to default case. Try to input " %c"

scanf("%d", &productNumber) get productNumber is a interger.
But case '1' : '1' is a char and his ASCII value is 49 and so every time you input a interger, there is no match case just skipping to default case. u can input " %c" to get a char.

Since your scanf function is referencing an integer, you merely have to switch your cases to integers:
case 1:
//your logic
break;
case 2:
//your logic
break;

Related

What am I doing wrong with this menu in C

I am new at C and am trying to create my first menu! But whenever the user inputs 1 and enter the default option appears and reload the menu. Although when 4 and enter are hit the default option also appears but the menu is successfully exited.
void begin_menu(void)
{
int choice;
do
{
printf("English Draughts - Main Menu\n\n");
printf("1. Play Game\n");
printf("2. Display Winners\n");
printf("3. Reset Scoreboard\n");
printf("4. Quit\n");
scanf("%d",&choice);
switch (choice)
{
case '1' : play();
break;
case '2' : /*write function to do here */
break;
case '3' : /*write function to do here */
break;
case '4' :
printf("Goodbye!\n");
exit(0);
break;
default:
printf("Please insert a correct choice.\n");
break;
}
} while (choice != 4);
}
void play(void)
{
while(end != "n");
{
printf("Player Names\n\n");
printf("Enter name for first player:\n");
scanf("%s",&player_one);
printf("Enter name for second player:\n");
scanf("%s",&player_two);
printf("Begin?(y to start, n to quit)\n");
scanf("%c",&end);
}
return;
}
Thanks everyone, but I have the problem that if play() is called.. ie 1 is entered.. the console just looks for input and doesn't print the function information at all.
'1'and 1 are not the same thing
The first one is an ascii character, the second one is a number.
You can lookup the value of '1' in the ascii table and see that it is 49, which does not equal 1.
Try entering 49 in your console, just for fun :)
You are evaluating strings instead of integers.
You defined the choice variable as an integer, so comparisons must be with integers to. Remove the ' around your numbers inside your switch statement and it should work fine.
You are having choice as integer data type.
int choice;
But in switch case you are checking for character constants. So it leads to default case always. Because '1' and 1 are not same!
Try the below changes-
switch (choice)
{
case 1 : play();
break;
case 2 : /*write function to do here */
break;
case 3 : /*write function to do here */
break;
case 4 : printf("Goodbye!\n");
exit(0);
break;
default: printf("Please insert a correct choice.\n");
break;
}
You have case '1' instead of case 1
'1' is an ascii character and 1 is an integer.
As others mentioned, '1' and 1 are not the same. '1' has a decimal value of 49. You can fix your code by:
changing choice to be type of char and then tell scanf to expect format of %c, not %d
or you can change your switch cases to use decimal values.
Switch cases accepts only integer constants. All of the cases are evaluated to integers, hence your code works. Note that switch cases won't work with string literals. If you would type "1" instead of '1' you would get a compiler error.

Loop showing menu never ends

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.

Switch Statement Not Executing Cases (c)

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.

A problem with (switch) in C

scanf("%ld",&l);
printf ("l=%ld",l);
switch (l)
{
case'1':
XOR(&matrix1[10],&matrix2[10],m);
break;
case'2':
AND(&matrix1[10],&matrix2[10],m);
break;
default:
printf("\n\t\tWrong input");
}
When the program reaches switch, no matter what I enter (whether it's wrong or right), the program keeps showing the massage (Wrong input), though I've entered a right number (1 or 2).
Change your case labels from
case'1':
...
case'2':
...
to
case 1:
...
case 2:
...
Explanation: your switch value is an integer, not a character, hence you need integer constants for your case labels, not character constants.
Your case should be case 1 and not case '1'.
'1' != 1
Note: '1' is nearly 60 or something like that, 'cause single quotes mean "using char" (or it's ASCII code). Try removing 'em from your switch cases:
scanf("%ld",&l); printf ("l=%ld",l); switch (l) { case 1: XOR(&matrix1[10],&matrix2[10],m); break; case 2: AND(&matrix1[10],&matrix2[10],m); break; default: printf("\n\t\tWrong input"); }
Or you can change your input from numeric to char:
scanf("%c", &l);
But you aren't reading a character but your cases are characters. Re-write as follows:
switch (l)
{
case 1:
XOR(&matrix1[10],&matrix2[10],m);
break;
case 2:
AND(&matrix1[10],&matrix2[10],m);
break;
default:
printf("\n\t\tWrong input");
}
'1' and 1 are not the same.
Because your switch is relying on an integer. Whereas you're taking in a string. You'll need to run l through atoi first.
'1' is a char, the ASCII representation of the digit 1. Use plain 1 instead.
case 1:
/*...*/
break;
That's because:
case '1':
is not the same as:
case 1:
The second one is the one you seem to be expecting.

C - Reading user input

I have a program where user input is required, a user types in a number 1-8 to determine how to sort some data, but if the user just hits enter a different function is performed. I get the general idea of how to do this and I thought what I had would work just fine but I'm having some issues when it comes to when the user just hits the enter key. Currently my code looks as follows:
//User input needed for sorting.
fputs("Enter an option (1-8 or Return): ", stdout);
fflush(stdout);
fgets(input, sizeof input, stdin);
printf("%s entered\n", input); //DEBUGGING PURPOSES
//If no option was entered:
if(input == "\n")
{
printf("Performing alternate function.");
}
//An option was entered.
else
{
//Convert input string to an integer value to compare in switch statment.
sscanf(input, "%d", &option);
//Determine how data will be sorted based on option entered.
switch(option)
{
case 1:
printf("Option 1.\n");
break;
case 2:
printf("Option 2.\n");
break;
case 3:
printf("Option 3.\n");
break;
case 4:
printf("Option 4.\n");
break;
case 5:
printf("Option 5.\n");
break;
case 6:
printf("Option 6.\n");
break;
case 7:
printf("Option 7.\n");
break;
case 8:
printf("Option 8.\n");
break;
default:
printf("Error! Invalid option selected!\n");
break;
}
}
Now I've changed the if statement to try input == "", input == " ", and input == "\n" but none of these seems to work. Any advice would be greatly appreciated. Currently from what I can see, the initial if statement fails and the code jumps to the else portion and then prints the default case.
Just to be clear the variables I declared for this code are as follows:
char input[2]; //Used to read user input.
int option = 0; //Convert user input to an integer (Used in switch statement).
The problem is in how you're doing the string comparison (if (input == "\n")). C doesn't have a "native" string type, so to compare strings, you need to use strcmp() instead of ==. Alternatively, you could just compare to the first character of the input: if (input[0] == '\n') .... Since you're then comparing char's instead of strings, the comparison doesn't require a function.
Try:
#include <string.h>
at the top and
if(strcmp(input, "\n") == 0)
in place if your if ( input == ... )
Basically, you have to use string comparison functions in C, you can't use comparison operators.
Try:
input[0] == '\n'
(or *input == '\n')
You need to use single quotes rather than double quotes
if(input == "\n")
compares the input address to the address of the string "\n",
What you want to do is to compare the first character of the input buffer
to the character literal \n like this
if(input[0] == '\n')
Note the use of single quotes around '\n'
You need to capture return code from sscanf, it will tell you how many of the field are "assigned", which in "Enter" key case, return code of 0
edit:
you should use strcmp when comparing string, not the operator "==".
The issue is with strings, you are comparing pointers, i.e. memory addresses. Since the input and "\n" aren't the same exact memory, it always fails (I assume input is a char *). Since you're looking for a single character, you can instead dereference input and compare to a char using single quotes instead of double.
(*input == '\n')
Should work as you intend.

Resources