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.
Related
I am really new to C-language and was testing a simple if-statement program which, from your age and gender tells one answer from 4 different outcomes.
Which goes something like this:
If you are under the age of 55 and are male, it will print:
"You are a man at his best age!"
But I come across a error code which says: Run-Time Check Failure #2 - Stack around the variable 'miesVaiNainen' was corrupted.
I myself, think it might have something to do with: if (manOrFemale == "f" && age <= 55)
How can I fix this issue so the error wont come across?
I've tried to look for help in stackoverflow and tried to change the code a lot.
int age;
char manOrFemale;
printf("Are you a man or a female(m/f)");
scanf("%s", &manOrFemale);
printf("Input age:");
scanf("%d", &age);
if (manOrFemale == "f" && age <= 55)
{
printf("\nYou are a lady at her best!");
} else if (manOrFemale == "f" && age >= 56)
{
printf("\nYou look young for your age!");
}
if (manOrFemale == "m" && age <= 55)
{
printf("\nYou are a man at his best age!");
} else if (manOrFemale == "m" && age >= 56)
{
printf("\nYou are a wise man!");
} else {
printf("There has been an error in the program!");
}
}
As of now you are using %s specifier to read char.
you need to use %c specifier to read char, %s is for char *.
scanf(" %c", &manOrFemale);
And
you need to use single quotes to compare chars. As of now you are comparing
char with pointer.
if (manOrFemale == 'f'; && age <= 55)
Here's a very large problem:
scanf("%s", &manOrFemale);
The variable manOrFemale is a single character. The format "%s" is to read null-terminated byte strings.
A string of only a single character needs space for two characters, to fit the null-terminator. Since you don't have space for the terminator, the scanf function will write into memory you don't own, clobbering the stack (where compilers usually store local variables) leading to the error you get.
If you want to read a single character, then use the "%c" format, as in
scanf(" %c", &manOrFemale);
Do note the leading space in the format string, it's needed to ignore possible leading white-space (like newlines from any previous input).
Also note that with the comparison manOrFemale == "f" you compare the single character in manOrFemale with the string "f". A literal string in C is really a read-only array of characters, and as any array it decays to a pointer to its first element. So you're not comparing characters, you're comparing a character with a pointer.
Your compiler should have warned you about this.
To solve this you need to compare to a single character instead: manOrFemale == 'f'. Note the use of single-quotes instead.
Lastly a more stylistic note...
The statements
if (manOrFemale == 'f' && age <= 55)
{
printf("\nYou are a lady at her best!");
} else if (manOrFemale == 'f' && age >= 56)
{
printf("\nYou look young for your age!");
}
could be rewritten as
if (manOrFemale == 'f')
{
if (age <= 55)
printf("You are a lady at her best!\n");
else
printf("You look young for your age!\n");
}
One extra thing to note here is that I use trailing newline in the output. That's because otherwise there might not be a newline after the program finishes (so the output seems to be intermingled with the command-line prompt), but also because output to stdout (where printf writes) is by default line-buffered. Line-buffering means that output is buffered internally, and not actually written to the terminal until either the buffer is full, or a newline is written. If you use leading newlines in your output, then the previous line will be written, not the current line.
I'm following a tutorial on youtube and was doing a dice generator.
It basically print out 3 dice result and sum out the dice result.
After which, the user will look at the sum, and based on the sum, the user going to guess whether the next roll is going to be higher,lower, or the same.
Below is my code, suppose, when I typed 'yes', it should be doing the code inside the if statement. However, it went straight to the else statement. Can someone please tell me what's wrong?
int answer;
int guess;
int diceRoll4 = 0;
printf("Would you like to guess your next dice? Y/N \n");
scanf(" %c", &answer);
if (answer == 'yes' ){
printf("What is your guess?\n");
printf("please key in your number \n");
scanf(" %d", &guess);
if (guess > diceRoll4 ){
printf(" You got it wrong, too high!");
}
else if (guess < diceRoll4){
printf(" You got it wrong, too low!");
}
else {
printf("You got it right");
}
}
else{
printf("Thanks for playing");
}
First of all, answer should be an array of chars in order to hold a string. Change
int answer;
to
char answer[10]; //Or any other reasonable size
Secondly, since you want to scan a string and not a character, change
scanf(" %c", &answer);
to
scanf("%9s", answer);
The 9 will scan a maximum of 9 characters (+1 for the NUL-terminator at the end), thus preventing buffer overflows.
I've removed & as %s expects a char* while &answer will give a char(*)[10]. Name of an array gets converted into a pointer to its first element char*, exactly what %s expects. The above scanf is thus equivalent to
scanf("%9s", &answer[0]);
Thirdly, comparing two strings using == compares pointers and not the actual content in them. Use strcmp from string.h instead. It returns 0 when both its arguments hold the same content. Change
if (answer == 'yes' ){
to
if (strcmp(answer, "yes") == 0){
Double quotes are used to denote a NUL-terminated string(char*), which is exactly what strcmp expects, while single quotes, as in your code, is a multi-character literal whose value is implementation-defined.
'yes' is a multi-byte character whose behaviour is implementation-defined.
What you probably want is to read and compare a single char:
if (answer == 'y' ){
or read a whole string and compare:
char answer[128];
scanf("%s", answer);
if ( strcmp(answer,"yes") == 0 ){
...
}
Notice that I changed the type of answer and used %s to read a string.
If you do not want to read in a string, but only a single char where the user can answer either Y or N, you should change int answer; to char answer;. You can then go on using your original scanf()-call. You will still need to change
if (answer == 'yes')
to
if (answer == 'Y')
If you want the user to either type in y or Y you could user toupper() from ctype.h and change your if-condition to if (toupper(answer) == 'Y').
To test the equality you have to use strcmp. If the returning value is 0 it means that they are equal.
if (strcmp(answer, "yes") == 0) {
// ...
} else {
// ...
}
Notes:
Using just answer == 'yes' it test the equality of pointers not value. This is the reason why enters only in else.
Because answer is int you have to change to an array
char answer[15]
As #Sathya mentioned you are reading just a char %c for reading a string you have to use %s
scanf("%s", answer);
Instead of 'yes' which is multi-character character constant change to "yes" that is an array of char with \0 at the end, more informations here.
this line:
if (answer == 'yes' ){
has several problems.
1) the definition of 'answer' is 'int' but the scanf is inputting a single character
2) answer could be compared with 'y' or 'n' but not to a array of char.
3) since the scanf only input a single char
and you/the user input 'yes',
only the first character was consumed,
so the 'es' are still in the input buffer
4) note the the single character could be anything, except white space.
the leading space in the format string would consume any white space.
so the user could input say 'y' or 'Y'
these are different characters
however, using the toupper() macro from ctypes.h
would mean only a 'Y' would need to be compared
5) if you decide to read a string,
then 'answer' needs to be a character array,
say: char answer[10];
and the scanf needs to have a max length modifier
on the associated "%s" input/conversion parameter
so as to avoid the user overflowing the input buffer
and the comparison would be via the strcmp() function
6) always check the returned value (not the parameter value)
from scanf to assure the operation was successful
7) diceRoll4 and guess can never be a negative number
so the variable definitions should be unsigned
and the associated scanf() for guess should use
something like "%u"
8) on the printf() format strings, always end them with '\n'
so the sting will be immediately displayed to the user,
otherwise, they will only be displayed
when a input statement is executed or the program exits
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
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.
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.