Alright well the code is pretty long so cheers lol. But the program will not run in release mode at all. But when I comment out the destructors code, it works fine in debug mode with no debugging.
Code:
#include "Matrix.h"
//default constructor
Matrix::Matrix()
{
_name = "";
_row = 0;
_col = 0;
_mat = NULL;
errorInput = 1;
}
//copy constructor call
Matrix::Matrix(const Matrix &m)
{
int i,j;
_row = m._row;
_col = m._col;
_name = m._name;
errorInput = m.errorInput;
_mat = new double *[_row];
for(i=0;i<_row;i++)
{
_mat[i] = new double [_col];
for(j=0;j<_col;j++)
{
_mat[i][j] = m._mat[i][j];
}
}
}
//destructor
Matrix::~Matrix()
{
for(int i = 0; i < _row; i++)
{
delete[] _mat[i];
}
delete[] _mat;
_mat = NULL;
}
//swap for the copy
void Matrix::swap(Matrix& m)
{
//uses std::swap and swaps the current matrix's contents with the contents of the arg m - 1 by 1
std::swap(_name, m._name);
std::swap(_row, m._row);
std::swap(_col, m._col);
std::swap(errorInput, m.errorInput);
std::swap(_mat,m._mat);
}
//returns the name of a matrix
string Matrix::getName(void)
{
return _name;
}
//returns the number of rows
int Matrix::getRow(void)
{
return _row;
}
//returns the number of columns
int Matrix::getCol(void)
{
return _col;
}
//returns the error
int Matrix::getError(void)
{
return errorInput;
}
//clear the matrix by using the copy swap idiom and creating a blank temp and swapping it with the
//current matrixs data. then when exits destructor gets called to destroy temp (old data)
void Matrix::clear(void)
{
Matrix temp;
swap(temp);
}
//this sets the name of the string passed to matrixs name
void Matrix::setName(string name)
{
_name.clear();
_name = name;
}
//transpose a matrix uses the copy and swap idiom again by using a copy constructor to create a temp instance
//with the data of the current matrix and a default constructor for another. Set the corresponding rows and columns
//by reversing the order from the current matrix. while using the same new double method and swapping at the end with the new data
Matrix Matrix::transpose(void)
{
Matrix temp1;
temp1._row = _col;
temp1._col = _row;
temp1._mat = new double *[temp1._row];
for(int i = 0; i < temp1._row; i++)
{
temp1._mat[i] = new double [temp1._col];
for(int j = 0; j < temp1._col; j++)
{
temp1._mat[i][j] = _mat[j][i];
}
}
return temp1;
}
//sets the data of a matrix given a matrix operator overloading
//assignment operator just another copy and swap
Matrix & Matrix::operator = (const Matrix& mMatrix)
{
Matrix temp(mMatrix);
swap(temp);
return *this;
}
//overloaded input stream operator
std::istream& operator>>(std::istream &is, Matrix & mMatrix)
{
string tempString,restOfLine;
istringstream tempNumString;
deque<string> sList;
int row = 0;
int col = 0;
int foundEnd = 0;
int lastCol = 0;
double tempDBL;
//set flags for ios
std::ios_base::fmtflags temp=is.flags();
//get the entire line of input
getline(cin,restOfLine);
for(string::iterator sIT = restOfLine.begin(); sIT != restOfLine.end(); ++sIT)
{
//should only be one [ and it should be at the beginning
if(*sIT == '[')
{
//error if the [ is not at the begining of the line and thats it
if(sIT != restOfLine.begin())
{
mMatrix.errorInput = 3;
return is;
}
}
//the character is an ] then this is the final go around
else if(*sIT == ']')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
}
else if(lastCol == col)
{
row++;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
else
{
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
}
else if(lastCol == col)
{
row++;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
foundEnd = 1;
}
else if(*sIT == ';')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
col = 0;
}
else if(lastCol == col)
{
row++;
col = 0;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
else
{
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
col = 0;
}
else if(lastCol == col)
{
row++;
col = 0;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
}
//if find whitespace then gotta do a new column case if there is something in tempString
else if(*sIT == ' ')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
}
else
{
//then junk or just did above so skip over everything
}
}
//then the chacter must be something other than '[' ']' ';' ' '
else
{
//if it is a valid number then push it into a string
if(*sIT > 47 && *sIT < 58)
{
tempString.push_back(*sIT);
}
//if its not a valid number then leave
//and return proper error
else
{
mMatrix.errorInput = 3;
return is;
}
}
}
mMatrix.errorInput = 1;
mMatrix._row = row;
mMatrix._col = col;
//and do a final assignment to the matrix passed to the stream
mMatrix._mat = new double *[row-1];
for(int i=0;i<row;i++)
{
mMatrix._mat[i] = new double [col-1];
for(int j=0;j<col;j++)
{
//use isstringstreams to convert the string to a double
tempNumString.str(sList.front());
tempNumString >> tempDBL;
//then pop front to get the next string in line
sList.pop_front();
//clear the isstrinstream
tempNumString.clear();
//and finally assign the matrix its value
mMatrix._mat[i][j] = tempDBL;
}
}
is.flags(temp);
return is;
}
//overloaded operator for cout
//just a simple display loop
ostream& operator<<(ostream& os, const Matrix& m)
{
std::ios_base::fmtflags temp=os.flags();
int i,j;
cout << m._name << " =" << endl << endl;
for(i=0;i<m._row;i++)
{
for(j=0;j<m._col;j++)
{
cout << "\t" << m._mat[i][j];
}
cout << endl;
}
cout << endl << endl;
os.flags(temp);
return os;
}
//simple scalar addition with a matrix
const Matrix Matrix::operator+ (double adder)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
result._mat[i][j] += adder;
}
}
return result;
}
//simple scalar subtraction with a matrix
const Matrix Matrix::operator- (double subber)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
result._mat[i][j] -= subber;
}
}
return result;
}
//simple scalar multiplication with a matrix
const Matrix Matrix::operator* (double multer)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
result._mat[i][j] *= multer;
}
}
return result;
}
//addition between two matrices the rows and columns of each must equal
//then add term by term
const Matrix Matrix::operator+(const Matrix &rhs) const
{
Matrix result(*this);
if(_row == rhs._row && _col == rhs._col)
{
for(int i = 0; i< _row; i++)
{
for(int j = 0 ; j<_col ; j++)
{
result._mat[i][j] += rhs._mat[i][j];
}
}
}
return result;
}
//subtraction between two matrices the rows and columns of each must equal
//then subtract term by term
const Matrix Matrix::operator-(const Matrix &rhs) const
{
Matrix result(*this);
if(_row == rhs._row && _col == rhs._col)
{
for(int i = 0; i< _row; i++)
{
for(int j = 0 ; j<_col ; j++)
{
result._mat[i][j] -= rhs._mat[i][j];
}
}
}
return result;
}
//multiplactions between two matrices the new size of the matrix
//will be the rows of the first matrix by the columns of the second matrix
//and do the special math for each term (result._mat[i][j] = result._mat[i][j] + _mat[i][k] * rhs._mat[k][j])
const Matrix Matrix::operator*(const Matrix &rhs) const
{
Matrix result;
result._mat = new double*[_row];
for(int i=0;i<_row;i++)
{
result._mat[i] = new double [rhs._col];
for(int j=0;j<rhs._col;j++)
{
result._mat[i][j] = 0;
for(int k=0;k< _col;k++)
{
result._mat[i][j] = result._mat[i][j] + _mat[i][k] * rhs._mat[k][j];
}
}
}
//then set the new rows to the final matrix along with the cols
//and its errorinput to a 1
result._row = _row;
result._col = rhs._col;
result.errorInput = 1;
return result;
}
main.cpp
Code:
#include "Matrix.h"
/* THE FOLLOWING TWO FUNCTIONS MUST BE COMPLETED; THEY ARE LISTED AT THE BOTTOM OF THIS FILE */
// Finds matrix with name n in vector mL; returns -1 if matrix is not present
int findMatrix(vector <Matrix> &mL, string n);
// Adds matrix m to vector mL; returns position where added
int addMatrix(vector <Matrix> &mL, Matrix &m);
int main()
{
//definitions
vector <Matrix> mList; // List of variables in program
string cmd, cmd2, cmd3; // Strings for command input
string restOfLine, tempString; // Used to clear input stream on errors
char c; // Holds single input character
Matrix temp; // Temporary matrix object
int pos, pos2, pos3; // Used to hold position of matrices in mList
char op; // Operator
int scalar; // Scalar input variable
//forever while loop
while (1)
{
//display indicator
//and scan in the first thing should be a name of a matrix or cmd of exit clear who or whos
cout << ">> ";
cin >> cmd;
if (cmd == "exit") // Exit program
return 0;
else if (cmd == "clear") // Clear all variables
mList.clear();
else if (cmd == "who")
{
if(mList.size() > 0)
{
// Print variable names
cout << "Your variables are:" << endl << endl;
for(vector<Matrix>::iterator iT = mList.begin(); iT != mList.end(); ++iT)
{
cout << iT->getName() << "\t";
}
cout << endl << endl;
}
}
else if (cmd == "whos")
{
if(mList.size() > 0)
{
// Print detailed variable information
cout << "Name\tSize\tBytes" << endl << endl;
for(vector<Matrix>::iterator iT = mList.begin(); iT != mList.end(); ++iT)
{
cout << iT->getName() << "\t" << iT->getRow() << "x" << iT->getCol() << "\t" << (int)iT->getRow() * (int)iT->getCol() * 8 << " bytes" << endl << endl;
}
}
}
/* If no conditions above are true, treat cmd as name of matrix
* Possible commands include:
* M = [<list>] Create new matrix
* M = M Assign one matrix to another
* M = M' Assign the transpose of one matrix to another
* M = -M Assign the negative of one matrix to another
* M = M op M Perform op (+, -, *) on two matrices and assign result to matrix
* M = M op S Perform op (+, -, *) on matrix and scalar and assign result to matrix */
else
{
// cmd should be treated as matrix name--see if it's in mList
// Will use value of pos later
pos = findMatrix(mList, cmd);
//if following the name of matrix is a new line then print contents of the matrix
if (cin.peek() == '\n')
{
// End of line--should print contents of current matrix
// Matrix not found--print error
if (pos == -1)
cerr << "Error: undefined matrix " << cmd << endl;
// Matrix found--print it
else
cout << mList[pos];
}
//if not new line character then the next charcter must be an = by itself
else
{
cin >> c;
if (c != '=')
{
// Wrong character--print error and clear input stream
cerr << "Error: incorrectly formatted command" << endl;
getline(cin, restOfLine);
}
else
{
/* How you handle the next part of the input depends on whether the
* first character is '[' or not--if it is, you're creating a new
* matrix (or assigning new values to an existing one); if it's not,
* then you're doing some sort of matrix operation. The >> operator
* will assume that you're reading in everything starting with the '[',
* so the code below will scan the input and discard all whitespace
* characters. You can't just use "cin >>" because you don't know
* what the next character will be. */
//skip the whitespace between the = and what follows
while ((c = cin.peek()) == ' ')
cin.get(c);
// Check for '[' --> assigning new values to matrix
if (c == '[')
{
//if the matrix name is not found on the left of = then
//must create the matrix parse the info from the [...] and use addMatrix to assign matrix
//to the list
if (pos == -1)
{
//clear all the leftover contents of temp
temp.clear();
//call the istream operator to parse what follows in the [...]
cin >> temp;
//upon return from the istream overloaded operator
//switch for errors
switch(temp.getError())
{
//if error is a 2 then the dimensions within the matrix are not the same
case 2:
temp.clear();
cout << "Dimensions don't match" << endl;
break;
//if error is a 3 then the matrix is missing the ]
case 3:
temp.clear();
cout << "Improperly formatted matrix" << endl;
break;
//if error is a 4 then the matrix has a character in it [..a; 1 2 a]
case 4:
temp.clear();
cout << "Improperly formatted matrix" << endl;
break;
//if none above then the no error and good to set the name of the matrix to that
//from cmd which holds the name left of =
//then add instance of matrix to list and display it
default:
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
break;
}
}
else
{
//same as above except the name of matrix to left of = was found
//so only thing that changes is the default case which sets the matrix appropriate
//index in list to the temp instance
cin >> temp;
switch(temp.getError())
{
case 2:
temp.clear();
cout << "Dimensions don't match" << endl;
break;
case 3:
temp.clear();
cout << "Improperly formatted matrix" << endl;
break;
case 4:
temp.clear();
cout << "Improperly formatted matrix" << endl;
break;
default:
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
break;
}
}
}
// Other commands of form M = expression
else
{
cin >> cmd2; // Read matrix name
/* End of line--command must be:
* M = M Assign one matrix to another
* M = M' Assign the transpose of one matrix to another
* M = -M Assign the negative of one matrix to another */
if (cin.peek() == '\n')
{
// Transpose if find ' in the following string
if (cmd2.find('\'', cmd2.size() - 1) != string::npos)
{
//get the name of matrix to traspose by itself
cmd2 = cmd2.substr(0, cmd2.size() - 1);
//find its index in list
pos2 = findMatrix(mList, cmd2);
//if matrix on right of = doesnt exist then return error
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if the matrix on right was found then
//clear the temp instance and set it to the transposed
//matrix of the index from the list
temp.clear();
temp = mList[pos2].transpose();
//set the name of the matrix to the name on the left
temp.setName(cmd);
//if matrix on left is not found then add new matrix
if(findMatrix(mList,cmd) == -1)
{
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the new temp instance
else
{
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
}
// Negative
else if (cmd2.find('-') == 0)
{
//find the matrix name following the first character which should be the -
cmd2 = cmd2.substr(1);
pos2 = findMatrix(mList, cmd2);
//if the matrix does not exist then error otherwise
//set the matrix on left of = to the - of the matrix on right
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on left is not found then add new matrix
//with the appropriate neg data
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * (-1);
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix * -1
else
{
temp = mList[pos2] * (-1);
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
}
// Basic assignment
else
{
pos2 = findMatrix(mList, cmd2);
//if the matrix on the right is not found
//then return error otherwise set matrix on left to right
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on left is not found then add new matrix
//by clearing temp and then add matrix with the appropriate data
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2];
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix
else
{
temp = mList[pos2];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
}
}
/* Command must take one of two forms:
* M = M op M Perform op (+, -, *) on two matrices and assign result to matrix
* M = M op S Perform op (+, -, *) on matrix and scalar and assign result to matrix */
else
{
cin >> op; // Read operator
/* Remove whitespace--need to be able to check if next string
is matrix or scalar */
while ((c = cin.peek()) == ' ')
cin.get(c);
// Scalar input--command is M op S
// Must fix name in each case when done
if ((c >= '0') && (c <= '9'))
{
//get the following number following the op
cin >> scalar;
//find if the matrix on the right of the = which has an op and scalar to it
//exists if it doesn return error if it does exist figure of what the op is and do according
pos2 = findMatrix(mList, cmd2);
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//switch for the op code
switch (op)
{
//if the op is + then a simple scalar addition is required
case '+':
//if matrix on left is not found then add new matrix
//with the appropriate data from addition of scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] + scalar;
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix + scalar
else
{
temp.clear();
temp = mList[pos2] + scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
break;
//simple subtraction of scalar and matrix
case '-':
//if matrix on left is not found then add new matrix
//with the appropriate data from subtraction of scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] - scalar;
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix - scalar
else
{
temp.clear();
temp = mList[pos2] - scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
break;
case '*':
//if matrix on left is not found then add new matrix
//with the appropriate data multiplied by scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * scalar;
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix * scalar
else
{
temp.clear();
temp = mList[pos2] * scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
break;
default:
cerr << "Error: undefined operation " << op << endl;
}
}
}
// Matrix input--command is M op M
else {
cin >> cmd3;
//scanned in the 3rd matrix name time to check both matrices on right of = exist
//if matrix before op doesnt exit return error otherwise check other matrix
pos2 = findMatrix(mList, cmd2);
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on right of op doesnt exist then return error
//otherwise both exist time to do the math
pos3 = findMatrix(mList, cmd3);
if (pos3 == -1)
cerr << "Error: undefined matrix " << cmd3 << endl;
else
{
//switch statement for the op between the two matrices
switch(op)
{
//addition of the two matrices requires them to be the same exact size
case '+':
if(mList[pos2].getCol() == mList[pos3].getCol() && mList[pos2].getRow() == mList[pos3].getRow())
{
//if the matrices are the same size then do the apporpiate math for the matrix
//on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] + mList[pos3];
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix + 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] + mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
else
cout << "Error: dimensions are inconsistent" << endl;
break;
case '-':
if(mList[pos2].getCol() == mList[pos3].getCol() && mList[pos2].getRow() == mList[pos3].getRow())
{
//if the matrices are the same size then do the apporpiate math for the matrix
//on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] - mList[pos3];
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix - 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] - mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
else
cout << "Error: dimensions are inconsistent" << endl;
break;
case '*':
//for matrix multiplication then the columns of the first matrix
//must equal the rows of the second matrix
if(mList[pos2].getCol() == mList[pos3].getRow())
{
//if the matrices are the appropriate size for matrix multiplication
//then do the apporpiate math for the matrix on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * mList[pos3];
temp.setName(cmd);
addMatrix(mList,temp);
cout << temp;
}
//else set the index from list to the right matrix * 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] * mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
addMatrix(mList,temp);
cout << temp;
}
}
else
cout << "Error: inner dimensions must match" << endl;
break;
default:
cerr << "Error: undefined operation " << op << endl;
}
}
}
}
}
}
}
}
}
}
}
// Finds matrix with name n in vector mL; returns -1 if matrix not present
int findMatrix(vector <Matrix> &mL, string n)
{
for(vector<Matrix>::iterator iT = mL.begin(); iT != mL.end(); ++iT)
{
//if strings match use std function called distance to find the number of elements between
//the beginning of a vector and the current itereator pos
if(iT->getName() == n)
return (int)distance(mL.begin(), iT);
}
return -1;
}
// Add m to array of matrices
int addMatrix(vector <Matrix> &mL, Matrix &m)
{
mL.push_back(m);
Matrix tmp, tmp1;
for(long i=0;i<mL.size();i++)
{
for(long x=0; x<mL.size()-1-i; x++)
{
if(mL[x].getName() > mL[x+1].getName())
{
//r.push_back(rnd);
tmp = mL[x];
mL[x] = mL[x+1];
mL[x+1] = tmp;
}
}
}
return -1;
}
header
Code:
#pragma once
#include <vector>
#include <string>
#include <sstream>
#include <deque>
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix
{
private:
string _name;
int errorInput;
int _row;
int _col;
double ** _mat;
deque<string> mSList;
public:
//Constructors
Matrix();
Matrix(const Matrix &m);
//Deconstructor
~Matrix();
//swap for copy
void swap(Matrix& m);
//get functions for variables
string getName(void);
int getRow(void);
int getCol(void);
int getError(void);
//set functions for variables
void setName(string name);
//clear the matrix
void clear(void);
//transpose Matrix
Matrix transpose(void);
//operators to overload
Matrix & Matrix::operator = (const Matrix & mMatrix);
friend std::istream& operator>>(std::istream &is, Matrix & mMatrix);
friend ostream& operator<<(ostream& os, const Matrix& dt);
const Matrix operator+(double adder) const;
const Matrix operator-(double subber) const;
const Matrix operator*(double multer) const;
const Matrix operator+(const Matrix &rhs) const;
const Matrix operator-(const Matrix &rhs) const;
const Matrix operator*(const Matrix &rhs) const;
};