Comparing user-inputted characters in C - c

The following code snippets are from a C program.
The user enters Y or N.
char *answer = '\0';
scanf (" %c", answer);
if (*answer == ('Y' || 'y'))
// do work
I can't figure out why this if statement doesn't evaluate to true.
I checked for the y or n input with a printf and it is there, so I know I'm getting the user input. Also when I replace the the condition of the if statement with 1 (making it true), it evaluates properly.

I see two problems:
The pointer answer is a null pointer and you are trying to dereference it in scanf, this leads to undefined behavior.
You don't need a char pointer here. You can just use a char variable as:
char answer;
scanf(" %c",&answer);
Next to see if the read character is 'y' or 'Y' you should do:
if( answer == 'y' || answer == 'Y') {
// user entered y or Y.
}
If you really need to use a char pointer you can do something like:
char var;
char *answer = &var; // make answer point to char variable var.
scanf (" %c", answer);
if( *answer == 'y' || *answer == 'Y') {

answer shouldn't be a pointer, the intent is obviously to hold a character. scanf takes the address of this character, so it should be called as
char answer;
scanf(" %c", &answer);
Next, your "or" statement is formed incorrectly.
if (answer == 'Y' || answer == 'y')
What you wrote originally asks to compare answer with the result of 'Y' || 'y', which I'm guessing isn't quite what you wanted to do.

For a start, your answer variable should be of type char, not char*.
As for the if statement:
if (answer == ('Y' || 'y'))
This is first evaluating 'Y' || 'y' which, in Boolean logic (and for ASCII) is true since both of them are "true" (non-zero). In other words, you'd only get the if statement to fire if you'd somehow entered CTRLA (again, for ASCII, and where a true values equates to 1)*a.
You could use the more correct:
if ((answer == 'Y') || (answer == 'y'))
but you really should be using:
if (toupper(answer) == 'Y')
since that's the more portable way to achieve the same end.
*a You may be wondering why I'm putting in all sorts of conditionals for my statements. While the vast majority of C implementations use ASCII and certain known values, it's not necessarily mandated by the ISO standards. I know for a fact that at least one compiler still uses EBCDIC so I don't like making unwarranted assumptions.

Because comparison doesn't work that way. 'Y' || 'y' is a logical-or operator; it returns 1 (true) if either of its arguments is true. Since 'Y' and 'y' are both true, you're comparing *answer with 1.
What you want is if(*answer == 'Y' || *answer == 'y') or perhaps:
switch (*answer) {
case 'Y':
case 'y':
/* Code for Y */
break;
default:
/* Code for anything else */
}

Related

If statement executing regardless of the condition [duplicate]

This question already has answers here:
Program not recognizing character inputs in if-else statements
(5 answers)
Closed 1 year ago.
I'm writing a C program that asks the user for a variety of inputs, one is a Yes or No question. If you put Y, or y, the If statement is supposed to execute. However, no matter what you input, it goes through with the If statement.
double phonePrice;
double phoneTax;
double phoneTotal;
double phoneApplePrice;
double phoneSubtotal;
double temp;
int yearsAppleCare;
char userAnswer;
//prompting for price
printf("Enter the price of the phone> ");
scanf("%f", &phonePrice);
fflush(stdin);
//prompting for iphone
printf("Is the phone an iPhone (Y/N) ?> ");
scanf("%c", &userAnswer);
fflush(stdin);
//nested if statements asking for apple care amount
if(userAnswer=="Y"||"y")
{
printf("Enter the number of years of AppleCare> ");
scanf("%d", &yearsAppleCare);
if(yearsAppleCare<=0)
{
printf("You must choose at least 1 year of AppleCare");
return 0;
}
}
Any help with this would be appreciated.
For starters this call
fflush(stdin);
has undefined behavior. Remove it.
Instead of this call
scanf("%c", &userAnswer);
use
scanf(" %c", &userAnswer);
^^^^
to skip white spaces in the input buffer as for example the new line character '\n'.
Also for double variables use the conversion specifier %lf. For example
scanf("%lf", &phonePrice);
The condition in the if statement
if(userAnswer=="Y"||"y")
is equivalent to
if( ( userAnswer=="Y" ) || ( "y" ) )
As the string literal "y" that is implicitly converted to a pointer to its first element is not equal to a null pointer then the condition always evaluates to logical true.
You need to write
if( userAnswer == 'Y' || userAnswer == 'y' )
using integer character constants 'Y' and 'y' instead of the string literals.
Error is here:
//nested if statements asking for apple care amount
if(userAnswer=="Y"||"y")
{
Should be:
//nested if statements asking for apple care amount
if(userAnswer == "Y" || userAnswer == "y")
{
Wait! No!
Should be:
//nested if statements asking for apple care amount
if( strcmp(userAnswer, "Y") == 0 || strcmp(userAnswer, "y") == 0)
{
Why?
What does == mean?
In C language, == means the two objects are equal. In the case of strings, the objects are char*, I.e. pointers to char. These will be equal if and only if the memory address is the same. This will not be true in this case.
Why? Because one string is compiled into the program and initialised as the program starts, and the other is provided by the user into temporary memory. These will be at different addresses so the pointers will not be the same.
What you probably want is to compare the contents of the memory locations pointed to by the two pointers.
For that purpose the strcmp function is provided. This function returns zero if the strings are the same. You may also want to consider stricmp.

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'");
}

declaration shadows a local variable in c

I am using the cs50 library and ide and when trying to compile this program I get errors saying that the variable 'answer' has already been declared and I don't know how to solve this any answers would be appreciated I am really stuck on this as I have just began to learn how to program the error log is:
char.c:9:14: error: declaration shadows a local variable [-Werror,-Wshadow]
char answer = get_char("are you okay")
char.c:6:10: note: previous declaration is here
char answer;
char.c:20:12: error: variable 'answer' is uninitialized when used here [-Werror,-Wuninitialized]
while (answer != 'y' && answer != 'Y' && answer != 'n' && answer != 'N');
char.c:6:16: note: initialize the variable 'answer' to silence this warning
char answer;
The code is:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
char answer;
do
{
char answer = get_char("are you okay Y/N ");
if (answer == 'y' || answer == 'Y')
{
printf("you are okay");
}
else if (answer == 'n' || answer == 'N')
{
printf("you are not okay ");
}
}
while (answer != 'y' && answer != 'Y' && answer != 'n' && answer != 'N');
}
Note, the warning messages in your post are very helpful. Do not be shy about simply following their suggestions in-order one-by-one. (They are what I used to make the suggestions below.)
The shadow is caused by the second declaration of answer inside the do block:
char answer;// original declaration (the shadow)
do
{
char answer = get_char("are you okay Y/N ");//2nd declaration (being shadowed)
To Fix, do this
char answer;// leave this declaration to allow proper scope
do
{
answer = get_char("are you okay Y/N ");// uses same instance of 'answer' (no shadowing)
^^^^ removed second instance of `char`
There is a C specific discussion on variable shadowing here, and another more broad discussion here
Within the compound statement of the do-while loop you need to use the same variable answer that is declared before the loop.
char answer;
do
{
answer = get_char("are you okay Y/N ");
if (answer == 'y' || answer == 'Y')
{
printf("you are okay");
}
else if (answer == 'n' || answer == 'N')
{
printf("you are not okay ");
}
}
while (answer != 'y' && answer != 'Y' && answer != 'n' && answer != 'N');
Otherwise this declaration within the compound statement of the do while loop
char answer = get_char("are you okay Y/N ");
hides the declaration of the variable with the same name before the while loop and moreover this variable is not alive outside the loop.
Pay attention to that the do-while loop is defined in C the following way
do statement while ( expression ) ;
For example you may write
do ; while ( expression );
where a sub-statement of the do-while statement is the null statement ;.
If you use a compound statement as the sub-statement like
do { /*...*/ } while ( expression );
then this compound statement forms its one scope and all variables with automatic storage duration are not alive outside the compound statement.
Also instead of call printf like this
printf("you are okay");
it is better to use a call of puts like
puts("you are okay");
because the call of puts also appends an output of the new line character '\n'.
try removing the char in
char answer = get_char("are you okay Y/N ");
as it is declared outside the loop
and initilize it to char answer="";

Generating a dice game - C Programming

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

The code "should" work, but the program stops working

I'm a beginner with a few hours of expirience and I'm trying to make a really simple program to get familiar withe IF command. I came up with this code:
#include<stdio.h>
int main()
{
char ans;
char n;
char y;
printf("Do you want to exit?\n");
scanf("%c\n",ans);
if (ans == y)
{
printf("As you wish!\n");
return 0;
}
else (ans == n);
{
printf("You'll exit anyways!\n");
return 0;
}
}
I think it should work, but after I type something the program stops workig! Thanks in advance!
The
if (ans == y)
should read
if (ans == 'y')
The former compares ans to the value of the uninitialized variable y, whereas the latter checks whether ans contains the character 'y'.
The same goes for 'n'.
The y and n variables are unnecessary and can be removed.
Also, the following line is incorrect:
else (ans == n);
It should read
else if (ans == 'n')
(I've added the if and have removed the semicolon.)
Finally, the scanf() should read:
scanf("%c",&ans);
else (ans == n);
This doesn't give expected results. Remove the ; and the condition.
else may only take a body of code. It does not handle conditions.
If you want conditions, use else if:
else if (ans == 'n')
More errors:
if (ans == y)
y in here refers to the variable, which is declared but has no value. Surely you want to refer to the character 'y':
if (ans == 'y')
Also, scanf expects a pointer, so instead of ans, use &ans.
It needs to write to the memory address of the value. It doesn't care about the value.
You'll learn about pointers eventually. (Assuming you haven't gone over them in your few hours of experience)
There are three main errors.
You should pass pointers to the scanf function, so you have to add an ampersand before ans (&ans).
There is a trailing ; at the end of the else statement.
y refers to a variable (which does not exist), whereas you want to compare ans against the character 'y'.

Resources