Program works fine in Debug, but not in Release - c++

I made a tic-tac-toe game which works good. Recently I decided to add a reset game feature.
Here is the part where I take input from user
void playerMove() //Gets the player move and updates the box variables
{
int boxnumber;
while(1) //Set's loop if the player enters a invalid input
{
cout << "\n Player " << player << "'s turn!(Press 0 to reset the game!): ";
cin >> boxnumber;
if(box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0) // Checks if the input is valid or not
{
system("CLS");//If invalid, show error and loop back to start to get new input
displayBoard();
cout << "\n Invalid Input! Try again!\n";
}else if(boxnumber == 0)
{
refreshGame();
displayBoard();
}else
{
box[boxnumber-1] = player;//If inputs are fine, set the box variable's and break out of loop!
break;
}
}
}
Now, in debug mode, when I press 0, everything runs fine and the game is reset, but in release build, when I press 0, it gives me the "Invalid Input! Try again!"
Things I have tried the didnt work:
-Rebuild the entire release and debug version.
-Making a new project and copy-pasting my code. Same thing, debug works, release doesnt.
For anyone wondering, I am using code::blocks IDE. The compiler is GNU GCC.
Thanks for the help! :)

You have undefined behavior.
In the "first" if you have box[boxnumber-1], so when you enter 0 (as you have stated in your question), you're trying to access element with index -1. That's UB, as you're reading "invalid" memory.
You should check for 0 first (and for negative numbers also).

In the if statement, put the range checks in front of the value checks. That is, change
if(box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0)
to
if(boxnumber < 0 || box number > 9 || box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O')
That takes advantage of short-circuiting: if the input value is less than 0 or greater than 9 the value checks won't be executed. That will avoid checking things like box[10], which isn't valid.
That still leaves a problem: if the user inputs 0, this code will happily check box[-1], which is also out of range. To get rid of this, move the branch of the if statement that tests box number == 0 in front of this part:
if (box number == 0)
// whatever
else if (box[boxnumber-1] == 'X' || box[boxnumber-1] == 'O' || boxnumber > 9 || boxnumber < 0)
// whatever else

Related

Infinite Loop When Using Function Return Value as a Statement [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 5 years ago.
Was making a small code for a text based game but i tried to do thinks a bit different than the tutorial sort of to test my understanding but i tried to get a function value to make a do while statement but it seems whether the statement false or true the code just keep looping infinitely im a beginner so pls if you have a time explain why the code is faulty and Thank you in Advance
The main function
int main() {
PrintIntroStart();
do {
PlayGame();
AskToPlayAgain();
} while (AskToPlayAgain() == true);
return 0;
}
the Bool Function
bool AskToPlayAgain(){
//Asking The Player Whether To Play Again Or Not
std::string PlayerResponse = "";
std::cout << "Do You Want To Play Again? (Yes/No)" << std::endl;
std::cin >> PlayerResponse;
if (PlayerResponse[0] == 'y' || 'Y')
return true;
else
return false;
}
Also, here you are asking twice to play again
do {
PlayGame();
AskToPlayAgain();
} while (AskToPlayAgain() == true);
this should be
do {
PlayGame();
} while (AskToPlayAgain() == true);
if (PlayerResponse[0] == 'y' || 'Y') this one should be
if (PlayerResponse[0] == 'y' || PlayerResponse[0] == 'Y')
Otherwise your if condition is always true, because 'Y' itself is non-zero.
And in fact you don't need this if statement, just
return PlayerResponse[0] == 'y' || PlayerResponse[0] == 'Y';
So first of all, you are only checking the outcome of the game every second play.
You should follow #ziza s answer and remove the function call inside the loop.
The second problem, that causes the infinite loop is your input check.
A bool value in c++ is not a single bit, but just anoter regular value that is evaluated as false if it is 0 and to true if it has any other value. In your case the first comparison will evauate to 1 if the player input is 'y' and the second part of the condition will be the value of the 'Y' character (which is not 0). So your condition will always be true like #liliscent stated.

program doesnt enter if condition , gives segmentation fault

the code is somewhat like
cin >> n // test cases
for( n times )
{
.....
for(;;)
{
getline(cin,inp) //inp is supposed to be +,-,*,\,0-9,if simply enter pressed program passes out of loop
for(;;)
{
if (inp[0] == '*')
{
do stuff...
}
if (inp[0] == '\')
{
do stuff...
}
if (inp[0] == '+') \\ this is where the problem occurs
{
do stuff...
}
.....
.....
}
}
return 0 ;
}
here is the actual code with some comments ,i have tried converting infix to postfix inn the program . here's my input and the problem...
>1 //1 test case
>3 //if condition as it should entered line 124
>inp[0] 3 //confirms 3 is inp[0]
>* //works as it should (if condn entered line 37)
>inp[0] *
>/ //works as it should
>inp[0] /
>+ //problem!! if condition not entered even though it should
//as inp[0] == '+' (line 61)
>inp[0] + //confirmation inp[0] is + right before if condition checked
>Segmentation fault (core dumped)
I tried my level best to explain the code and the problem briefly, i ask this question as the problem looks totally ambiguos to me , any explanation needed pls tell me .
Also , give any suggestion to debug problems like these , i have got such errors before and i cant everytime ask here. Give any reccomendation to an beginner->amatuer coder for solving such segmentation faults .
thanks and regards
General advice:
use breakpoints and other features provided by your ide to find your problem.
It's been decades since c++ was born, there won't be such bug.
diag:
for debug message, change cout<<"+ detected"; to cout<<"+ detected"<<endl ;. endl for flushing the buffer and put it to screen.
it do enters your if-condition and failed at
if (stk.top() == '*' || stk.top() == '/' && stk.size() != 0 )
if stk.top() succeed, of course stk.size() != 0. It's not empty.
if stk.empty() == true, stk.top() will try to get something from an empty stack and throws seg fault back.
and just few lines below this there's another if-statement with the same mistake:
else if (stk.top() == '-' && stk.size() != 0 )
I changed these line and code works for your input sequence 1 3 * / +.

Issue with for loop, it reads both if and else if statement

I have an issue with my for loop. It goes through two arrays and compares the account number and PIN. An if statement checks if the combination of account number and PIN are correct. Since I changed this part (user_Account != accounts[i] || user_Pin != pins[i]) from the original (user_Account == accounts[i] && user_Pin != pins[i]), this happens. Before that it worked perfectly, but I was afraid that if someone types wrong account, then the program might crash so I made that change. Here is part of the code, I can post more if needed. Please have one thing in mind I am in beginning class, so no advanced changes or recommendations, I need something on my current level. I appreciate any help.
for (int i = 0; i < 6; i++)
{
if(user_Account == accounts[i] && user_Pin == pins[i])
{
cout << "You entered correct combination of account and pin number." << endl;
}
else if(user_Account != accounts[i] || user_Pin != pins[i])
{
cout << "You entered wrong account and/or wrong pin number. Please start over." << endl;
return 0;
}
}
When you converted from
(user_Account == accounts[i] && user_Pin != pins[i])
to
(user_Account != accounts[i] || user_Pin != pins[i])
you should have converted to:
(user_Account != accounts[i] || user_Pin == pins[i])
You are actually applying something called De Morgan's laws, and it's worth reading up on them for the history at least :).
Regarding if you should have separate if-else clauses for account fail compared to PIN fail - that's kind of a design decision. If someone was trying to break into your 'bank' and was guessing both the PIN and the account number from, say, looking over someone's shoulder, then seperate error messages would help him/her find the correct combination more quickly. On the other hand, if (more likely) a customer has just make a typing error, it's nice to have a message telling them. It's pretty much up to you.
If there are only two cases:
Both account id and password match
or
At least one doesn't match
I would just save yourself the headache of a second condition and let the check be this:
if (user_Account == accounts[i] && user_Pin == pins[i])
// accounts match message
else
// accounts don't match message
Also, a pointer on your for loop: you might want to make sure the for loop doesn't keep going when one of the arrays runs out, so your for loop signature could be this:
for (int i = 0; (i < accounts::size) && (i < pins::size); i++)

if condition on turbo C++

I'm having a problem regarding with if statement in C++ this statement is in do-while loop.
gotoxy(27,22);cout<<"Do you want to continue [Y]?";
sub=getche();
if(sub!='y' || sub!='Y')
{
gotoxy(27,24);cout<<"INVALID ANSWER!!";
gotoxy(27,26);cout<<"Closing Program....";
delay(3000);
exit(1);
}else
{
sub=ans;
}
}while(tolower(ans)=='y');
whenever I input y on the variable sub the code on if statement is still executing.. please someone tells me where is the error.. Thanks!
The boolean expression of (sub!='y' || sub!='Y') will always evaluate to true
This line:
if(sub!='y' || sub!='Y')
Needs to be this:
if ( (sub != 'y') && (sub != 'Y') )
Your code if(sub!='y' || sub!='Y') will be true ,no matter what you enter because eithersub!='y' or sub!='Y' will evaluate to true. Hence Use && instead of ||.

getchar() doesn't actually take input from user

I am writing a flexible command-line (but not for long!) diamond-square generator in C++. I have just finished writing the user input half. However, on the very last command, input "slips" and a newline is automatically inputted to getchar(). I have taken precautions to ensure that it's not any sort of overflow, namely, fflushing both stdin, and, for good measure, stdout. The problem persists. Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main () {
unsigned long seed = 0, x = 0, y = 0, initial = 0, range = 0;
int smooth = 0, fail = 1;
char flagchar1 = 'n';
printf("Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. ");
do {
printf("Please input the seed (this is a positive integer):\n");
fail = scanf("%lu", &seed);
while (fail == 0) {
printf("Try again, smartass.\n");
fail = scanf("%lu", &seed);
}
fail = 1;
printf("Now input the x, or horizontal, size of your grid:\n");
fail = scanf("%lu", &x);
while (fail == 0) {
printf("An integer. Not a string. An integer. You can do that, can't you?\n");
fail = scanf("%lu", &x);
}
fail = 1;
printf("Now input the y, or vertical, size of your grid:\n");
fail = scanf("%lu", &y);
while (fail == 0) {
printf("What was that supposed to be? An integer, please.\n");
fail = scanf("%lu", &y);
}
fail = 1;
printf("Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):\n");
fail = scanf("%lu", &initial);
while (initial == 0 || initial > 256 || fail == 0) {
printf("ahahahahaha how HIGH do you have to be just to HAVE that hieght........\n");
fail = scanf("%lu", &initial);
}
fail = 1;
printf("Now input the range of the heights on your grid (this must be equal to or less than 256):\n");
scanf("%lu", &range);
while (range >= 256 || fail == 0) {
printf("What did I say about being equal to or less than 256? Give me something reasonable to work with here.\n");
fail = scanf("%lu", &range);
}
fail = 1;
printf("Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!\n");
fail = scanf("%d", &smooth);
while (fail == 0) {
printf("That... was not a number.\n");
fail = scanf("%d", &smooth);
}
fail = 1;
printf("\nOkay. Are these the values you want?\n Seed: %lu\n Width: %lu\n Length: %lu\n Height: %lu\n Range: %lu\n Smoothness: %d\nDo you want to keep these? Type Y/n.\n", seed, x, y, initial, range, smooth);
fflush(stdin);
fflush(stdout);
flagchar1 = getchar();
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');
}
Here is my output, the program having ended (the program just repeats the entire do-while loop if I remove the && flagchar1 != '\n' from while()):
Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. Please input the seed (this is a positive integer):
12345678
Now input the x, or horizontal, size of your grid:
40
Now input the y, or vertical, size of your grid:
30
Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):
1288
ahahahahaha how HIGH do you have to be just to HAVE that hieght........
128
Now input the range of the heights on your grid (this must be equal to or less than 256):
30
Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!
10
Okay. Are these the values you want?
Seed: 12345678
Width: 40
Length: 30
Height: 128
Range: 30
Smoothness: 10
Do you want to keep these? Type Y/n.
What's happening, and how do I fix it?
P.S. I know my input validation is essentially useless. Help with this is also greatly appreciated.
Make the end of your loop look like this:
// Ignore remaining characters on current line.
int ch;
while( (ch = getchar()) != EOF && ch != '\n')
;
// fetch first character on next line
flagchar1 = getchar();
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');
You are leaving the '\n' in stdin after your last call to scanf.
You must not rely upon fflush(stdin) having any specific behavior. The result of invoking fflush on a input stream is undefined. See Using fflush(stdin)
The code is behaving exactly as you tell it to. If the user enters 'y', 'Y' or enter, one of those conditions in the while loop will be false, which causes it to exit.
What you want is:
while (flagchar1 == 'y' || flagchar1 == 'Y' || flagchar1 == '\n');
Edit: I would also delete the fflush(stdin) and replace getchar() with fgets(). That will guarantee the entire line is read without having to use fflush, which may be the issue.
I'm guessing you are on Linux? This works fine on VS in Windows. It prompts, reads from keyboard, and if examined contains the correct 'y' or 'Y' in question.
I might suggest you try changing the last scanf to:
fail = scanf("%d ", &smooth);
You could also try calling fpurge() instead of fflush(), but that's non standard, and I think the space at the end of the format string will get you what you want.
The trailing space will ask scanf to consume any extra whitespace (including newlines) in the input data. fflush() probably won't do what you want for input.
I suspect whatever system you are on is indeed leaving the carriage return in the stream and if you print flagchar1 as an int you'll get 10?
Suggestions:
Use C++ streams.
Use tolower or toupper before comparing characters.
Use std::string.
The C language, which uses fgets, gets, fflush, strcmp, has many issues in this area. The C++ language has resolved many of these issues in the std::stream classes.
Since you are not using C++ features, you should change the C++ tag to C.
Try
} while (flagchar1 != 'y' || flagchar1 != 'Y' || flagchar1 != '\n');
instead of
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');