I cannot figure out why this while loop is endless [duplicate] - c++

This question already has answers here:
Can anyone tell me why these functions are not giving me a result in a reasonable spectrum?
(2 answers)
Closed 9 years ago.
Here is the code I am currently working with:
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;
}
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;
}
Whenever I run it it creates am emdless loop with no text appearing in the terminal. The function roll2Dice() simulates the roll of two six sided dice using the rand() function and adds the two results together. Any help would be appreciated.

Your while test, crapsResult != true || crapsResult != false is necessarily true, and therefore does not terminate. The crapsResult value is either true of false, which will make one of the two halves of the expression true, and one false. Both true || false and false || true evaluate to true.

As others have noted it's pretty obvious why the loop never ends.
Your use of NULL makes me think you wish you could have a bool which could hold three values (unset, true and false). You could achieve this with minimal changes by using a pointer to bool, but that's pretty disgusting. Enums are what you really need:
enum CrapsResult
{
unrolled,
true_result,
false_result
};
The pertinent code then becomes*:
CrapsResult crapsResult = unrolled;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true_result;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false_result;
}
else
{
crapsResult = unrolled;
}
while(crapsResult == unrolled)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true_result;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false_result;
}
currentRoll += 1;
}
*I haven't actually compiled this.

while(crapsResult != true || crapsResult != false)
equals to
while(crapsResult == false || crapsResult == true)
.
//while(crapsResult == (false || true)) // DonĀ“t matter
so as boolean has only false or true
it will always evaluate true and equals to this expression
while(true)

In C and C++, expressions can resolve to true or false based on the following: 0 is false, everything else is true. The formal definition of C's macros FALSE and TRUE is #define FALSE 0 and #define TRUE (!(FALSE)).
A variable of type bool can either be true or false. You initialize your crapsResult with the value of NULL. NULL is a macro defined as 0UL or 0ULL, which evaluates to false.
bool crapsResult = NULL;
is equivalent to
bool crapsResult = false;
So when your code does the following:
while (crapsResult != true || crapsResult != false)
one of these conditions is always met, so the loop always repeats.
You will need a second variable, presumably of type bool, to determine if you have an acceptable answer.
bool crapsResult = false;
bool haveCrapsResult = false;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true;
haveCrapsResult = true;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false;
haveCrapsResult = false;
}
while(!haveCrapsResult)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true;
haveCrapsResult = true;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false;
haveCrapsResult = true;
}
currentRoll += 1;
}
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) is redundant */
{
cout << "lose";
}
cout << endl;
}
return crapsResult;

Related

Trying to find all prime numbers in a list

the output
The program is checking every number in the list and should output if is prime or not. Probably I just don't get the prime algorithm right.
Currently outputs that no number is prime.
void primList(struct node* stnode)
{
struct node* pr = stnode;
int i;
bool primNum = true;
if (stnode != NULL)
{
while (pr != NULL)
{
if ((pr->num) == 0 || (pr->num) == 1)
primNum = false;
else
{
for (i = 2; i <= ((pr->num) / 2); ++i) //The mistake
if (((pr->num) % i) == 0) //is here?
{
primNum = false;
break;
}
}
if (primNum)
cout << "\n" << pr->num << " is a prime number.";
else
cout << "\n" << pr->num << " is not a prime number.";
pr = pr->nextptr;
bool primNum = true;
}
}
}
In general such questions (seeking debugging help) are discouraged, see on-topic.
In this case the minimal change to fix this code would be:
void primList(struct node* stnode)
{
struct node* pr = stnode;
int i;
bool primNum = true;
if (stnode != NULL)
{
while (pr != NULL)
{
if ((pr->num) == 0 || (pr->num) == 1)
primNum = false;
else
{
for (i = 2; i <= ((pr->num) / 2); ++i) //The mistake
if (((pr->num) % i) == 0) //is here?
{
primNum = false;
break;
}
}
if (primNum)
cout << "\n" << pr->num << " is a prime number.";
else
cout << "\n" << pr->num << " is not a prime number.";
pr = pr->nextptr;
primNum = true; // <-- notice I erased bool here
}
}
}
The problem here is that the primNum variable is not really changed in line bool primNum = true, but a new variable with the same name is created (and then immediately destroyed).
There are many other ways on how your code could be improved. See for example The Definitive C++ Book Guide and List as it has a lot of great sources.

C++ How to make a variable true if another variable WAS true

I was wonder how could I make a bool true if another bool was true for example with this program :
for(int i=1;i<5;i++){
if (i == 3){
x = false;
} else{
x = true;
}
if(x){
cout << "true";
}else{
cout << "false";
}
}
output :
true
true
false
true
true
how would I make it so that the output is this:
output:
true
true
false
false
false
sorry if this is hard to understand I'm not the best at explaining
int flag = 0;
for(int i=1;i<5;i++){
if (i == 3){
x = false;
flag = 1;
} else{
x = true;
}
if(x && flag == 0){
cout << "true";
}else{
cout << "false";
}
}
If you specifically wish to switch your output upon getting 3, you can flag up the case where there is a change in x. See the code above. This is in accordance to your code pattern.
Try this code
x = true;
for(int i=1;i<5;i++){
if (i == 3){
x = false;
}
if(x){
cout << "true";
}else{
cout << "false";
}
}

How do you find the shortest path after the BFS algorithm?

while( !q.is_empty() )
{
loc = q.remove_from_front();
//cout << loc.row << " " << loc.col << endl;
if( (loc.row-1) >= 0) //north
{
loc2.row = loc.row-1;
loc2.col = loc.col;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.col-1 >= 0) //West
{
loc2.row = loc.row;
loc2.col = loc.col-1;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.row+1 < rows) //South
{
loc2.row = loc.row+1;
loc2.col = loc.col;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
// loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.col+1 < cols) //East
{
loc2.row = loc.row;
loc2.col = loc.col+1;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc.row][loc.col] = '*';
break;
}
}
}
}
if(result == 1)
{
while()
{
//not sure...
}
}
This is my BFS algorithm and the main reason I asked this question is because the other questions similar to my own question tends to be done with vectors. I haven't learn vectors yet. What I am trying to do is to print the shortest path using '' characters to display it on valid elements. It should be in bounds, no walls visited (walls are '#' characters), and no element should be visited twice. I know that if I set my predecessor 2D array correctly, the shortest path should be displayed correctly. However, I am not sure if I did set it up correctly and how to actually fill in that path with '' characters...

Can't get boolean to return false C++

I am making a program for my C++ course to validate the date using different functions but mostly boolean. My problem is that it won't give false when it is. I have tried it using the else command instead of leaving the return false; without the else but it didn't seem to change anything. Here is the code though:
int main()
{
char Data[80];
int Month,Day,Year;
int *pMonth,*pDay,*pYear;
pMonth = &Month;
pDay = &Day ;
pYear = &Year ;
cout << "\n\t\tGive me date : ";
cin >> Data;
trial();
PauseScreen(28,20,3);
return 0;
}
void SetCursorPosition(int X, int Y)
{
COORD XY = { Y,X };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),XY);
}
void SetTextColor(int Color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), Color);
}
void ClearScreen()
{
system("cls");
}
void PauseScreen(int x, int y, int color)
{
SetCursorPosition(x,y);
SetTextColor(color);
system("pause");
}
int InputValues(char *A, int *pM, int *pD, int *pY)
{
char Buffer[10];
Buffer[0] = A[0];
Buffer[1] = A[1];
Buffer[2] = '\0';
*pM = atoi(Buffer);
Buffer[0] = A[3];
Buffer[1] = A[4];
Buffer[2] = '\0';
*pD = atoi(Buffer);
Buffer[0] = A[6];
Buffer[1] = A[7];
Buffer[2] = A[8];
Buffer[3] = A[9];
Buffer[4] = '\0';
*pY = atoi(Buffer);
return strlen(A);
}
bool ValidateMonth(int A)
{
if ( A > 0 && A < 13 )
{
return true;
}
return false;
}
bool ValidateDay(int day,int month)
{
if ( month == 1 || month == 3 || month == 5 || month == 7 || month == 9|| month == 10|| month == 12 && (day > 0 && day < 32) )
{
return true;
}
return false;
}
bool ValidateDayTwo(int day,int month)
{
if ( month == 4 || month == 6 || month == 8 || month == 11 && (day > 0 && day < 31) )
{
return true;
}
return false;
}
void trial()
{
if(ValidateDay && ValidateDayTwo && ValidateMonth)
{
SetCursorPosition(10,10);
cout << "Date is Valid";
}
else
{
SetCursorPosition(10,10);
cout << "You done messed up BALAKI";
}
}
You're not actually calling your functions in your if statement. ValidDay, ValidDayTwo, ValidMonth
if(ValidateDay && ValidateDayTwo && ValidateMonth)
Instead you'll need to invoke the function by passing in arguments
if(ValidateDay(somearg1) && ValidateDayTwo(somearg2) && ValidateMonth(somearg2))
bool ValidateMonth(int A)
{
if ( A > 0 && A < 13 )
{
return true;
}
return false;
}
There is no need to say "If the condition is true, return true; otherwise, return false". You can simply return the result of evaluating the condition:
bool ValidateMonth(int A)
{
return A > 0 && A < 13;
}
You didn't call the functions correctly (well, you actually didn't call them at all) - there are no arguments:
if(ValidateDay(?) && ValidateDayTwo(?) && ValidateMonth(?))
For example, your ValidateDayTwo function takes two parameters.
The fact that the functions' return types are bool doesn't change anything, this doesn't do what you think it does. The name of the function is a pointer to the function itself, and you didn't get false as expected, because that pointer is not NULL.

Fast way to determine if string is a JSON number

The check must not user C++11 features or additional libraries e.g. Boost, Regex etc. I came up with the following solution. No pretty but working. Does it get more elegant and/or faster from here?
bool isJsonNumber(const std::string& text)
{
if(text.empty()) return false;
bool foundE = false;
bool foundESign = false;
bool leadingZero = false;
bool lastIsDigit = false;
bool foundDot = false;
for(uint32_t i=0; i < text.length(); ++i)
{
const unsigned char c = text[i];
lastIsDigit = false;
const bool currIsNoDigit = (c < '0' || c > '9');
if(i == 0)
{
if(currIsNoDigit && c != '-' ) return false;
if(c == '0') leadingZero = true;
if(c != '-') lastIsDigit = true;
}
else
{
if(leadingZero)
{
leadingZero = false;
if(c != '.') return false;
foundDot = true;
}
else if(c == '.')
{
if(foundDot) return false;
foundDot = true;
}
else if(c == 'e' || c == 'E')
{
if(foundE) return false;
foundE = true;
}
else if(foundE && !foundESign)
{
if(currIsNoDigit && c != '-' && c != '+') return false;
if(c == '+' || c == '-')
{
foundESign = true;
}
else
{
lastIsDigit = true;
}
}
else
{
foundESign = false;
if(currIsNoDigit) return false;
lastIsDigit = true;
}
}
}
if(lastIsDigit == false) return false;
return true;
}
The use case is a small embedded server that recieves huge CSV files and anwsers clients with portions in JSON.
It would probably be easier to use std::stod:
size_t endpos;
std::stod(text, &endpos);
if (endpos != text.length())
{
// Not a number
}
else
{
// A number
}
If you don't have std::stod, as it's a C++11 feature, you could do something similar with std::strtod.
If you want to disallow INFINITY or NAN or hexadecimal floating point values, it's as easy as checking that the second or third character in the string is not a letter:
if ((text.length() > 2 && std::isalpha(text[1])) ||
(text.length() > 3 && std::isalpha(text[2])))
{
// Not a number
}
For "larger" numnbers there always std::stold or std::strtold. However if you want arbitrarily sized numbers then either do as you do now or use a library such as GMP (mpf_set_str seems like a good function for this).