If statement executing regardless of the condition [duplicate] - c

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.

Related

A simple while loop to check input stuck in infinite loop

I am pretty sure this was asked before but I could not find any answers, so here I go. This is a simple line of code and I cannot get it to exit the while loop. If I change the || to && the loop just exit no matter what I press. Thank you for the answers.
#include <stdio.h>
int main()
{
int answer;
printf("Are you sure you want to exit the program? Type in 1 for yes and 2 for no.\n");
scanf("%d", answer);
//This is to check that the user inputs the right number if not error message is displayed
while(answer <1 || answer > 2)
{
printf("Please type in 1 to exit the program and yes and 0 to keep playing. \n");
scanf("%d", answer);
flushall();
}
return 0;
}
If You want to exit on 1, then You just need to check if input is equal to it, that is why I want to scan for more answers when it is not equal to 1. If it is then it will omit while loop and go directly to return 0.
Also I changed the way of usage of scanf - when you declare a variable (in Your case answer), system gives it an address in the memory. Then you use scanf to take an input from the user, and after you take the input, you write it on the address of that variable so that when you refer to it later, the system goes to the address and retrieve the value.
int main()
{
int answer;
printf("Are you sure you want to exit the program? Type in 1 for yes and 2 for no.\n");
scanf("%d", &answer);
//This is to check that the user inputs the right number if not error message is displayed
while(answer != 1)
{
printf("Please type in 1 to exit the program and yes and 0 to keep playing. \n");
scanf("%d", &answer);
}
return 0;
}
This is one the frequent cases of misunderstanding/forgetting how scanf works.
int scanf ( const char * format, ... );
reads formatted data from stdin.
It reads data from stdin and stores data according to the parameter format into the locations pointed by the additional arguments.
The additional arguments should point to already allocated objects of the type specified by their corresponding format specifier within the format string.
It means that arguments should be pointers.
In your case:
int answer;
scanf("%d", answer);
answer is not a pointer but the variable (object) of type int.
To satisfy the scanf you have to use a pointer to the answer.
You can do it using the unary or monadic operator & which gives the address of a variable.
scanf("%d", &answer);
or you could use a pointer pointing to the answer:
int answer;
int answer_ptr = & answer;
scanf("%d", answer_ptr);
which is also correct but typically there is no need to go for this construction.
Secondly the line:
while(answer <1 || answer > 2)
You may want to modify it to
while (answer != 1 && answer != 2)
if you are interested in breaking the while loop when answer is being equal to 1 or 2.

Why is the while loop not working?

im new to c language and i am facing some problems with my code.. I have to make a program that computes the prices for renting cars but the while loop is not functioning properly.The scanf above the while condition is %s and not %c because it wont let me give a characther when it is %c.Thank you in advance.
int main(){
float skms, ekms, tkms, price;
char catcode;
int days;
do{
printf("Selected rental program:\n");
scanf("%c",&catcode);
printf("Enter number of days:\n");
scanf("%d",&days);
printf("Starting kilometers display:\n");
scanf("%f",&skms);
printf("Kilometers display at end of rent:\n");
scanf("%f",&ekms);
tkms=(ekms/10)-(skms/10);
switch(catcode){
case'a':
case'A':
price=ammountDueA(days, tkms);
printf("%.2f\n",price);
break;
case'b':
case'B':
price=ammountDueB(days, tkms);
printf("%.2f\n",price);
break;
case'c':
case'C':
price=ammountDueC(days, tkms);
printf("%.2f\n",price);
}
printf("Select rental program.('Q' or 'q' to exit)\n");
scanf("%s",&catcode);
}while(catcode==!'Q'&&catcode==!'q');
printf("%c",catcode);
return 0;
}
By "not working", I suppose you mean that it never enters a second iteration, but that is exactly what it is supposed to do. catcode==!'Q'&&catcode==!'q' is true if catcode is equal to !'Q' and equal to !'q'. 'Q' is some non-zero integer (depends on your system, but is probably 81), and !'Q' is zero. Similarly, !'q' is zero. catcode isn't zero, so the loop terminates.
There are two problems in your code:
First of all, the specifiers in scanf...
scanf("%s", &catcode);
This won't work. The "%s" specifier expects its corresponding argument to be a char* to a buffer of unspecified length (i.e: this has the same problem as gets()). You probably meant "%c", whose corresponding argument shall point to a single character. Now, your format specifier is not recommended to be "%c", but " %c", because that extra space indicatesscanf()to ignore all whitespace it can before"%c"`. So, that line becomes...
scanf(" %c", &catcode);
Now, you're right, there's a problem in your while loop:
while(catcode==!'Q'&&catcode==!'q');
Let's "expand" this with whitespace, to make what you (apparently) intended more obvious (that's reason #1 to use spaces between operators!)...
while(catcode ==! 'Q' && catcode ==! 'q');
For you it appears okay. Not for me. The C language does not define any operator ==!, rather, it defines operator == (that compares for equality), and operator ! (that negates its single operand). The compiler would have understood that line as...
while(catcode == !'Q' && catcode == !'q');
Now, what does that mean? If the operand is non-zero, the ! operator returns zero (in this case, the null character, '\0'). Otherwise, it returns a non-negative value (usually 1 (does the standard mandates this?)). Because 'Q' is not '\0', and same for 'q', that means that your loop is effectively...
while(catcode == '\0' && catcode == '\0'); // Think of '\0' as 0
Absolute non-sense expressed in code! The solution is to simply use operator != (compares for inequality)...
while(catcode != 'Q' && catcode != 'q');
I hope this has led some light on you!

Warning: comparison b/w pointer and integer in C.

int main()
{
char name[10], food[10], color[10], ans[10];
int height, year, age, date;
/* Ask for user inputs and do stuff here */
/* ------------------------------------- */
printf("Would you like me to repeat this?\n");
scanf("%c", ans);
/* its giving me a warning for the if condition on the line */
/* below saying warning: comparison b/w pointer and integer. */
if (ans == 'y')
printf("ok I will\n");
else
printf("fine.\n");
return 0;
}
At the end of the program, I wrote an IF statement where if user types "y" then it'll say "ok I will" ELSE say "fine" -nothing fancy.
But when I run it, the program would ask me "Would you like me to repeat this?" and even though I type "y" the program will output "fine" instead of "ok I will"... please help.
The variable ans is an array, and can decay to a pointer to the first element. You compare it to a character.
You should change to e.g. ans[0] == 'y'.
Or even better, since you only read a single character, why us an array at all? Just declare ans as a single character, and use the address-of operator in the scanf call:
char ans;
scanf(" %c", &ans);
if (tolower(ans) == 'y') ...
You're comparing ans which is regarded as pointer ,to 'y' which is regarded as integer. change char ans[10] to char ans.

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

Having trouble with do while loops in C

I am a beginner at C and I am writing a basic program that converts dollars to euros. For some reason the program is not running this line: "scanf("%c", &yn);". If I remove the do while loop the program works fine.
Instead of stopping and waiting for the user to enter 'y' or 'n' the loop restarts and asks for the usd amount again.
#include<stdio.h>
main()
{
float usd = 0.00;
float euro = 0.00;
char yn;
const float conversion = 0.75;
do {
/*get amount to convert*/
printf("Please enter the amount of USD you want to convert to Euros: ");
scanf("%f", &usd);
/*convert amount*/
euro = (usd * conversion);
/*output results and ask to continue*/
printf("\n%.2f USD equals %.2f Euros. Do you want to convert another amount? (y/n): ", usd, euro);
scanf("%c", &yn);
printf("\n");
/*if yes, get new amount to convert. if no, program ends*/
} while (yn = 'y');
return 0;
}
Thanks in advance.
do {
// ...
} while( yn == 'y'); // At this statement you are making an assignment,
// not comparison. Use the equal to operator.
Your scanf is picking up the newline from reading the float previously. You need to account for the new line, scanf(" %c", &yn); should work.. Even once you enter a 'y' or a 'n' the evaluation will fail because you are assigning 'y' to yn which would always evaluate as true. change it to while( yn == 'y').
You need to change yn = 'y' to yn == 'y'. In the first case, you're setting yn to 'y' while what you want to do is compare it to 'y'. The == operator is used for comparisons.
You meant to do == in your while condition, not a single =, that will always evaluate truthfully.
Give a space in the second scanf before the %c like this scanf(" %c", &yn);.
Also go through this question, quite similar to your problem:
Noticing strange behavior with strings in c
Also as pointed out by others:
while (yn = 'y'); will be (yn == 'y')
while (yn = 'y') should be while (yn == 'y')
You've proboly noticed, and understood the silly bug, however, this is a very common bug, and it's really hard to trace, because the assignment operation always return the right value of the assignment. There are two ways to minimize the chance for such a bug. the first is to use #define equals =.
The other one is two always replace the order of comparisment. so yn == 'y' will become 'y' == yn. In this way, if by mistake replace the == with = you'll get compilation error.
I don't know a single person who haven't stumbbled upon this bug...
As others have pointed out, the problem is that you've accidentally written an assignment statement instead of the equality test. We've all done that.
But on a side note, as a junior C programmer you may come across advice telling you to switch the order of the operands in an equality test (which will cause a compile error if you make that same mistake), or #define EQUALS (or, on a related topic, TRUE and FALSE). This is very bad advice.
Reversing the order of the operands makes the code harder to read, because you don't actually want to compare the constant to the variable, you want to compare the variable to the constant. (Also, it won't help at all if you are comparing two variables.) Using #defines also clutters up the code with irrelevant nonsense. There is no boolean datatype in C, and C does have similarly named assignment and equality operators.
The better advice is to learn the language, not try to make it look like something it's not.

Resources