Menu that accepts single character in C language - c

I want to create a simple menu in C program that accepts single character. The menu will be like this:
[S]how
[E]xit
If the user enter '1','s' or 'S' the program will print "Hello" and prompt again for the input
else if the user enters '2',E or 'E' the program ends.
else it should print "invalid input" and prompt again.
I am able to create the program but the problem is that when user enters 12, 13, 14, 15, 16.....so on starting with 1, it shows Hello and same for other options.
My code is:
#include <stdio.h>
void clearBuffer();
int main() {
int i = 0;
char selection;
do
{
printf("\t1. [S]how\n");
printf("\t2. [E]xit\n");
printf("Enter your selection from the number or character noted above: ");
scanf("%s", &selection);
clearBuffer();
if (selection == '1' || selection == 's' || selection == 'S')
printf("Hello");
else if (selection == '2' || selection == 'E' || selection == 'x')
i = 0;
} while(i != 0);
}
void clearBuffer()
{
while(getchar() != '\n');
}

If you are going to receive only one character consider replacing the scanf() function for getchar() function:
printf("Enter your selection from the number or character noted above: ");
selection = getchar();

You could use strlen, which is part of the standard C library, to check the length of the string returned by scanf and reject entries longer than one character:
if (strlen(selection) > 1)
{
printf("Invalid selection.");
}
Alternatively, I think you could use getchar() to accept just a single character from the user, which means they wouldn't have to press enter.

As already mentioned, you should use getchar() if you only want one character. If you still want to use scanf() for whatever reason you may have, the correct format is "%c", not "%s".
I would also suggest that if you are looking for a single character, the if block looks a little "busy" (read, awkward) ... a switch would be a cleaner, more elegant way to do it (IMHO).
/* something like this ... */
switch ( selection ) {
case '1':
case 's':
case 'S':
printf ( "Hello\n" );
break;
case '2':
case 'e':
case 'E':
i = 0;
break;
}
Other couple of things ... if you don't care about the case of the character being read (that is, 's' and 'S' will do the same thing), you can convert selection to uppercase before your if-block or switch-block using toupper(). Also, and this is just a style suggestion, don't use i for your exit flag. General practice is to use things like i and j for counters or indexes - you could use something like quit_now or user_done which would convey more precisely what the variable means.

Related

How to Compare char array with char in C language

What's wrong in the below code?
I am stuck in the do while loop. Am I comparing character wrong? I tried using scanf("%c", &answer); as well but same result
char answer[10];
for (i = 0; i < wish; i++)
{
/* ... */
/* ... */
do
{
printf(" Does this item have financing options? [y/n]:");
scanf("%s", &answer[i]);
if ((answer[i] != 'y' )|| (answer[i] != 'n'))
{
printf("\nERROR: Must be a lowercase 'y' or 'n'");
}
} while ((answer[i] != 'y') || (answer[i] != 'n'));
You are stuck in your loop because your condition for continuing the loop is always true.
If you have trouble seeing that try to name a letter which is neither different to "y" nor different to "n".
Take for example "a", it is different to both.
Take for example "n", it is not different to "n", but it IS different to "y".
Take for example "y", it is different to "n", though not different to "y".
So whatever letter comes in, the loop will continue.
To solve, use the comment by Chris and change to
((answer[i] != 'y' ) && (answer[i] != 'n'))
This way, any other letter than "n" or "y" will be either different than "n" AND different than "y" and will continue the loop, while both "y" and "n" will be different from at least one of the two and end the loop.
Once you got the condition right it might only be necessary once, i.e. only in the loop. The additional if is unneeded, at least in the shown code. You might have code which needs it, outside of what you show here.
Building on #Yunnosch's excellent answer, there us another way of looking at the logic of checking to see if something is not a set of characters.
We can look at it as checking to see if a character is not 'y' and not 'n':
answer[i] != 'y' && answer[i] != 'n'
Or... we can check to see if it is either 'y' or 'n':
answer[i] == 'y' || answer[i] == 'n'
Then simply negate that!
!(answer[i] == 'y' || answer[i] == 'n')
Another alternative
One more way of looking at this, because char is a numeric type, would be to use a switch.
switch (answer[i]) {
case 'y':
case 'n':
/* Do whatever happens when there is a valid input */
break;
default:
printf("\nERROR: Must be a lowercase 'y' or 'n'");
}
The only real advantage of using switch here is that it makes checking for things like capital y and n very easy:
switch (answer[i]) {
case 'y': case 'Y':
case 'n': case 'N':
/* Do whatever happens when there is a valid input */
break;
default:
printf("\nERROR: Must be a lowercase 'y' or 'n'");
}

Compare strings correctly in C [duplicate]

This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 8 years ago.
I have to make a program where the input must be one of 2 values, 'M' or 'F'.
Here is the program segment that I have created to demonstrate
do
{
printf("What is your Gender? (M for Male - F for Female) ");
fgets(GenderValue, 16, stdin);
if (GenderValue[0] == '\n')
{
printf("Try again");
getch();
system("cls");
loop=1;
}
else
{
loop = -1;
}
if (GenderValue == "M");
{
loop =-1;
}
else if(GenderValue == "F");
{
loop=-1;
}
else
{
printf("Try again");
getch();
system("cls");
loop=1;
}
}
while(loop > 0); //Checks for NULL input
printf("Gender: %s",GenderValue);
I know I could have done an integer choice input, but I would like to recycle this later if possible.
So far the program calls my Gender value comparisons "Errors", Which is fine, except I have no idea what to do next, I could find a function that compares strings, but I really don't want to over complicate my code.
Edit: Duplicate?, Really?, The example given doesn't even come close to helping me.
Edit 2: Found the problem, i had ;'s next to my if statements, that's fixed now. But seriously, no one spotted this ?
You use strcmp to compare strings. Using the comparison operator == just compares the pointers.
But note that fgets will leave the ending newline in the string, so you need to compare to e.g. "M\n", or remove the newline if it's there.
Also note that scrcmp is case sensitive, the string "M" is not equal to the string "m".
You could use e.g. scanf to read the input as a single character instead, and use e.g. tolower (or toupper) to get case insensitive comparison.
However, using scanf brings other problems, especially if you use it again afterwards to read another single character. The reason for this is that Scanf leaves the newline in the input buffer, causeing the possible next scanf call with the "%c" format to read that newline. There are very simple solution for this: Tell scanf to read and discart leading whitespace by using " %c".
If GenderValue is a string, GenderValue == "M" is wrong . strings are not supposed to be comapred with ==. use strcmp().
[In this case, IMO its suitable] If GenderValue is a single character, comparison should be done as GenderValue == 'M'
For your case, [considering one character input] you can do something like
fgets(GenderValue, 16, stdin);
switch(GenderValue[0])
{
case '\n':
//your code
break;
case 'M':
case 'm':
//your code
break;
case 'F':
case 'f':
//your code
break;
default:
}
In above code, three advantages
You don't need to bother about removing trailing \n caused by
fgets()
Exactly one character input is considered
No need to worry about the upper/lower case of input.
replace (GenderValue == "M") with (strcmp(GenderValue, "M") == 0 )
and
replace (GenderValue == "F") with (strcmp(GenderValue, "F") == 0 )
try replacing GenderValue == "F" with !strcmp(GenderValue, "F\n") and GenderValue == "M" with !strcmp(GenderValue, "M\n")
you might also need to include "string.h"
Use string compare function (strcmp("")) whenever you need to compare strings.

How Does Char Variable Work in C

What I am trying to accomplish is prompting the user with the question of do they want to run the program again. They either type y or n. If y, it reruns the program. If no, it stops the program. Anything other than those two will prompt an error and ask the question again. I'm used to C# where strings are not complicated, but in C, I guess there technically isn't strings, so we have to use either char arrays or char pointers. I've tried both, none that work that way I want, but I'm probably the problem. This is what I have.
char answer[1] = "a";
while (strcmp(answer, "y") != 0 || strcmp(answer, "n") != 0)
{
printf ("\n\nWould you like to run the program again? Type y or n. Then, hit Enter.");
scanf ("%c", answer);
if (strcmp(answer, "y") == 0)
{
main();
}
else if (strcmp(answer, "n") == 0)
{
continue;
}
else
{
printf ("\nERROR: Invalid input was provided. Your answer must be either y or n. Hit Enter to continue.");
F = getchar();
while ((getchar()) != F && EOF != '\n');
}
}
I have other while loops similar to this that work as expected, but use a float. So I'm assuming the problem is me using char here. What happens right now is that it doesn't even prompt the user for the question. It just asks the question and shows the error right afterwards. I'm sure there are other things wrong with this code, but since I can't get the prompt to work, I cannot test the rest of it yet.
I suggest using a light weight getchar() instead of the heavy scanf.
#include <stdio.h>
int c; /* Note getchar returns int because it must handle EOF as well. */
for (;;) {
printf ("Enter y or n\n");
c = getchar();
switch (c) {
case 'y': ...
break;
case 'n': ...
break:
case EOF:
exit(0);
}
}
"a" is a string literal == char id[2]={'a','\0'} //Strings are
char arrays terminated by zero, in C
'a' is a char literal
strcmp is just "compare each char in two strings, until you hit '\0'"
scanf ("%c", ___); expect an address to write to as the second
argument. Functions in C cannot modify their arguments (they don't
have access to them--they get their own local copy) unless they have
a memory address. You need to put &answer in there.
Jens has already basically answered the question, you most likely want to use getchar so that you can detect EOF easily. Unlike scanf("%c",...), getchar will not skip spaces, and I believe both versions will leave you with the unprocessed rest of the input line (a newline character ('\n') at least) after each getchar. You might want to something like
int dump;
while((dump=getchar())!='\n' && dump!=EOF) {};
So that you discard the rest of the line once you've read your first character of it.
Otherwise, the next getchar will get the next unprocessed character of the same line. ('\n' if the line was a single letter).
Here is one way to do it. It is by no means the only way to do it, but I think it accomplishes what you want. You should not call the main function recursively.
#include <stdio.h>
#include <stdlib.h>
void run_program()
{
printf("program was run.");
}
int main() {
char answer[2] = "y\0";
int dump;
do {
if (answer[0] == 'y')
{
run_program(); /* Not main, don't call main recursively. */
}
printf ("\n\nWould you like to run the program again? Type y or n. Then, hit Enter.\n");
scanf ("%1s", answer);
/* Dump all other characters on the input buffer to
prevent continuous reading old characters if a user
types more than one, as suggested by ThorX89. */
while((dump=getchar())!='\n' && dump!=EOF);
if (answer[0] != 'n' && answer[0] != 'y')
{
printf ("Please enter either y or n\n");
}
} while (answer[0] != 'n');
return 0;
}
Using %s instead of %c, reads in the new line so that the new line character is not in the stdin buffer which would become answer then next time scanf was called.
The run_program function is just a function where you would put your program's logic. You can call it whatever you want. I did this to separate out the menu logic from the logic of the actual program.
Well, you are comparing two strings instead of characters.
If you want to compare two character you have to follow this syntax:
char c;
scanf("%c",&c);
if(c == 'y')
//do something
else
//do nothing

C while loop - code won't work

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.

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