Hi i keep getting a stack around the variable nhour was corrupted error, and I can not figure out why. I am trying to have a time entered and check it to make sure it is a good input. making the array bigger or smaller seems not to work. I have also added checks in and the output seems find until I get the error
void DEPARTURETIME(string& szdepartureTime)
{
bool berror;
char cdeparture[9];
int nhour[2],
nminute[2],
nhourValue,
nminuteValue;
nhour[0] = 0;
do
{
berror = false;
system("CLS");
cout << "Enter departure time. (HH:DDAM/PM)" << endl;
cin >> cdeparture;
cin.ignore();
berror = ERRORCHECK();
for (int i = 0; i < 2 && berror != true; i++)
{
nhour[i] = CONVTOINT(cdeparture[i]);
}
//Beginning of testing hour for errors
if (nhour[0] > 1 && berror != true)
{
cout << "Error, can not exceed 12 hours." << endl;
system("pause");
berror = true;
}
else if (nhour[0] == 1)
{
nhour[0] *= 10;
}
cout << nhour[0] << nhour[1] << endl;
nhourValue = nhour[0] + nhour[1];
cout << nhourValue << endl;
if (nhourValue > 12 || nhourValue <= 0 && berror != true)
{
cout << "Error, can not exceed 12 hours and can not be
zero." << endl;
system("pause");
berror = true;
}
//End of testing hour for errors
//Beginning of testing for a colon
if (cdeparture[2] != ':' && berror != true)
{
cout << "Error, you need a colon inbetween hours and minutes." << endl;
system("pause");
berror = true;
}
//End of testing for a colon
for (int i = 3; i < 5 && berror != true; i++)
{
nminute[i] = CONVTOINT(cdeparture[i]);
}
//Beginning of testing for minute errors
if (nminute[3] > 6 && berror != true)
{
cout << "Error, minutes can not exceed 60." << endl;
system("pause");
berror = true;
}
else if (nminute[3] > 0 || berror != true)
{
nminute[3] *= 10;
}
nminuteValue = nminute[3] + nminute[4];
if (nminuteValue > 60 && berror != true)
{
cout << "Error, minutes can not exceed 60." << endl;
system("pause");
berror = true;
}
//End of testing for minute errors
cdeparture[5] = toupper(cdeparture[5]);
cdeparture[6] = toupper(cdeparture[6]);
//Beginning of testing for AM and PM errors
if (cdeparture[5] != 'A' && cdeparture[5] != 'P' || cdeparture[6] != 'M' && berror != true)
{
cout << "Error, must have AM or PM." << endl;
system("pause");
berror = true;
}
} while (berror != false);
//End of testing for AM and PM errors
for (int i = 0; i < 7; i++)
{
szdepartureTime += cdeparture[i];
}
return;
}
and this is the other function that is called
int CONVTOINT(char cchar)
{
int value = cchar - '0';
if (value < 0 || value > 9)
{
cout << "Error, Convertion failed" << endl;
system("pause");
return 0;
}
return value;
}
You declare nminute as an array with two elements, but when you use it you're accessing elements 3 and 4 (which requires the array to have 5 elements). Since you're accessing past the ends of the array, you run into Undefined Behavior. In this case, your compiler has inserted code to detect this problem and is telling you about it.
To fix it, change the subscripting on nminute when used in the code to only access elements 0 and 1.
Related
I'm working on a little poker application and i've run into the first problem I just can't seem to comprehend.
while (allplayersGood != 1) { //round table till all decided
cout << "TOP OF WHILE LOOP";
for (int i = 0; i < PLAYER_COUNT; i++) { //for loop for decisions from non button or blinds
int player_decision = 1;
char choice;
if ((players[i].playerhand.card1.value != 'F') && (players[i].playerhand.card1.value != 'C')) {
if ((players[i].blind != 1 && players[i].blind != 2) && players[i].button != true) {
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
if (playerTable->currentBet > players[i].currentBet) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type F for Fold, B for Call, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'F') {
player_decision = 0;
players[i].fold();
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'B') {
player_decision = 0;
players[i].call(playerTable);
}
}
if ((playerTable->currentBet == players[i].currentBet) && player_decision != 0) { //big blind after round table
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type C for Check, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'B') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'C') {
if (players[i].check(playerTable) == true) {
player_decision = 0;
}
}
}
}
}
else if (players[i].blind == 1 || players[i].blind == 2) {
if (players[i].blind == 1) {
players[i].chip_amount -= sblind;
playerTable->currentPot += sblind;
players[i].blind = 0;
players[i].currentBet = sblind;
}
if (players[i].blind == 2) {
players[i].chip_amount -= bblind;
playerTable->currentPot += bblind;
players[i].blind = 0;
players[i].currentBet = bblind;
}
}
}
}
for (int i = 0; i < PLAYER_COUNT; i++) { //seperate loop for button and blinds that were ignored in loop above
int player_decision = 1;
char choice;
if (players[i].button == true || players[i].blind == 1) { //button and small blind
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type F for Fold, B for Call, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'F') {
player_decision = 0;
players[i].fold();
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'B') {
player_decision = 0;
players[i].call(playerTable);
}
}
}
cout << i;
if (players[i].blind == 2) { //big blind
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "C for Check, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'C') {
if (players[i].check(playerTable) == true) {
player_decision = 0;
}
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
}
}
}
int playersBetting = 0;
int playersGood = 0;
int playersChecked = 0;
int playersNot = 0;
for (int i = 0; i < PLAYER_COUNT; i++) {
if (players[i].playerhand.card1.value != 'F') {
playersBetting++;
if (players[i].currentBet == playerTable->currentBet) {
playersGood++;
}
}
}
for (int i = 0; i < PLAYER_COUNT; i++) {
if (players[i].playerhand.card1.value != 'F') {
if (players[i].isChecked == true) {
playersChecked++;
}
else {
playersNot++;
}
}
}
cout << playersBetting << playersGood;
if ((playersBetting == playersGood) || (playersNot == 0)) {
cout << "NEXT ROUND STARTED";
}
}
The issue is, during the second for loop with comment "seperate loop for button and blinds that were ignored in loop above" after the first if statement succeeds because players[0] has button equal to true, the player will make the terminal input as a decision, and the program will exit the for loop and go down to the end with the playersBetting and playersGood loops, then return back to the for loop at index 1 correctly.
I'm sorry if this is a little complicated to understand there is a lot of code that I probably didn't put into context very well, if you need any extra information please let me know.
Thank you.
You seem to have different loops inside one another. This is possible, but in that case, you need to use another loop variable (j instead of i), let me show you what happens:
for i ...
for j ...
This causes the following values to be taken for i and j:
i j
1 1
1 2
1 ...
1 n
2 1
2 2
2 ...
2 n
...
n 1
n 2
...
n n
... and here it stops.
If you keep using i in the inner loop, this is what you get:
i (outside loop) i (inside loop)
1 1
2 2 // indeed: changing i inside also changes i outside
... ...
n n
So you jump out of the outside loop, even after just having looped the inside loop one time.
I figured it out, it was unrelated to the actual loop and actually had to do with a value I changed upstream. Thank you for the few who tried to help with such little context haha
Have a good one
I am using for loops combined with if statements to read integers from a text file into a two-dimensional array.
This is my code:
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
if (invalidnum = true) {
cout << *(*(ArrB + i) + j) << " ";
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
}
}
This code will read in the first 6 integers (max_row * max_column) from a text file into ArrB.
If -1 exists in the first 6 integers, it will exit the loop and print out "The array does not have enough integers".
If there is no -1 in the first 6 integers, then it will check all 6 integers to see if there are any other negative numbers or zero.
If there are negative numbers or zero, I want it to still print out the array, then print out the error message (There is/are negative number(s) or zero(s) in the array imported from your text file) ONLY ONCE.
For example, this is my text file. As you can see, there is no -1 in the first 6 numbers, but there is a -7.
So, ideally, the result should be something like:
2 4 5 6 9 -7
There is/are negative number(s) or zero(s) in the array imported from your text file
But this is what I am getting if I run my code above:
-------------------------------------UPDATE--------------------------------------
Figured it out based on #ZedLepplin 's comment
Here is the code:
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
cout << *(*(ArrB + i) + j) << " ";
}
}
if (invalidnum == true) {
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
You could just set a counter, and put the message outside of the loop.
Something like :
int counter = 0;
for(int i = 0; i < MAX_ROWS ; i++) {
if(myVector[i] == -1) {
counter++;
}
else {
// Do normal stuff
}
}
if(counter > 0) {
cout << "The array contained " << counter << "negative values" << endl;
}
Ho, and I'd advise to avoid comparisons to "true". If myVar is a boolean alrady, I can just do if(myVar). No need to do if(myVar == true).
And doing if(myVar = true) is worse, as it sets myVar to true, regardless of its initial value. That's a common typo that can be hard to detect when proofreading code.
Edited version (to adapt to comments) :
bool earlyNegativeOneFound = false;
int otherNegativeCounter;
for(int i = 0; i < MAX_ROWS ; i++) {
if(i < 6 && myVector[i] == -1) {
earlyNegativeOneFound = true;
break;
}
else if(myVector[i] < 0) {
cout << myVector[i] << endl;
otherNegativeCounter++;
}
else {
// Do normal stuff
}
}
if(!earlyNegativeOneFound && otherNegativeCounter> 0) {
cout << "The array contained " << otherNegativeCounter << "negative values" << endl;
}
Put the conditional error message print after your for loop. Leave the cout for displaying the array number inside the for loop so it is output for every iteration of the loop.
for (int i = 0; i<MAX_ROWS;i++) {
for (int j = 0; j<MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
cout << * (*(ArrB + i) + j) << " ";
}
}
if (invalidnum = true) {
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
I am not sure if this is what you meant
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
flag log = false;
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
if (invalidnum = true) {
cout << *(*(ArrB + i) + j) << " ";
if(!flag)
{
cout << "There is/are negative number(s) or zero(s) in the array
imported from your text file." << endl;
flag = true;
}
}
}
}
Adding the flag boolean variable would allow the statement "there are negative numbers.." to be printed once.
Just store the message and print it where and when you want. Some psuedo-code:
std::string message;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j< M; ++j)
{
if (smth)
{
message {"Your message"};
break; // note that after break,
// you are still in the outer loop
}
else if (smth else)
{
message {"Your message"};
}
}
// print it here
}
// or here, or wherever you want to
the function DataDisplayAndSearch for some reason causes a segmentation fault when i enter "x" to exit the program. I have tried debugging and cannot figure out what the problem could be. This is homework
string DataDisplayAndSearch (int customerCount, string ssn[])
{
//local variables
int index;
int count;
int numberLen;
int numberLocation = NOT_FOUND;
int high;
int low;
int middle;
bool invalidNumber = false;
string choice;
cout << " Social Security Numbers on file are:" << endl;
for (index = 0; index < customerCount; index++)
{
cout << " " << ssn[index] << " ";
}
do
{
cout << endl << endl << " Enter SSN to find (or X to exit):";
invalidNumber = false;
cin >> choice;
if (choice != EXIT && choice != EXIT1)
{
numberLen = choice.length();
if (numberLen < LENGTH || numberLen > LENGTH)
{
invalidNumber = true;
}
for (count = 0; count < LENGTH; count++)
{
if (isprint(choice[count]));
else
{
invalidNumber = true;
}
}
if (choice[IDX2] != DASH || choice[IDX5] != DASH)
{
invalidNumber = true;
}
low = 0;
high = customerCount - 1;
while ((low <= high) && (numberLocation == NOT_FOUND))
{
middle = (low + high) / 2;
if (choice > ssn[middle])
{
high = middle - 1;
}
else if (choice < ssn[middle])
{
low = middle + 1;
}
else
{
numberLocation = middle;
}
}
if (numberLocation == NOT_FOUND)
{
cout << " Error!! Please enter a valid SSN." << endl;
}
if (invalidNumber)
{
cout << " Input dashes and digits " << choice << " are formatted."
<< " SSN must be exactly 11 characters long, formatted as:"
<< " ###-##-###" << endl;
}
} //end of if
} while (((invalidNumber) && (choice != EXIT && choice != EXIT1 ) && (numberLocation == NOT_FOUND)));
}
When the outer loop exits for any reason, including choice == EXIT, the function exits without providing a return value of type string. The caller then attempts to use a non-existent string object, hence the crash.
Crossing the closing brace of a function with a non-void return type is undefined behavior. It may crash, but might not crash every time. Your compiler might warn you about things like this if you can enable its warning feature, such as by -Wall on the command line.
I'm building a battleships game and I need some advices how to deal with this problem.
Okey so the problem is that the game ends when both players has shoot down all the ships, this is controlled by a while loop and i want it to break as fast as one player has shot down the opponent.
The problem is at the function void ShootAtShip(int board1[], int board2[], string names[], int cap) and the while loop says while ((board1[i] != 0 || board2[i] != 0)) what I think is the problem is that the while loop has to run all the way from top to bottom before it ends, I want it to break in the middle IF board1 gets all 0's.
bool isGameOver(int board1[], int board2[], int cap)
{
bool lost1 = true;
bool lost2 = true;
for (int i = 0; i < cap && lost1 != false; ++i)
if (board1[i] != 0)
lost1 = false;
if (lost1)
return true;
for (int i = 0; i < cap && lost2 != false; ++i)
if (board2[i] != 0)
lost2 = false;
return lost2;
}
void ShootAtShip(int board1[], int board2[], string names[], int cap) {
const int hit = 0;
int shot = 0;
int temp;
isGameOver(board1, board2, cap);
for (int i = 0; i < cap; i++) {
while ((board1[i] != 0 || board2[i] != 0)) { //detects if any board has all their ships shot down
cout << names[1] << " set a position to shoot." << endl;
cin >> shot;
temp = shot;
while ((shot >= cap) || (shot < 0)) { //detects if the number is allowed
cout << "That number is not allowed, " << names[1] << " set a position to shoot." << endl;
cin >> shot;
}
if (board1[shot] != 0) {
board1[shot] = 0;
cout << "Hit!" << endl;
}
else {
cout << "You missed." << endl;
}
shot = 0;
cout << names[0] << " set a position to shoot." << endl;
cin >> shot;
while ((shot >= cap) || (shot < 0)) { //detects if the number is allowed
cout << "That number is not allowed, " << names[0] << " set a position to shoot." << endl;
cin >> shot;
}
if (board2[shot] != 0) {
board2[shot] = 0;
cout << "Hit!" << endl;
}
else {
cout << "You missed." << endl;
}
}
}
cout << "Testing is while loop stops";
}
So the reason the loop does not break is because you are using the wrong logic operator in your condition.
while ((board1[i] != 0 || board2[i] != 0))
should be
while (board1[i] && board2[i])
I believe you're thinking "if board 1 is empty or board 2 is empty, then break", but what you typed out is "if board 1 has anything left, or board 2 has anything left, keep going".
Also, do note that if (n != 0) is potentially more efficient (and just the same) as if (n).
The full code I am using is listed below, it is supposed to simulate a game of craps and print details to the user and allow for betting if the user desires it. Everything functions except for the actual craps game. Instead of looping only while there is not a truth value associated to crapsResult, it finds one real value and an incomprehensible string of a single negative number. Any help would be appreciated.
int main()
{
//Declare the user input variables
int gamesPlayed = 0;
char inputPrint = ' ';
char isBetting = ' ';
int startingBet = 0;
//Declare the variables used by the program
int endingBet = 0;
int currentGame = 0;
bool crapsResult;
int gamesWon = 0;
int gamesLost = 0;
double percentWon = 0;
bool detailPrint = false;
//Prompt the user to input their variables
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
while(gamesPlayed < 1)
{
cout << " Error: must be greater than 0" << endl;
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
cin.clear();
cin.ignore();
}
cout << "Do you wish to print details (Y/N): ";
cin >> inputPrint;
if(inputPrint == 'y' || inputPrint == 'Y')
{
detailPrint = true;
}
cout << "Do you wish to bet (Y/N): ";
cin >> isBetting;
if(isBetting == 'y' || isBetting == 'Y')
{
cout << "Enter money to start betting with: ";
cin >> startingBet;
while(startingBet < 1)
{
cout << " Error: must be greater than 0" << endl;
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
cin.clear();
cin.ignore();
}
}
//Seed the random number generator
srand(time(NULL));
//Set a value for ending bet
if(startingBet == 0)
{
endingBet = 1;
}
else
{
endingBet = startingBet;
}
//Call playcraps to simulate the game for as many games as the user input
for(currentGame = 1; currentGame <= gamesPlayed && endingBet > 0; currentGame += 1)
{
crapsResult = NULL;
crapsResult = playCraps(currentGame, detailPrint, isBetting, startingBet);
if(crapsResult == true)
{
gamesWon += 1;
endingBet = betting(endingBet, crapsResult);
}
if(crapsResult == false)
{
gamesLost += 1;
endingBet = betting(endingBet, crapsResult);
}
if((isBetting == 'Y' || isBetting == 'y') && (detailPrint == true))
{
cout << "Money left is $" << endingBet << endl;
}
}
//Calculate the percentage of games won
percentWon = (double(gamesWon) / double(currentGame-1)) * 100.0;
//Print the results to the user
if(isBetting == 'Y' || isBetting == 'y')
{
cout << "Money at end of games is $" << endingBet << endl;
}
cout << "The number of games played is " << currentGame - 1 << endl;
cout << "The number of games won is " << gamesWon << endl;
cout << "The number of games lost is " << gamesLost << endl;
cout << "The percent of games won is " << fixed << showpoint << setprecision(3) << percentWon << endl;
}
//Simulates the roll of a single die and returns the result
int roll()
{
int rollResult = 0;
rollResult = rand() % 6 + 1;
return rollResult;
}
//Calls roll twice and returns the sum of the two results
int roll2Dice()
{
//Declare variables for this function
int rollOne = 0;
int rollTwo = 0;
int rollSum = 0;
//Find rollOne and rollTwo
rollOne = roll();
rollTwo = roll();
//Find rollSum
rollSum = rollOne + rollTwo;
return rollSum;
}
bool playCraps(int currentGame, bool detailPrint, char isBetting, int startingBet)
{
bool crapsResult = NULL;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false;
}
else
{
crapsResult = NULL;
}
while(crapsResult != true && crapsResult != false)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false;
}
currentRoll += 1;
}
if(detailPrint == true)
{
cout << "Game " << currentGame << ": ";
for(printingNumber = 0; printingNumber <= currentRoll; printingNumber += 1)
{
cout << currentGameStorage[printingNumber] << " ";
}
if(crapsResult == true)
{
cout << "win";
}
else if(crapsResult == false)
{
cout << "lose";
}
cout << endl;
}
return crapsResult;
}
int betting(int endingBet, bool crapsResult)
{
if(crapsResult == true)
{
endingBet += 1;
}
else if(crapsResult == false)
{
endingBet -= 1;
}
return endingBet;
}
Just skimmed and didn't read all of your code (so there may be other things wrong too), but this line is definitely problematic:
while(crapsResult != true && crapsResult != false)
It is logically impossible for crapsResult to simultaneously be both true and false, so that loop will never be entered.
Turix got the right bug I believe, but I would put the emphasis on a different spot:
bool crapsResult = NULL;
You are trying to use crapsResult for three different values (true, false and NULL). However, NULL usually has a integer value of 0, which translates to a boolean value of false, so your loop will never be entered.
Then a second bug comes into play: currentRoll is 1 at this time, so you try to print the contents of currentGameStorage from index 0 to 1 (inclusive), currentGameStorage[1] hasn't been assigned yet. This is why you get the cryptic numer in your output. This is a general mistake: Your code always tries to print one item too much. Use < instead of <= in the loop head to fix that:
for(printingNumber = 0; printingNumber < currentRoll; printingNumber += 1)