What is causing zsh:segmentation fault in this case? - c++

this is my first every time posting a question on stackoverflow so I apologize beforehand If my question seems messy. I have a class named token, and a derived class from it called function, integer, and operator. Token has a public variable of type int called _type. I assigned different _type values for each derived classes. The type for integer is 1, 2 for operator, and 3 for function. The purpose of this is so that I can implement different operations depending on the type encountered. I made an rpn function and in it I have something like this.
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
}
return rpn_stack.top()->value();
}
after testing it a couple of times, I found out that the zsh:segmentation fault problem is caused by the input_q.pop() in
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
However, the code works if I change the order of the if statements like this
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
}
return rpn_stack.top()->value();
}
which leads me to question whether the problem was input_q.pop() in the first place. It also works if I were to assign input_q.front()->_type to a static variable inside the while loop like this
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
int type = input_q.front()->_type;
if(type == 1){
rpn_stack.push(input_q.pop());
}
if(type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
if(type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
}
return rpn_stack.top()->value();
}
At this point I am very confused as to what is causing zsh:segmentation fault when using the first version. Im wondering if the problem lies in accessing input_q.front()->_type? I could just use the second and third version but I really want to know what is causing zsh:segmentation fault on the first version. If it helps, here is the simple program I wrote to test it. I am also using stack and queue if it helps.
Queue<Token *> postfix;
postfix.push(new Integer(3));
postfix.push(new Integer(5));
postfix.push(new Operator("*"));
RPN rpn(postfix);
cout << "3 5 *: " << rpn() << endl;
cout << "-------------" << endl;
Queue<Token *> postfix2;
postfix2.push(new Integer(3));
postfix2.push(new Function("X"));
postfix2.push(new Operator("*"));
rpn.set_input(postfix2);
cout << "3 x *: (x=3): " << rpn(3) << endl;
the rpn function is called using the () operator in the RPN class. the RPN class has a private variable called _val that is assigned a value to by the () operator. Hope the information Ive provided is enough. Thank you for your time, would appreciate the input!

With reference to your first code snippet, when you say this:
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
...
You don't check if there's anything left on the input queue the second time you call input_q.front.
A simple fix is to insert a continue statement, like this:
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
continue;
}
...
You will then loop back to the while statement which checks whether the queue is empty before proceeding.
There are other places in the code where you need to make a similar change, but you get the idea.

Related

Can't figure out how to loop playerturns and moves Tic Tac Toe (C++) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
EDIT: Solved now thank you triple_r and AJNeufield for your help on this problem I was having.
I've looked around multiple websites and YouTube about this and I can't seem to find anything on what I am specifically looking for this as my format for the program is a good bit different than others. Therefore, it's hard to decipher where I need to put the things I do need that I know of.
Please note that I'm relatively new to C++ so I'd appreciate all the feedback or criticism you might provide me.
Also, note my code does compile and run it just does not allow me to put in more than one input and more than likely does not allow for a switch of player turns.
Quick Edit: Switched the code with the new setup suggested by triple_r but I seemed to have messed it up somewhere along the line and it does compile(with the exception of x and y not being utilized and one other error) but it always starts off with player 2 going first and as soon as it receives input it ends automatically with a segmentation fault.
#include <iostream>
#include <cstdlib>
using namespace std;
//////////////////////////////////////////////////////////
void initboard(char board[3][3])
{
int x,y;
for (x=0;x<3;x++)
for (y=0;y<3;y++)
board[x][y]=' ';
return;
}
//////////////////////////////////////////////////////////
void printboard(char board[3][3])
{
int x,y;
for (x=0;x<3;x++)
{
cout<<"\n";
for (y=0;y<3;y++)
{
cout<<" "<<board[x][y]<<" ";
if (y<2) cout<<"|";
}
if (x<2) cout<<"\n===========";
}
return;
}
//////////////////////////////////////////////////////////
void getmove(char board[3][3], int player)
{
return;
}
//////////////////////////////////////////////////////////
int main()
{
bool done=false;
char board[3][3];
int x,y,player=1,turn,playerchoice,playermark;
initboard(board);
turn=0;
do
{
if (player==1)
playermark='X';
else
playermark='O';
if (turn%2)
player=1;
else
player=2;
cout<<"Player "<<player<<" where do you want to move?: ";
cin>>playerchoice;
if (playerchoice==1)
{
board[0][0]=playermark;
}
else if (playerchoice==2)
{
board[0][1]=playermark;
}
else if (playerchoice==3)
{
board[0][2]=playermark;
}
else if (playerchoice==4)
{
board[1][0]=playermark;
}
else if (playerchoice==5)
{
board[1][1]=playermark;
}
else if (playerchoice==6)
{
board[1][2]=playermark;
}
else if (playerchoice==7)
{
board[2][0]=playermark;
}
else if (playerchoice==8)
{
board[2][1]=playermark;
}
else if (playerchoice==9)
{
board[2][2]=playermark;
}
else
{
cout<<"Invalid move ";
}
if (board[x][y]!=' ')
cout<<"Move is already taken.";
board[x][y]=playermark;
if(board[x][y]==' ')
turn++;
}while (!done);
void printboard(char board[3][3]);
return 0;
}
EDIT: based on the updated code
So, the first thing I can see is that you are using x and y in your program but you don't initialize them or assign any values to them. Also, try to use functions/classes/... yo make your code more readable. You already have a function for player move but you are not using it. You can move the large if statement inside that function and that will make your main code shorter and more readable.
Here are my comments on the main part of your program:
int main()
{
// add a new variable to see if the move was valid or not:
bool done=false, validmove = true;
char board[3][3];
int x, y, player = 1, turn = 0, playerchoice, playermark;
initboard(board);
do
{
// swap the two `if`s so you decide who`s turn it is then assign the player mark,
// also, reverse the condition to make sure turn '0' is player 1's turn.
if (!(turn % 2))
player = 1;
else
player = 2;
if (player == 1)
playermark = 'X';
else
playermark = 'O';
cout << "Player " << player << " where do you want to move?: ";
cin >> playerchoice;
// Assign `x` and `y` here instead of updating the board, because you want to make
// sure that the move is valid before putting the mark:
validmove = true;
if (playerchoice == 1)
{
x = 0; y = 0;
}
else if (playerchoice == 2)
{
x = 0; y = 1;
}
else if (playerchoice == 3)
{
x = 0; y = 2;
}
else if (playerchoice == 4)
{
x = 1; y = 0;
}
else if (playerchoice == 5)
{
x = 1; y = 1;
}
else if (playerchoice == 6)
{
x = 1; y = 2;
}
else if (playerchoice == 7)
{
x = 2; y = 0;
}
else if (playerchoice == 8)
{
x = 2; y = 1;
}
else if (playerchoice == 9)
{
x = 2; y = 2;
}
else
{
cout << "Invalid move, try again!";
// Make sure to mark the move as invalid so they get a chance to
// change their move:
validmove = false;
}
// check to see if the turn was valid:
if(validmove)
{
if (board[x][y] != ' ')
{
cout << "Move is already taken, try again";
}
else
{
board[x][y] = playermark;
turn++;
}
}
// have to make sure you have a condition for end of game. A simple
// one is to check if turn is less than `9`, otherwise the board is
// full:
if(turn == 9)
done = true;
// you probably want to add a few more checks to see who won the game.
}while (!done);
// when calling a function, no need to put the return type or parameter type:
printboard(board);
return 0;
}
========================================================================
There are two do-while loops in your program and both seem to be meant as a game loop. What I would do is:
initboard(...);
turn = 0;
do{
//this is the game loop
...;
if( validturn )
turn++;
}while(!done);
release_resources(...);
return 0;
so, you fold everything into one loop. In that loop, you want to:
find who's turn it is:
if (turn % 2)
player = 1;
else
player = 2;
get users input:
std::cin >> playerchoice;
...
convert player choice to grid location:
switch ( move )
{
case 0:
x = 0;
y = 0;
break;
case 1:
...;
...
default:
//invalid move
}
see if the move is valid:
if( board[x][y] != ' ' )
//already taken, invalid move
then apply the move:
board[x][y] = playermark;
I hope this helps.
Your cin >> playerchoice is outside your do { ... } while ( moves != 9); loop. Move it inside.

How to access a function of an object that was returned as a pointer by another function.

It's the guy who was making the boggle simulator again! This time I have the issue of having a function that was forced to return a pointer to an object for syntax reasons. I want to access a function of the object that said pointer points to. How should I go about this? My code for the functions involved is below.
boggleNode * nextNode(int adj){
return adjacency[adj]; //For switching between nodes.
}
bool getUsed(){
return isUsed;
}
private:
boggleNode * adjacency[8];
char letter;
bool isUsed;
};
And finally, here is the function that contains the functions above:
int sift(boggleNode bog, string word, string matcher){
int endofnodes;
string matchee;
if (bog.getData() == 'q')
matchee = matcher + bog.getData() + 'u';
else
matchee = matcher + bog.getData();
if (compare(word, matcher) == 0){
cout << word << endl;
return 5; //If it finds the word, escape the loop.
}
if (word.find(matcher) == 0){
bog.makeUsed();
for (int j = 0; j < 8; j++){
if (bog.nextNode(j) != NULL){
if ((bog.nextNode(j)).getUsed() == 0){
endofnodes = sift(bog.nextNode(j), word, matchee);
if (endofnodes == 5)
return endofnodes;
}
}
bog.reset();
return 0;
//If it doesn't find anything, move onto next adjacency.
/*any words share a common starting letter sequence with matcher*/
//Sift using an adjacent node, and add the old string to the new one.
}
}
}
In which I am specifically asking about this line:
if ((bog.nextNode(j)).getUsed() == 0)
When I attempt to compile this code, I get " error: request for member
getUsed' in(&bog)->boggleNode::nextNode(j)', which is of non-class
type `boggleNode*' "
Any help is greatly appreciated. Thanks in advance!
You should use -> instead of .:
if ((bog.nextNode(j))->getUsed() == 0)
which is shorthand, in this case, for:
if ((*(bog.nextNode(j))).getUsed() == 0)

C++ returning bool is always false?

I implemented a Quiz Code and did a short change at the end of it to check if the User answered it correctly.
My if / else looks like this:
if (answer == rightanswer){
rightA = true;
}
else {
rightA = false;
}
return rightA;
I already checked with the debugger that if the correct answer is entered it goes to rightA = true; and to return, so this works finde.
But if i check the value of rightA it's false.
If it's needed, here is the function that i use to call the Quiz:
void gameOver(char field[HEIGHT][WIDTH], char newField[HEIGHT][WIDTH]){ // TODO
bool rightA = false;
showQuizDialog(rightA);
do{
system("cmd /c cls");
switch (rightA){
case true : cout << "menu"; menu(field, newField); break;
case false : showQuizDialog(rightA); break;
default : cout << " ";
}
}while(rightA == false);
}
I'm a bit hintless. I may have some logic failure in it i just don't see at the moment.
Greetings
E: I don't wanted to bomb you guys with code. But here is it:
bool showQuizDialog(bool rightA){
Quiz* quiz = Quiz::getInstance();
quiz -> askQuestion(rightA);
return rightA;
}
And the full askQuestion:
bool Quiz::askQuestion(bool rightA) {
int fragenID = rand() % this->fragen.size(); //zufällige Fragen auswählen
struct Question frage = this->fragen.at(fragenID);
std::cout << frage.frage.c_str() << std::endl << endl; //Frage stellen
int rightanswer = this->listAnswers(frage.antworten);
int answer = this->readAnswer(0, frage.antworten.size() - 1);
if (answer == rightanswer){
rightA = true;
}
else {
rightA = false;
}
return rightA;
}
Is showQuizDialog(rightA) supposed to magically change the value of rightA? (I'm assuming you're not passing it by reference).
Did you mean to write rightA = showQuizDialog(rightA) or rightA = quiz -> askQuestion(rightA)?
Also, in your switch that switches on a bool, do you expect any other values than a true or a false?
Your showQuizDIalog is a call-by-value function. So always store the return value of the function into rightA, when calling showQuizDialog, that is :
rightA = showQuizDialog(rightA);
Otherwise, change your function declaration to allow pass-by-reference, maybe like this
showQuizDialog(&rightA);
and no need to return anything from the function(just use a pointer instead of a variable rightA inside the function)

Nested for loop being ignored after if-else chain

I am programming a MARIE assembler for one of my classes and I've ran into a logical error involving my control structure for one of my functions.
What I'm trying to accomplish is taking in all the data that was inserted into my vectors and then that data is being used to create integer opcode data for display. Yet for whatever reason my nested for loop is being ignored after my if-else chain.
The code within the nested for-loop seems to be working properly aside from this one logic error.
Please note that instructions, hexNums, secondPassData, valueZ, and symBols are my vectors.
For some clarification:
The If-Else chain is just used to read instruction words and to set basedInt to the proper decimal number for later hexadecimal conversion.
There are a few special conditions in the code below which are marked.
If there is no special condition then the code checks the valueZ vector at instructions.at(i) to see if the valueZ element is in symBols.
If it is a symBol element through character checks, it takes its hexNums position and adds it to the basedInt.
If it is not, it instead has its corresponding valueZ element converted from string to int and then added to the basedInt.
Those elements are added to the secondPassData vector.
int basedInt;
int newInt;
int pushInt;
string temp;
for(unsigned int i = 0; i < instructions.size(); ++i) //if i is less then instructions.size(), follow through with the statement
{
if(instructions.at(i) == "JNS") //sets basedInt to a decimal version of its hexidecimal opcode
{
basedInt = 0;
}
else if(instructions.at(i) == "HALT") //a special condition where the number is plugged into the secondPassData vector automatically
{
secondPassData.push_back(28672);
continue;
}
else if(instructions.at(i) == "CLEAR") //same as above
{
secondPassData.push_back(-24576);
continue;
}
else if(instructions.at(i) == "ADDL")
else if(instructions.at(i) == "ORG")
{
secondPassData.push_back(0000);
continue;
}
else if(instructions.at(i) == "HEX") //checks for the HEX psuedo-OP.
{
temp = valueZ.at(i); //converts it at position i to a string
basedInt = atoi(temp.c_str()); //converts that string to an int.
secondPassData.push_back(basedInt);//pushes into vector.
continue;
}
else if(instructions.at(i) == "DEC")
{
temp = valueZ.at(i);
basedInt = atoi(temp.c_str()); //similar function as above.
secondPassData.push_back(basedInt);
continue;
}
else
{
cout << "Beep Boop, program borked!" << endl;
return;
}
//for some reason the code below is getting ignored.
cout << i << endl;
for(unsigned int a = 0; a < instructions.size(); ++a) //works
{
cout << i << " " << a << endl;
string valFind = valueZ.at(i);
string symFind = symBols.at(a); //works
temp = valueZ.at(i);
if(symFind[0] == valFind[0])
{
newInt = hexNums.at(a);
pushInt = basedInt + newInt;
secondPassData.push_back(pushInt);
break;
}
else if(symFind[0] != valFind[0]) //works
{
temp = valueZ.at(i);
newInt = atoi(temp.c_str()); //works
pushInt= basedInt + newInt;
secondPassData.push_back(pushInt); //works
break;
}
break;
}
}
If you hit a continue in your else-if chain your main for loop will jump to its next iteration and will skip the rest of your code (in this case your nested for loop)
continue

C++ Member Function Clearing Matrix

I have had a similar issue with quite a few projects I have worked on involving classes containing arrays. I have a class that is supposed to handle a 2 dimensional matrix representing a TicTacToe game. There is an enumeration in the class for the status of the current game and one member function that has an enumeration return type. I cant seem to figure out why I can create the class set values in the matrix and as soon as I call the member function with the enumerated return type the whole array is reinitialized to 0. I think it has something to do with the constructor being called again or something along those lines but I have not been able to find anything after searching for the past few hours. Any help would be greatly appreciated.
Here is my header file containing the class information:
#ifndef TTT_H
#define TTT_H
#include <cstdlib>
#include <iostream>
using namespace std;
class TicTacToe
{
private:
enum Status{WinX, WinO, Continue, Draw};
int **board;
public:
TicTacToe();
~TicTacToe();
void PrintBoard();
bool ValidMove(int, int);
bool PlayerMove(int, int, int);
Status GameStatus(); //this one causes the problem
void Debug();
};
#endif
Here is the code for CPP file with the member function definitions:
#include "TicTacToe.h"
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <cassert>
using namespace std;
TicTacToe::TicTacToe()
{
board = new int*[3];
assert(board != 0);
for(int i=0;i<3;i++)
{
cout << "Constructor Ran again" << endl; //for testing
board[i] = new int[3];
assert(board[i] != 0);
for(int j=0;j<3;j++)
board[i][j] = 9;
}
}
TicTacToe::TicTacToe(TicTacToe &copy)
{
board = new int*[3];
assert(board != 0);
}
TicTacToe::~TicTacToe()
{
if(board)
delete[] board;
}
void TicTacToe::PrintBoard()
{
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
cout << "| ";
switch(board[i][j]){
case 0:
cout << "O ";
break;
case 1:
cout << "X ";
break;
case 9:
cout << " ";
break;
}
}
cout << "|" << endl;
cout << "------------" << endl;
}
}
bool TicTacToe::ValidMove(int row, int col)
{
bool valid = false;
if(row < 3 && col < 3)
{
if(board[row][col] == 9)
valid = true;
}
return valid;
}
bool TicTacToe::PlayerMove(int player, int row, int col)
{
bool done = false;
if(ValidMove(row,col) == true)
{
if(player == 1)
board[row][col] = 1;
else
board[row][col] = 0;
done = true;
}
return done;
}
TicTacToe::Status TicTacToe::GameStatus() //This function is the problem
{
int check, empty = 0;
bool done = false;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
check += board[i][j];
if(board[i][j] = 9)
empty++;
}
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
}
if(empty == 0)
return Draw;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
check += board[j][i];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
}
check = board[0][0] + board[1][1] + board[2][2];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
check = board[0][2] + board[1][1] + board[2][0];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
return Continue;
}
void TicTacToe::Debug()
{
//cout << &board[0][0] << endl;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
cout << board[i][j];
cout << endl;
}
}
Here is the driver file I am using to test:
#include "TicTacToe.h"
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
int row, col;
bool valid;
enum Status{WinX, WinO, Continue, Draw};
TicTacToe * T;
T = new TicTacToe;
assert(T != 0);
cout << "There are 2 players. P1 is x P2 is o" << endl;
do
{
T->PrintBoard();
valid = false;
while(valid == false)
{
cout << "\nP1 choose a cell" ;
cin >> row >> col;
if(T->ValidMove(row, col) == true)
{
T->PlayerMove(1, row, col);
valid = true;
}
else
{
cout << "Not a valid choice" << endl;
valid = false;
}
}
T->PrintBoard();
cout << endl;
T->GameStatus(); //<<<<<this is the pain in my butt
T->PrintBoard();
valid = false;
while(valid == false)
{
cout << "\nP2 choose a cell" ;
cin >> row >> col;
if(T->ValidMove(row, col) == true)
{
T->PlayerMove(2, row, col);
valid = true;
}
else
{
cout << "Not a valid choice" << endl;
valid = false;
}
}
}
while(/*T->GameStatus() == Continue*/ 1==1);
//the call to GameStatus was commented out of the
//while statement for testing
return 0;
}
I know the code inside of the GameStatus function is far from pretty but the array is messed up before any of those lines are processed.
I left all of the other functions just to show that they work properly without issue.
Thanks in advance for any help you may be able to give.
You've got a simple typo in your code..
if(board[i][j] = 9) // will always return true (refp)
empty++;
Other remarks
When looking at your code a bit more thoroughly I see that you have a few other miss-happens, intentional or unintentional.. that I don't know:
int check is not initialized in TicTacToe::GameStatus
You are not freeing the allocated memory properly, you'll
need to free all entries in board, ie. delete board[i])
I don't like bugs, how can I get rid of the operator= vs operator== problem?
A quite common method to circumvent the problem of making a typo and writing = when you mean to compare (==) two variables is to flip the operands around (if one of them is a constant value, such as 9.
if(9 = board[i][j]) will not compile and such a bug would've never appeared in your code.
I'll have to say that I don't like writing my statements that way.. though it's a quite common method, especially in the "beginner" segment.
check is not initialized in GameStatus() .
if (board[i][j] = 9)
Isn't the above line of code resetting the array contents? You probably want to use == here, instead.
You have a serious issue in memory management. Look:
Your constructor performs 4 allocations (an array of pointers and 3 arrays of ints, to emulate a 2D arrray),
Your destructor performs 1 deallocation (= memory leak),
You have a custom destructor but you don't define (or block) operator= (you need to, see What is The Rule of Three?)
Your copy constructor is incomplete and doesn't create a "valid" object.
Basically the above is likely to cause you some memory problems. I suggest to:
Rewrite the destructor to first free all the arrays of ints, then the array of pointers,
Make the class TicTacToe uncopiable by declaring the copy constructor and the operator= as private.
Also some minor details on that matter:
board = new int*[3];
assert(board != 0);
The assertion is unnecessary. If the allocation fails, the operator new will throw an exception.
if(board)
delete[] board;
Operators delete and delete[] don't do anything if their argument is a null pointer, so that condition is redundant. Also you have designed your object with the invariant that the board exists as long as the TicTacToe object exists, so that check is totally unnecessary, right?
Keep it safe and simple!