C if statements skipped over - c

I'm currently learning C and am attempting to do the reverse of what some courses are asking for. miniMasterMind is an assignment I found where the user guesses numbers randomly generated by the computer. I'm attempting to make a simple flip on it, where the user tells the computer whether or not its guesses are correct for a user generated 3 digit number.
I have what I think is a fully working program, except my 3 if statements asking for user input sometimes do not work. I can't see any reason for it, but after compiling I often find one or two of the if statements to just skip over the user input. I put in system("pause")'s after each step to make it easier to see.
Each turn in the game, a different set of if statements seems to break. Why is this happening?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// Initialize variables
int UCMain = 0;
int CG1 = -1, CG2 = -1, CG3 = -1;
int win1 = -2, win2 = -3, win3 = -4;
char check1 = 'A', check2 = 'B', check3 = 'C';
int turnCount = 0;
// Print out start screen
printf("Welcome to masterMind reversed! Let's see how this works out!\n\n");
// Accept user input
printf("Type in a three digit number for the computer to guess.\n");
scanf_s("%d", &UCMain, 3);
const int UC1 = (UCMain / 100) % 10;
const int UC2 = (UCMain / 10) % 10;
const int UC3 = UCMain % 10;
printf("\nTest print, UC1: %d UC2: %d UC3: %d\n", UC1, UC2, UC3);
system("Pause");
// Start game loop
while (turnCount < 10)
{
// Random number gen
srand((int)time(0));
// 1st number
if (win1 == UC1)
{
CG1 = win1;
}
else if (win1 != UC1)
{
CG1 = rand() % 10;
}
// 2nd number
if (win2 == UC2)
{
CG2 = win2;
}
else if (win2 != UC2)
{
CG2 = rand() % 10;
if (CG2 == CG1)
{
CG2 = rand() % 10;
} // End unique check
}
//3rd number
if (win3 == UC3)
{
CG3 = win3;
}
else if (win3 != UC3)
{
CG3 = rand() % 10;
if (CG3 == CG2 || CG3 == CG1)
{
CG3 = rand() % 10;
} // End unique check
}
// End random number generation
printf("The computer guesses: %d%d%d\n", CG1, CG2, CG3);
system("Pause");
// Check if numbers are correct
if (win1 != UC1)
{
printf("Is the first number correct? Y/N\n");
scanf_s("%c", &check1, 1);
if (check1 == 'Y')
{
win1 = UC1;
} //
}// End 1st check
system("pause");
if (win2 != UC2)
{
printf("Is the second number correct? Y/N\n");
scanf_s("%c", &check2, 1);
if (check2 == 'Y')
{
win2 = UC2;
} //
}// End second check
system("pause");
if (win3 != UC3)
{
printf("Is the third number correct? Y/N\n");
scanf_s("%c", &check3, 1);
if (check3 == 'Y')
{
win3 = UC3;
} //
}// End third check
system("pause");
// Check if game is over
if (win1 == UC1 && win2 == UC2 && win3 == UC3)
{
printf("The computer wins!");
}
turnCount++;
} // End while
// Win/lose state
if (turnCount == 10)
{
printf("The computer loses!");
}
}

it is not really skipped:
it is taking a character the newline character: '\n'
Using a scanf with a space before it:
scanf(" %c", &b); // this one will work instead
Will tell the scanf that any white space characters (including the newline '\n') left on stdin should be ignored.
please read more about scanf here

scanf() is reading all user input, including line feed and carriage return characters. If the user types "1" and presses enter, you'll actually get 2 (or 3, depending on the platform) input characters, one for the digit and one or two for the newline character(s). This will stimulate 2 or 3 iterations of your loop when you only intended one.

Related

A Hangman game is not working when entering a guess, but a random word form list work

I am trying to write the logic for the Hangman game.
I want to be able to enter a word and to get a random word from a list.
The part in which that I choose a random word works great without a problem. The problem starts when I enter a word. No matter if I am guessing the correct char it will still count as a strike.
What is the explanation for why this is happening?
int main()
{
int option=5, randomword;
bool loop = true;
// here you choose if you want a random word or to enter one by yourself.
while (loop)
{
printf("choose an option:\n0 to enter a word.\n1 for the computer to choose a word for you.\n");
scanf("%d", &option);
// start the loop over again if the value that got scan is not 0 or 1;
if (option == 0 || option == 1)loop = false;
}
char EnterdWord[128];
// if you choose to enter a word it will scan it and enter it to a string. I am using fgets so you can enter space
if (option == 0)
{
printf("enter a word:\n");
getchar();
fgets(EnterdWord , 128, stdin);
}else // if you want a random word, this will make a random number, so later it will choose a random word from a list.
{
srand(time(NULL));
randomword = rand() % 20 ;
}
// random words list
char RanWord[][20] = {"dog", "cat", "sky", "orange", "apple", "movie", "code", "number" ,"ship" ,"google" ,"sushi" , "shower",
"super hero", "job interview" ,"computer" ,"video games" ,"pizza" ,"cell phone", "charger", "bottle"};
char *TempWord = malloc(1024 * sizeof(char));
// remove the \n from the scan in fgets.
if (*EnterdWord && EnterdWord[strlen(EnterdWord)-1] == '\n')EnterdWord[strlen(EnterdWord)-1] = 0;
// give to the string TempWord the word based on the option u choose
if (option == 0) strcpy(TempWord, EnterdWord);
if (option == 1) strcpy(TempWord, RanWord[randomword]);
//this is the string that you are going to scan your right guess.
char *NiceWord = malloc(1024 * sizeof(char));
if (NiceWord == NULL) return 0;
// copy temp word to nice word
strcpy(NiceWord, TempWord);
// finding the length of the word for the loop below (I know I can use while != \0)
int lengh = strlen(TempWord);
int i=0;
// this part is for aesthetics. I could have just changed all the characters to space.
while(i < lengh)
{
if (TempWord[i] != ' ')NiceWord[i]='_';
if (TempWord[i] == ' ')NiceWord[i]=' ';
i++;
}
loop = true;
char guess;
// bool verb to check for strikes.
bool CheckStrike = true;
int y, strikes=0;
// print so you can see how many characters the word is.
printf("\n%s\n", NiceWord);
while (loop == true)
{
y=0;
//scan your guess.
printf("enter your guess:\n");
getchar();
scanf("%c", &guess);
// reset the strike checker in case you where right for the last guess
CheckStrike = true;
// check if your guess is correct or not.
while(TempWord[y] != '\0')
{
if ( TempWord[y] == guess)
{
NiceWord[y] = guess;
CheckStrike = false;
}
y++;
}
// if your guess was false, add one strike
if (CheckStrike == true)strikes++;
printf("you have %d strikes left\n", 10-strikes);
printf("%s\n", NiceWord);
// check if you lost
if (strikes == 10)
{
printf("the word was: %s\nyou lost :( ", TempWord);
loop = false;
}
// check if you won
if (strcmp (NiceWord, TempWord) == 0)
{
printf("\n\n\n\nu won :) with %d strikes left!\n\n\n\n\n", 10-strikes);
loop = false;
}
}
return 0;
}
Use:
printf("enter your guess:\n");
if (option == 1)
getchar();
scanf("%c", &guess);
if (option == 0)
getchar();
This solves the problem.

C: first number in array becomes 0 for unknown reason

The Program:
This was supposed to be a simple reverse polish notation addition program, please ignore the EOF break thing, it's a placeholder.
Input is c, always one numeral number, it gets transfered to x where every next numeral c will be added to the number x, so for example when we input c as 1,2 and 3 x will be 123.
When we input 'e' it will mark the start of a new number, and x will be transfered to the stack[0] after the entire stack gets pushed back, and x will become 0. When inputing '+' addition happens, the last two numbers will be summed, x and the first number in the stack, or the first and second number in the stack, or the first number in the stack will duplicate itself.
The Problem:
The first number in the stack array will randomly become 0 and I cannot see where I made the error. The first number (stack[0]) only gets the value zero at the start, never again. At times when inputting '+' it will just get a value.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int stack[16];
int x;
int i;
char c;
//int c;
x=0;
for (i = 0; i < 16; i++)
{
stack[i]=0;
}
while(1)
{
//input character
scanf("%s", &c);
if (c == EOF) break;
//put x to stack
else if (c == 'e')
{for (i = 15; i >0; i--)
{
stack[i]=stack[i-1];
}
stack[0] = x;
x = 0;
}
//reverse polish addition
else if (c == '+')
//if x is 0 go immediately to the stack
{if (x == 0)
//if both x and the second number in array are 0 just duplicate the first number
if (stack[1] == 0)
stack[0] = stack[0] + stack[0];
//if only x is 0 add the first number on the second
else
{
stack[0]=stack[0]+stack[1];
//push back the array to fill the gap on the second number
for (i = 1; i <15; i++)
{
stack[i]=stack[i+1];
}
}
else
{
stack[0] = stack[0] + x;
x = 0;
}
}
else
{
x = x * 10 + ((int)c-0x30);
// putchar(c);
}
printf("X=%d\n",x);
//print stack
for (i = 0; i < 16; i++)
{
printf("%d \t",stack[i]);
}
printf("\n");
}
return 0;
}
Problem 1
scanf("%s", &c); causes undefined behavior. Use scanf(" %c", &c);.
Problem 2
c is never going to be equal to EOF by using scanf. Hence, the following line is useless.
if (c == EOF) break;
The following will take care of both problems.
// Use " %c" instead of "%c" to skip leading whitespace characters.
while ( scanf(" %c", &c) == 1 )
{
}

Number guessing what the user has in mind C

I'm trying to create a program where the program guesses what kind of number the user has in mind. First it will ask the user for a minimum and maximum number, for example 1 and 10(the number I have in mind should be between 1 and 10 then).
Lets say I have the number 4 in mind and the program will output a number. I can type in L for low, H for high or G for good.
If I type in L, the program should generate a number lower than the guessed number, for H it should guess an higher number. If I input G, the program should stop and print out how many times it guessed.
I have added my code below, what am I missing?
#include <stdio.h>
#include <stdlib.h>
int main() {
int minNumber;
int maxNumber;
int counter;
printf("Give min and max: ");
scanf("%d %d", &minNumber, &maxNumber);
//printf("%d %d", minNumber, maxNumber);
int num_between_x_and_y = (rand() % (maxNumber - minNumber)) + minNumber;
char input[100];
do {
printf("is it %d? ", num_between_x_and_y);
scanf("%s", input);
if (input == 'L') {
counter++;
}
if (input == 'H') {
counter++;
}
} while (input != 'G');
printf("I guessed it in %d times!", counter);
return 0;
}
I do not see any "counter" variable initialization
int counter = 1;
I do not see the new random number regeneration in the cycle, it should be something like:
do {
printf("is it %d? ", num_between_x_and_y);
scanf("%s", input);
if (input[0] == 'L') {
counter++;
maxNumber = num_between_x_and_y;
}
if (input[0] == 'H') {
counter++;
minNumber = num_between_x_and_y;
}
num_between_x_and_y = (rand() % (maxNumber - minNumber)) + minNumber;
} while (input[0] != 'G');
You can't use == to compare strings (which are multiple bytes).
Either do if (input[0] == 'L') to just compare the first letter the user entered to a literal value, or if (strcmp(input,"L") == 0) to compare everything the user entered to the 1 character string literal (to use strcmp you will need to add #include <string.h>
Also your code is missing other things, like counter should be set to presumably set to zero before you use it. I assume you haven't finished your code yet because you can't get the user input part to work.

Numeric input validation in C

I am doing a lab for an intro programming class
I have to make sure that an integer is entered. I thought this would do it but when I put in a letter it repeats in an endless loop.
I found this solution in another post
int num;
char term;
if (scanf("%d%c", &num, &term) != 2 || term != '\n')
printf("failure\n");
else
printf("valid integer followed by enter key\n");
But im not sure what I did wrong. Why is it not working in my code?
#include <stdio.h>
int main(void)
{
int oneVar;
char term;
double numOne;
double numTwo;
double sum;
double dif;
double quo;
double mult;
int checker = 1;
do
{
printf("Please choose one of the following:\n""1) Add\n""2) Subtract\n""3) Divide\n""4) Multiply\n""5) Quit\n");
if (scanf("%d%c" , &oneVar ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
else if (oneVar == 5)
{
printf("Thank you. Goodbye.\n");
checker = 0;
}
else if (oneVar != 1 && oneVar !=2 && oneVar != 3 && oneVar != 4)
{
printf("This is not a valid input\n\n");
checker = 1;
}
else
{
printf("Please enter the first number:\n");
if (scanf("%lf%c" , &numOne ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
printf("Please enter the second number:\n");
if (scanf("%lf%c" , &numTwo ,&term) != 2 || term != '\n')
{
printf ("This is not valid input\n\n");
checker = 1;
}
else if (oneVar == 1)
{
sum = numOne + numTwo;
printf("The sum is: %.2lf\n" ,sum);
checker = 0;
}
else if (oneVar == 2)
{
dif = numOne - numTwo;
printf("The difference is: %.2lf\n" ,dif);
checker = 0;
}
else if (oneVar == 3)
{
quo = numOne / numTwo;
printf("The quotient is: %.2lf\n" ,quo);
checker = 0;
}
else if (oneVar == 4)
{
mult = numOne * numTwo;
printf("The product is: %.2lf\n" ,mult);
checker = 0;
}
else if (oneVar == 5)
{
printf("Thank you. Goodbye.\n");
checker = 0;
}
}
} while (checker == 1);
return(0);
}
My prof posted this Im not sure how it helps but I thought it might help someone
To make sure that a user-input number is an integer you can use the notion of casting. Casting is a way to tell C to treat a variable as if it were a variable of a different type.
so, if I have something like this:
double myDouble;
myDouble = 5.43;
printf ("%d", (int) myDouble);
It will tell C to print myDouble, but to treat it like an integer. Only the 5 will be printed and you won't get any type mismatch errors. You can use casting to check to see if an input number is an integer by comparing the input to the (int) cast of the number. Something like this should work:
if(inputNum == (int) inputNum)
You'll still get 1.0 and 2.0 passing as valid numbers, but that is ok for now.
Why complicate things?
char x = 0;
scanf("%c", &x);
if (x >= 0x41 && x <= 0x7A)
printf("you entered a letter");
In ASCII table, letters have values between 0x41 ("A") and 0x7A ("z").
So, you just need to check the ASCII value of the input. :)
Using the %c to "consume" the end of line is not a good solution. If the user enters say:
123 abc<newline>
num will be 123, but term will be the space character. If you enter a letter rather than a number, the scan will stop without consuming any of the characters, the next input call will return due to the already buffered line, and may still consume nothing. Your program loops continuously because every input statement is failing to consume the newline and returns immediately. The standard input functions wait for a complete line before returning, if the line is not read completely, input functions do not need to wait.
There are a number of solutions, many of which such as the one you used are flawed, the method below, forces the input buffer to be flushed up to and including the newline.
int check = scanf( "%d", &num ) ;
while( getchar() != '\n' )
{
// do nothing
}
if( check != 2 )
printf("failure\n");
else
printf("valid integer followed by enter key\n");
If you use the %c format specifier at the end of the input, then a slightly different flush is necessary since the character input may be a newline:
int check = scanf( "%c", &ch ) ;
while( ch != '\n' && getchar() != '\n' )
{
// do nothing
}

Craps game doesnt return right values

wiHi everyone since last time i found extreme help on here, im gonna ask a question again
My code doesnt return right values :
something is wrong in the play_game function and i cant figure out what it is.I believe that all cases are covered but somehow they end up messed up.
also the code doesnt loop for everytime i want to play a game after the second game it stops.
this is not an assignment
any suggestion?
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
static int sum, point, win = 0, roll = 0;
bool play_game(void);
int roll_dice(void);
int main(void){
srand(time(NULL));
play_game();
char input[10];
do{ point = 0;
play_game();
if(win == 1){ // I'm assuming that play returns whether you won or not
printf("You won!\n");
}else{
printf("You lost!\n");
}
printf("Would you like to continue? y/n\n");
gets(input);
}while(*input == 'y'); // gets() flushes the buffer for next time you need input
return 0;
}
bool play_game(void){
point=0;
roll_dice();
printf("Your point is %d\n", sum);
while(roll == 1) /* first round */
{
if(sum == 7 || sum == 11)
return win = 1;
else if(sum == 2 || sum == 3 || sum == 12)
return win = 0;
else if(sum == 1 || sum == 4 || sum == 5 || sum == 6 || sum == 8 || sum == 9 || sum == 10){
point=sum;
roll_dice();
}
}
while(roll > 1) /* all others rounds*/
{
if(sum == 7)
return win = 0;
else if(sum == point)
return win = 1;
else if(sum != point || sum != 7)
roll_dice();
}
}
int roll_dice(void){
int a,b;
a=1+rand() % (6);
b=1+rand() % (6);
sum=a+b;
roll++;
printf("You rolled %d\n", sum);
return sum;
}
OUTPUT
A couple of points:
You probably want 1 + rand() % 6
The return value of printf() is probably not what you want to return from roll_dice()
The loop needs to be more like:
main(){
char input[10];
do{
score = 0; //Always initialize the score
if(play_game()){ // I'm assuming that play returns whether you won or not
printf("You won!\n");
}else{
printf("You lost!\n");
}
printf("Would you like to continue? y/n\n");
gets_s(input, 9);
}while(*input == 'y'); // gets() flushes the buffer for next time you need input
}
Kyle's answer is just fine (as I see it), But I can spot a few problems, hope it'll help you in further cases.
You always win, and I know it's nice, but I bet it's not the expected behavior:
while(true) // This will always happen, because true is always evaluated as true
{
printf("Won\n\n");
printf("Play again? y/n: ");
break;
}
while(false) //This will never happen, since false is always evaluated as false
{
printf("Lost\n\n");
printf("Play again? y/n: ");
break;
}
I think you meant to check the result of play_game(). So add another variable and check against it:
bool win;
win = play_game();
while (win == true)
...
while (win == false)
...
Why using while loop there? you break it in the first iteration anyway
if(win == true)
{
printf("Won\n\n");
}
else
{
printf("Lost\n\n");
}
printf("Play again? y/n: ");
The game will run not more than twice, because you don't have a loop that depends on the answer, but only an if statement that is evaluated just one time:
if(v=getchar() == 'y') //This is the second time the code runs, after that? nada.
{
point =0; /* reset point var */
play_game();
}
else if(v=getchar() == 'n') // Why adding this check? you're going out anyway after the if-else
exit(1);
EDIT
When you use a while loop, what you do is saying:
While (some expression in the parenthesis) is true, execute the code in the block {..} and then check again the expression in parenthesis.
If you write while(true), you actually writing while true is true, execute the code in the block. And this will always happen.
If you write while(false) you actually write while false is true, execute the code in the block. and this false is never true, than it will never execute the code in the block.
If you want a real condition here, you can use while(play_game()). this is like writing, while the returned value from the function play_game is true, execute the code in the block and then the code will be executed only when the play_game function return true (which indicates a win in the game).
There are many good C tutorials out there, start here or here
It is hard to tell from your description (please say what you expected to happen, and what happened instead), but the first thing I notice is that you are rolling 5-sided dice for a and b.
Rolling of the dice is happening at at incorrect points during your game sequence.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// add defines to make states easier to read
#define WIN 1
#define LOSE 0
static int sum, point, win = 0, roll = 0;
//bool play_game(void);
int play_game(void); // changed return type to be int
int roll_dice(void);
int main(void){
srand(time(NULL));
// play_game(); // unncessary
char input[10];
do
{
point = 0;
//play_game();
// if(win == 1){
if(play_game()){ // use return value from play_game()
printf("You won!\n");
}else{
printf("You lost!\n");
}
printf("Would you like to continue? y/n\n");
// gets(input);
fgets(input, sizeof(input), stdin); // a safer input read
} while(*input == 'y'); // gets() flushes the buffer for next time you need input
return 0;
}
// bool play_game(void)
int play_game(void) // changed return type to be int
{
point=0;
// remove as this messes up the roll sequence.
// roll_dice();
// incorrect place to display this message
//printf("Your point is %d\n", sum);
// the while loop here is unnecessary
//while(roll == 1) /* first round */
//{
roll_dice(); // add for initial come out roll.
if(sum == 7 || sum == 11) { // I use braces to remove ambiguity
// return win = 1;
return WIN;
} else if(sum == 2 || sum == 3 || sum == 12) {
//return win = 0;
return LOSE;
}
// sum will never be 1
// on that note if it control reaches here it will be one of the other numbers.
//} else if(sum == 1 || sum == 4 || sum == 5 || sum == 6 || sum == 8 || sum == 9 || sum == 10){
// point=sum;
// roll_dice(); // remove as this messes up the roll sequence.
// }
point=sum;
printf("Your point is %d\n", sum);
//}
// while(roll > 1) /* all others rounds*/
while (1) // might as well loop forever
{
roll_dice(); // add for subsequent dice rolls
if(sum == 7) {
//return win = 0;
return LOSE;
} else if(sum == point) {
// return win = 1;
return WIN;
}
// remove as this is unnecessary
// else if(sum != point || sum != 7)
// remove as this messes up the roll sequence.
//roll_dice();
}
}
int roll_dice(void){
int a,b;
a=1+rand() % (6);
b=1+rand() % (6);
sum=a+b;
// roll++; // unncessary
printf("You rolled %d\n", sum);
return sum;
}

Resources