Stack Program in C++ - c++

I want to implement a code in my program where it guesses whether or not the given series of operations and corresponding return values from an input file are operating as a stack. In other words, the output is fully determined by the input file.
The text file (StackTest.txt):
4
INSERT 2
INSERT 1
REMOVE 1
REMOVE 2
6
INSERT 5
INSERT 10
INSERT 12
REMOVE 10
REMOVE 5
REMOVE 12
2
INSERT 8
REMOVE 8
Expected Output(from input file):
stack
not stack
stack
However, I'm stuck on how to implement this feature into my current code.
If anyone can help me out on how to achieve the expected output above or give me some hints, I would really appreciate it!
Code in progress...
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
using namespace std;
// Function to check validity of stack sequence
bool validStackSeq(string input, int len)
{
// maintain count of popped elements
int j = 0;
// an empty stack
stack <int> s;
for(int i = 0; i < len; i++)
{
s.push(input[i]);
// check if appended value is next to be popped out
while (!s.empty() && j < len && s.top() == input[j])
{
s.pop();
j++;
}
}
return j == len;
}
int main()
{
ifstream inFile;
string data;
string command;
int num;
inFile.open("StackTest.txt");
//cout << "Reading file..." << endl;
stack <int> s;
while(getline(inFile, data))
{
if(command == "INSERT")
{
s.push(num);
}
else if(command == "REMOVE")
{
s.pop();
}
num = sizeof(data)/sizeof(data[0]);
cout << (validStackSeq(data, num) ? "Stack" : "Not Stack") << endl;
}
inFile.close();
}
Current Output
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack Validation Program (without input file)
#include <iostream>
#include <stack>
using namespace std;
bool validStackSeq(int pushed[], int popped[], int len)
{
int j = 0;
stack <int> pt;
for(int i = 0; i < len; i++)
{
pt.push(pushed[i]);
while (!pt.empty() && j < len && pt.top() == popped[j])
{
pt.pop();
j++;
}
}
return j == len;
}
// Driver code
int main()
{
int pushed[] = {2, 1};
int popped[] = {1, 2};
int len = sizeof(pushed)/sizeof(pushed[0]);
int pushed1[] = {5, 10, 12};
int popped1[] = {12, 5, 10};
int len1 = sizeof(pushed1)/sizeof(pushed1[0]);
int pushed2[] = {8};
int popped2[] = {8};
int len2 = sizeof(pushed2)/sizeof(pushed2[0]);
int pushed3[] = {1, 4};
int popped3[] = {4};
int len3 = sizeof(pushed3)/sizeof(pushed3[0]);
cout << (validStackSeq(pushed, popped, len) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed1, popped1, len1) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed2, popped2, len2) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed3, popped3, len3) ? "Stack" : "Not Stack") << endl;
return 0;
}

Perform the INSERT and REMOVE operations as specified in the text file. The result is 'stack' if all remove operations are possible (do not occur when the stack is empty) and the operand of each remove operation equals the actual value poped from your stack.
UPDATED 2020-02-29
You cannot create two separate arrays for INSERT and REMOVE operations and process them independently, because the result depends on how the operations are interleaved. For example
INSERT 1
INSERT 2
REMOVE 2
REMOVE 1
should result in stack, but if we move one REMOVE operation up:
INSERT 1
REMOVE 2
INSERT 2
REMOVE 1
the result will become not stack. It means that you need to process the operations in exactly same order as they appear in the file.
The general structure of the code:
ifstream inFile;
inFile.open("StackTest.txt");
int num;
while (inFile >> num) { // Read number of INSERT/REMOVE in each test set
stack<int> s;
bool isStack = true;
for (int i = 0; i < num; i++) {
// Read and process all INSERT/REMOVE operations in this test set
// Set isStack to false if not stack behavior detected
}
cout << (isStack ? "stack" : "not stack") << endl;
}
inFile.close();
As we read the operations from the input file we try to perform them. The INSERT operations should be performed as-is, no checks are required.
if (operation == "INSERT") {
s.push(argument);
}
The REMOVE operations require two checks to be performed: whether the stack is empty and whether the top of stack contains the same number as the argument of the REMOVE operation. If either of the checks fail then we set isStack to false.
if (operation == "REMOVE") {
if (s.empty() || s.top() != argument) {
isStack = false;
}
if (!s.empty()) {
s.pop ();
}
}
Combining this together we get:
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
using namespace std;
int main () {
ifstream inFile;
inFile.open("StackTest.txt");
int num;
while (inFile >> num) {
stack<int> s;
bool isStack = true;
for (int i = 0; i < num; i++) {
string operation;
int argument;
inFile >> operation >> argument;
if (!isStack)
continue;
if (operation == "INSERT") {
s.push(argument);
}
else if (operation == "REMOVE") {
if (s.empty() || s.top() != argument) {
isStack = false;
}
if (!s.empty()) {
s.pop ();
}
}
}
cout << (isStack ? "stack" : "not stack") << endl;
}
inFile.close();
}
There is just one more thing to mention: after we read the operation name and its argument from the file we do a check
if (!isStack)
continue;
This statement is not required, it's there just for a performance improvement. If we already detected that the given test set does not correspond to a stack then we don't need to perform all the remaining operations in this test set, we just skip them. You can safely remove this statement without influencing the result.

Related

Further optimization of finding max in a stack

My problem is to insert an element, pop the last inserted element and printed the max in the given. I am using 2 stacks for the purpose and it is optimized based on most suggested techniques available. But I still need further optimization for the case where number of queries, q <=100000 and test cases<=100. The following is my code as of now:
int main() {
int t,q;
cin>>t;
char query;
int detail;
for(int test=0;test<t;test++)
{
cout<<"Case "<<test+1<<":\n";
cin>>q;
stack<int> s;
stack<int> max;
for(int i=0;i<q;i++)
{
cin>>query;
if(query=='A')
{
cin>>detail;
s.push(detail);
if(max.empty())
max.push(detail);
else if(detail>=max.top())
max.push(detail);
}
else if(query=='R')
{
if(!s.empty())
{
if(s.top()==max.top())
max.pop();
s.pop();
}
}
else
{
if(max.empty())
cout<<"Empty\n";
else
cout<<max.top()<<"\n";
}
}
}
return 0;
}
I'm not sure what do you mean by 'optimize' (minimize memory usage in your cases, improve execution time or just referring to algorithm efficiency). Following comment from #alexeykuzmin0 , the code would look as follows:
std::stack<std::pair<int, int>> stack;
for (int i = 0; i<q; i++)
{
std::cin >> query;
if (query == 'A')
{
std::cin >> detail;
int max = stack.empty() ? detail : std::max(detail, stack.top().second);
stack.push(std::make_pair(detail, max));
}
else if (query == 'R')
{
if (!stack.empty())
{
stack.pop();
}
}
else
{
if (stack.empty())
std::cout << "Empty\n";
else
std::cout << stack.top().second << "\n";
}
}
Additionally it looks like you're not using the history of inserted items for anything, thus we can remove the pair and solve it using single stack.
std::stack<int> stack;
for (int i = 0; i<q; i++)
{
std::cin >> query;
if (query == 'A')
{
std::cin >> detail;
int max = stack.empty() ? detail : std::max(detail, stack.top());
stack.push(max);
}
else if (query == 'R')
{
if (!stack.empty())
{
stack.pop();
}
}
else
{
if (stack.empty())
std::cout << "Empty\n";
else
std::cout << stack.top() << "\n";
}
}
Also remember to measure performance (timings) in release mode builds, with optimizations on. (don't measure performance on debug builds)

C++: Deque Iterator Not Dereferenceable; can't find the rogue pop/top

I'm doing something very similar to what this user did:
Error: deque iterator not dereferenceable
I've been looking for an age but I just cannot see where I'm going wrong. The solution to the other poster was finding a place where he tried to pop or top from a deque with zero elements. I can't find where I'm doing that in my code.
EDIT: I suspect the issue is within SYAlg or OSProcess, if that helps.
// TestCalculator.cpp : main project file.
#include <string>
#include <iostream>
#include <locale>
#include <ctype.h>
#include <vector>
#include <deque>
using namespace System;
using namespace std;
//using std::string;
bool lastCharDigit = true;
string RawString; //Contains the raw equation the user types in.
deque<string> TokenEquation(1); //Contains the equation in tokenised infix form.
deque<string> RPNEquation; //Contains the equation in tokenised RPN form.
deque<string> OperatorStack; //Used as part of the Shunting Yard Algorithm
deque<string> SolverStack; //Used to solve the RPN Equation.
locale loc; //Used to verify digits.
//START FUNCTION DECLARATION
int main();
void tokeniser(string RawEquation);
void SYAlg();
void OSProcess(string newOperator);
void Solver();
//END FUNCTION DECLARATION
int main()
{
cout << "Please enter a valid infix notation equation, without parenthesis.\n";
cin >> RawString;
tokeniser(RawString);
cout << "\n";
system("pause");
return 0;
}
void tokeniser(string RawEquation)
{
int testCharPos = -1; // Initialise the index of the raw string
int tokenVectorPos = 0; // Initialise the token array position
int tokenVectorPrintPos = 0; // Initialise the print position
for (int eLength = RawEquation.length(); eLength != 0; eLength--) // For each character in the Raw string...
{
testCharPos++; // Increment the char we're testing
char testChar = RawEquation.at(testCharPos); // Establish the current test char
if (isdigit(testChar, loc)) //If the testchar is a digit
{
if (lastCharDigit) //If the last character was a digit
{
TokenEquation[tokenVectorPos] += testChar; //Append the tested char to the current token array pos
}
if (!lastCharDigit) //If the last character was not a digit
{
TokenEquation.push_back(string(1, testChar)); //Establish a new element with the testchar in it.
tokenVectorPos++;
}
lastCharDigit = true;
}
if (!isdigit(testChar, loc))//If the testchar is not a digit
{
TokenEquation.push_back(string(1, testChar)); //Establish a new element with the testchar in it.
tokenVectorPos++;
lastCharDigit = false;
}
}
cout << "The tokens of that equation are:\n\n"; //Outputs the tokens for testing purposes.
for (int tokenLength = TokenEquation.size(); tokenLength != 0; tokenLength--)
{
cout << " " << TokenEquation[tokenVectorPrintPos];
cout << "\n";
tokenVectorPrintPos++;
}
SYAlg(); //Call the SYAlg.
}
void SYAlg() //This function uses Shunting Yard Algorithm to convert the Infix tokens to RPN.
{
cout << TokenEquation.size();
for (int testtokenLength = TokenEquation.size(); testtokenLength != 0; testtokenLength--) //For each token in the tokenised deque
{
if (isdigit(TokenEquation.front().at(0), loc)) //Check if it's a number
{
RPNEquation.push_back(TokenEquation.front()); //Add the first raw token to the RPN Equation
TokenEquation.pop_front(); //Pop the token from the deque
}
if (!isdigit(TokenEquation.front().at(0), loc)) //If it's an operator
{
OSProcess(TokenEquation.front()); //Run the SYAlg operator stack procedure. NB This will pop the front of the TokenEquation for you.
}
}
cout << "The tokens of that equation are:\n\n"; //Outputs the tokens for testing purposes.
int RPNPrintPos = 0;
for (int tokenLength = RPNEquation.size(); tokenLength != 0; tokenLength--)
{
cout << " " << RPNEquation[RPNPrintPos];
cout << "\n";
RPNPrintPos++;
}
}
void OSProcess(string newOperator) //This function processes the Operator Stack
{
bool PushedNewOperator = false;
std::string newOpSTD = newOperator; //Creates an std::string version of the argument for easier comparison.
while (PushedNewOperator == false){ //As long as the new operator is still waiting to go to the stack
if (!OperatorStack.empty()) //If there's already an operator on the stack
{
if (newOpSTD == "/" || "*")
{
std::string OSBackSTD = OperatorStack.back(); //Create an STD version of the back of the OpStack for comparison.
if (OSBackSTD == "+" || "-")
{
OperatorStack.push_back(newOperator); //Add the tested operator to the stack
TokenEquation.pop_front(); //And pop it from the token equation
PushedNewOperator = true; //Set the flag variable to true so we stop looping
}
else
{
RPNEquation.push_back(OperatorStack.back()); //Add the top of the operator stack to the equation
OperatorStack.pop_back(); //Pop this back
}
}
else
{
RPNEquation.push_back(OperatorStack.back()); //Add the top of the operator stack to the equation
OperatorStack.pop_back(); //Pop this back
}
}
if (OperatorStack.empty())
{
OperatorStack.push_back(newOperator); //Add the tested operator to the stack
TokenEquation.pop_front(); //And pop it from the token equation
PushedNewOperator = true; //Set the flag variable to true so we stop looping
}
}
//For each operator on the stack, until the following statement returns false...
//Check if the precedence of newOperator is less than or equal to the top operator.
}
void Solver() //This function solves the RPNEquation
{
//Push each token to the solver stack
//If you push an operator, solve it against the stack
//When the RPN equation is empty and the solver stack only has one token in it, you have a solution
}
One major issue is with the multitude of lines which say if (newOpSTD == "/" || "*"), or something to that effect. These need to be changed to if (newOpSTD.compare("/") == 0 || newOpSTD.compare("*") == 0).
I think these checks failing means the while loop they're in turns into while(true).

How can I trace back the error

I was assigned to create an array check (to see if the array is increasing, decreasing, or neither [then exiting if neither]) and a recursive binary search for one of my assignments. I was able to do these things after some help from my peers, but I need help in finding what seems to be causing the error
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Aborted
when running the code. I Googled this error and this error seems to be vague or I just am not understanding. It compiles without errors, but I need help in what finding what I did wrong. It is able to run without the binarySearchR function and its associating code, as the array check on its own was the previous assignment. Below is the code, and I thank you so much in advance!
#include <iosteam>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
int checkArraySort (string *fileLines, int numberOfLines);
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax);
int main ()
{
int numberOfLines = 0;
string searchKey = 0;
cout << "Input search key: ";
cin >> searchKey;
ifstream fileIn;
fileIn.open("words_in.txt");
string line;
if (fileIn.eof()) /* Checks file to see if it is blank before proceeding */
{
exit (EXIT_SUCCESS);
}
else
{
while(!(fileIn.eof()))
{
fileIn >> line;
numberOfLines++;
}
fileIn.close(); /* closes fileIn, need to reopen to reset the line location */
fileIn.open("words_in.txt");
string *fileInLines;
fileInLines = new string[numberOfLines];
for (int i = 0; i < numberOfLines; i++)
{
fileIn >> line;
fileInLines[i] = line;
}
fileIn.close(); /* closes fileIn */
int resultingCheck = checkArraySort(fileInLines, numberOfLines);
if (resultingCheck == -1)
{
cout << "The array is sorted in descending order." << endl;
}
else if (resultingCheck == 1)
{
cout << "The array is sorted in ascending order." << endl;
}
else
{
cerr << "ERROR: Array not sorted!" << endl;
exit (EXIT_FAILURE);
}
int searchResult = binarySearchR (fileInLines, searchKey, 0, numberOfLines);
if (!searchResult == -1)
{
cout << "Key found at index " << searchResult << "." << endl;
}
else
{
cout << "Key not found at any index." << endl;
}
exit (EXIT_SUCCESS);
}
}
int checkArraySort (string *fileLines, int numberOfLines)
{
int result = 1; /* Ascending by default */
for (int i = 1; i < numberOfLines; i++) /* Checks if decending */
{
if (fileLines[i] < fileLines[i-1])
{
result = -1;
}
}
if (result == -1) /* Makes sure it is descending (or if it is neither) */
{
for (int i = 1; i < numberOfLines; i++)
{
if (fileLines[i] > fileLines[i-1])
{
result = 0;
}
}
}
return result;
}
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax)
{
// so, its gotta look at the center value and each times, it discards half of the remaining list.
if (iMax < iMin) /* If the minimum is greater than the maximum */
{
return -1;
}
else
{
int iMid = (iMin + iMax) / 2;
if (fileLines[iMid] > searchKey) /* If the key is in the lower subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid - 1);
}
else if (fileLines[iMid] < searchKey) /*If the key is in the upper subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid + 1);
}
else /*If anything else besides the two */
{
return iMid;
}
}
}
The easy way: add a bunch of cout s to see where you program goes and what the values are.
Pros
Easy to do
Cons
Requires a recompile each time you want to add more info
The hard way: Learn to use a debugger
Pros
Can inspect "on the fly"
Don't need to rebuild
Can use what you learn in every other C++ program
Cons
Requires a bit of research to learn how to do it.

C++, using stack.h read a string, then display it in reverse

For my current assignment, I have to use the following header file,
#ifndef STACK_H
#define STACK_H
template <class T, int n>
class STACK
{
private:
T a[n];
int counter;
public:
void MakeStack() {
counter = 0;
}
bool FullStack() {
return (counter == n) ? true : false ;
}
bool EmptyStack() {
return (counter == 0) ? true : false ;
}
void PushStack(T x) {
a[counter] = x;
counter++;
}
T PopStack() {
counter--;
return a[counter];
}
};
#endif
To write a program that will take a sentence, store it into the "stack", and then display it in reverse, and I have to allow the user to repeat this process as much as they want. The thing is, I am NOT allowed to use arrays (otherwise I wouldn't need help with this), and am finding myself stumped.
To give an idea of what I am attempting, here is my code as of posting, which obviously does not work fully but is simply meant to give an idea of the assignment.
#include <iostream>
#include <cstring>
#include <ctime>
#include "STACK.h"
using namespace std;
int main(void)
{
auto time_t a;
auto STACK<char, 256> s;
auto string curStr;
auto int i;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
cin >> curStr;
i = 0;
do
{
s.PushStack(curStr[i]);
i++;
} while (s.FullStack() == false);
do
{
cout << s.PopStack();
} while (s.EmptyStack() == false);
return 0;
} // end of "main"
UPDATE
This is my code currently
#include <iostream>
#include <string>
#include <ctime>
#include "STACK.h"
using namespace std;
time_t a;
STACK<char, 256> s;
string curStr;
int i;
int n;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
getline(cin, curStr);
i = 0;
n = curStr.size();
do
{
s.PushStack(curStr[i++]);
i++;
}while(i < n);
do
{
cout << s.PopStack();
}while( !(s.EmptyStack()) );
return 0;
You're on the right track, but you shouldn't be looping until the stack is full -- there are no guarantees curStr consists of at least 256 characters. Instead, loop like as follows...
int n = curStr.size();
do {
s.PushStack(curStr[i++]);
} while (i < n);
Now, you should really not write <bool-expr> == false or <bool-expr> == true... instead, merely write !<bool-expr> and <bool-expr>, respectively. You don't need all of your auto storage specifiers on the local variables, either. Your professor should also look into using the constructor rather than using MakeStack.
edit: It appears you had some trouble translating my code. You only need to i++ once per loop -- this increments our position in the string. As you are doing it now, you are actually incrementing the position twice and thus only pushing every other character.
Use a linked list instead of array in stack.
In the linked list, always store the tail pointer of your list's last node. Each node maintains a reference to your prev node.
A <--- B <---- C (tail)
push:
A <--- B <---- C <---- D (tail)
pop:
A <--- B <---- C (tail)
// D is popped out
when the tail == null, you know it is an empty stack

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!