Generating a dice game - C Programming - c

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

Related

Loop back to question instead of printing out "Try again"? (C)

this is my first day coding and I'm trying to see how the code work, how can I change Y/N to Yes/No and loop back questions if the answer is not Yes instead of printing out "Try again?" or make it better?
int main(void)
{
char answer;
int name;
printf("Enter Username: \n");
scanf("%s",&name);
printf("Is your username \"%s\"? Enter Y or N\n", &name);
while (scanf(" %c", &answer) == 1 && answer == 'Y')
{
char answer2;
Sleep(1000);
printf("Username confirmed\n");
Sleep(2000);
int pass;
printf("Enter your password: \n");
scanf("%s",&pass);
printf("Is your password \"%s\"? Enter Y or N\n", &pass);
while (scanf(" %c", &answer2) == 1 && answer2 == 'Y')
{
printf("Success!");
Sleep(1000);
exit;
}
printf("Try again..\n");
Sleep(1000);
exit;
}
Sleep(1000);
printf("Try again..\n");
Sleep(1000);
exit;
return 0;
}
My best advice, as Weather Vane told you in the comment section, is to try to compile your code, before making changes: you'll find out that it won't even compile, since there are some errors (https://godbolt.org/z/MdahM4sT8).
You should debug and try to figure out why it doesn't work, fix it, then move to the new "features".
You probably want to change the while() condition and read a sequence of characters (array of char) instead of a single char.
char answer[4];
while (scanf("%3s", answer) > 0 && strcmp(answer, "Yes") == 0)
char answer[4]; creates an array of characters (which can be called a string, even though C doesn't have that abstraction) of size 4.
You might want to know why we need a size of 4, since the longer answer we can get is "Yes". Well, a string in C is a sequence of characters (char), ending with a special character, called terminating character '\0'.
Therefore, when you read a string with scanf(), you need to reserve some space for the terminating character aswell, and scanf() will add it when reading a space or carriage return after your input string. So if you enter "Yes" and then press the Return key, your answer[4] buffer will look like: {'Y', 'e', 's', '\0'}.
%3s tells scanf() to read only the first 3 characters of the string (prevents security issues like buffer overflow).
int scanf(const char *format, ...)
Description
Reads formatted input from stdin.
Return Value
On success, the function returns the number of items of the argument list successfully read. If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror) and, if either happens before any data could be successfully read, EOF is returned.
Once you've read that string, you can use strcmp(), a function defined in `<string.h> header, that takes in 2 string parameters, and returns:
a negative value if the first precedes alphabetically the second;
0 if they're equal;
a positive integer if the second precedes alphabetically the second;
Therefore you can check if strcmp(answer, "Yes") == 0 to know if you've read Yes, and

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 read a yes / no response from the user?

Taking a beginning programming class and learning C. This is the first significant obstacle I've run into, was at it for 6+ hours yesterday and couldn't find a solution, so I gave up and decided to ask for help.
Assignment is to build a number guessing game (haven't yet gotten to the random number generation part) with a loop based on a boolean, where the user is prompted after a correct guess to play again and answer y or n.
I've tried a bunch of stuff, and the loop either terminates regardless of the option chosen (which is what it does in its current state), or loops endlessly regardless, and I'm not sure what I'm doing wrong.
Here's my code. Thanks in advance.
#include <stdio.h>
#include <stdbool.h>
int main()
{
int num = 5; /* temp placeholder for testing */
int guess;
char* response;
bool running = true;
while (running)
{
printf("Guess a number: ");
scanf("%d", &guess);
if (guess < num)
{
printf("That's too low.\n\n");
}
else if (guess > num)
{
printf("That's too high.\n\n");
}
else
{
printf("That is correct.\n\n");
guess = 0;
printf("Play again? (y/n): ");
scanf(" %c", response);
printf("Response: [%s]", response);
printf("\n");
if (response == "y")
{
running = true;
}
else
{
running = false;
}
}
}
return 0;
}
You are confusing strings with a single character. Here you have response declared as a pointer to a char.
char* response;
change that to
char response;
change
scanf(" %c", response);
to - this is passing in the address of the one character variable. %c accepts one character.
scanf(" %c", &response);
Change
if (response == "y")
to
if (response == 'y')
string literals use double-quotes. Also if you actually wanted to compare strings, that is not the correct way either, and you should look at the strcmp() function.
The first issue to be aware of is that == is not defined for strings (or other array types) - response == "y" doesn't work like you'd expect1.
To compare strings, you need to use the strcmp library function:
if ( strcmp( response, "y" ) == 0 ) // strcmp returns 0 if the strings match
{
// do something
}
The second issue is that you're confusing your types. You declare response as a char *, meaning that it's meant to store the address of another char object, not a character value. However, you never initialize it to point to a char object - its value is indeterminate, and it's pointing somewhere random. When you call scanf with it, you're writing the input value to some random location which in your case just happens to be writable and not "important" (in the sense that it doesn't cause your code to crash immediately).
You most likely want to do it the way OldProgrammer showed - change the type from char * to char, change the scanf call to use &response, and change the test to response == 'y' (single instead of double quotes).
Alternately, you can treat response as a string - in that case, you'd declare it as an array of char, large enough to hold your response plus the string terminator - in this case, 2 elements:
char response[2]; // 'y' or 'n' plus a string terminator
Instead of using scanf (which is prone to buffer overflows if you aren't careful), we'd use fgets instead:
if ( !fgets( response, sizeof response, stdin ) )
// input operation failed, handle as appropriate
else
// process response
and then as I said above, you'd use strcmp for the comparison:
if ( strcmp( response, "y" ) == 0 )
// process yes response
else
// process no response
Interestingly, you got the format string right for reading a single character (most new C programmers don"t). Unlike most conversion specifiers, %c won't skip over any leading whitespace, and more often than not people wind up reading stray newlines rather than the input they intend. Putting the blank before it in " %c" tells scanf to skip over any leading whitespace.
What it's actually doing is comparing the address value stored in response to the address of the first character of the string literal "y". The only way that expression will ever be true is if response stores the address of the literal "y".

How to fix "Debug Error!, Stack around the variable 'x' was corrupted"?

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.

Why does this if condition not work even if I enter the correct data?

#include < stdio.h >
#include < process.h >
rec();
main() {
int a, fact;
char question, n, y;
do {
printf("\nEnter any number ");
scanf("%d", & a);
fact = rec(a);
printf("Factorial value = %d\n", fact);
printf("do you want to exit.....(y/n):");
scanf("%s", & question);
}
while (question == n);
exit(0);
}
rec(int x) {
int f;
if (x == 1) return 1;
else f = x * rec(x - 1);
return f;
}
In this program I want to get factorial of the entered number, which I get. But I also want the user to say whether to exit or get the factorial of another number, which I can't do. It asks user but when I enter "n" it exits.
Where is the error?
You want
while (question == 'n');
Or
char question, n = 'n', y = 'y';
Though I find the 2nd version a little redundant.
Either way you need to change
scanf("%s"
to
scanf("%c"
To correctly read in a single char and not a string. Thanks RageD
One problem is the combination of:
char question, n, y;
scanf("%s", &question);
You are using %s to read a null-terminated string into a single character. Even if you hit 'y' and return, you'll be overwriting beyond the end of the variable. This is not good. (The good news is that "%s" skips over white space, including the newline after the number).
You either need to use "%c" in the format:
char question;
scanf(" %c", &question); // NB: The leading space is important!
or you need to use a string format and a string variable (and no &):
char question[10];
scanf("%9s", question);
If you use an array, you need to consider whether to use strcmp(), or whether to compare the first character from the input:
while (strcmp(question, "n") == 0);
while (question[0] == 'n');
You probably got told by the compiler that you'd not declared variable n so you added it. You probably need the loop to end with while (question == 'n');and then get rid of the (now) unused variablen(and the currently unused variabley`).
Note that if you use omit the space in the " %c" format string:
scanf("%c", &question);
then it will normally get the newline after the number, which won't be 'n', so your loop will exit every time, apparently without waiting for you to enter anything. You can finesse that with scanf(" %c", &question); which skips white space before reading a character.
You should test that scanf() received the input you expected each time you use it. The correct test for single item inputs is:
if (scanf(" %c", &question) != 1)
...input failed...
If you need to distinguish between EOF and conversion failure, you can capture the return from scanf():
int rc;
if ((rc = scanf(" %c", &question)) != 1)
...rc == EOF on EOF; rc == 0 on 'conversion failure'...
...a single character input can't easily fail...
...but if someone types 'a' instead of '9' when you're looking for a number...
Getting I/O right using scanf() is distressingly hard. Many experienced programmers simply don't use it; it is too hard to get right. Instead, we use fgets() or POSIX getline() to read a line of data, and then use sscanf() to parse it. There are many advantages to this, but a primary one is that the newline has been eaten so you don't run into problems with the variable question not containing the answer you expect.

Resources