my homework assignment is asking me to create a array2d class and I am having trouble compiling it. It crashes every time it is compiled and I am unsure what I am doing wrong. My debugger is saying it is during my set value portion but I am not sure what it is exactly. Help would be great!
#include <iostream>
using namespace std;
class array2D {
private:
int xRes, yRes;
float **xtable;
public:
array2D(int xRes, int yRes){
float **xtable;
xtable = new float*[yRes];
for(int i=0;i < yRes;i++) {
xtable[i] = new float[xRes];}}
~array2D(){
for (int i = 0; i<yRes; i++){
delete [] xtable[i];}
delete [] xtable;}
void getSize(int &xRes, int &yRes){}
int getValue (int x, int y){return xtable[x][y];}
void setValue(int x, int y, int Val) {xtable[x][y]=Val;}
};
int main() {
array2D *a = new array2D(320,240);
int xRes, yRes;
a->getSize(xRes,yRes);
for(int i=0;i < yRes;i++){
for(int j=0;j < xRes;j++){
a->setValue(i,j,100); // constant value of 100 at all locations
}
}
for(int i=0;i < yRes;i++){
for(int j=0;j < xRes;j++){
cout << a->getValue(i,j) << " ";
}
cout << endl;
}
delete a;
}
In these lines
array2D(int xRes, int yRes){
float **xtable;
you are declaring a local variable. The class member variable of the same name remains uninitialized and you use that later.
Remove the second line.
Also, the member variables xRes and yRes are not initialized either.
Use:
array2D(int xResIn, int yResIn) : xRes(xResIn), yRes(yResIn) {
xtable = new float*[yRes];
for(int i=0;i < yRes;i++) {
xtable[i] = new float[xRes];
}
}
Also, change
void getSize(int &xRes, int &yRes){}
to
void getSize(int &xResOut, int &yResOut)
{
xResOut = this->xRes;
yResOut = this->yRes;
}
As you expand this class, keep in mind The Rule of Three and implement the copy constructor and copy assignment operator.
array2D(array2D const& copy) { ... }
array2D& operator=(array2D const& rhs) { ... }
Related
I am working on a tic tac toe program and I need to create a 2D array of variable size in a class. This is how I have it written now:
class ticTacToe
{
public:
ticTacToe();
void display();
bool moveIsValid();
private:
int rows;
int cols;
int board[rows][col];
}
I have the board being read in from a file in the constructor but I am not sure how to make it of variable size so that I can read in a board of any size and then access it outside of the class.
"I have the board being read in from a file in the constructor but I am not sure how to make it of variable size so that I can read in a board of any size"
In c++ you use a std::vector instead a raw array like follows
class ticTacToe {
public:
ticTacToe();
void display();
bool moveIsValid();
private:
int rows;
int cols;
std::vector<std::vector<int>> board; // <<<<
};
The dynamic allocation can be applied as follows in a constructor:
ticTacToe(int rows_, int cols_) : rows(rows_), cols(cols_) {
board.resize(rows,std::vector<int>(cols));
}
and then access it outside of the class
Well, I'm not sure that this is really a good idea, but you can simply add an accessor function for that member variable
std::vector<std::vector<int>>& accBoard() { return board; }
The better design approach would be IMHO, to provide something like a separate function to read from a std::istream:
void ticTacToe::readFromStream(std::istream& is) {
// supposed the first two numbers in the file contain rows and cols
is >> rows >> cols;
board.resize(rows,std::vector<int>(cols));
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < cols; ++c) {
cin >> board[r][c];
}
}
}
For real code you would check for input errors of course like
if(!(is >> rows >> cols)) {
// handle errors from input
}
In case this is homework and you cannot use the standard library:
// Declaration
int rows;
int columns;
int **board;
// Construction
board = new int*[rows];
for (int i = 0; i < rows; i++) {
board[i] = new int[columns];
}
// Destruction
for (int i = 0; i < rows; i++) {
delete[] board[i];
}
delete[] board;
Update: You could perform a single allocation but it will be easier for you to work it this way.
You either need to have a dynamically sized array
int* board;
Then your constructor would be
ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
board = new int[rows * cols];
}
And your destructor
ticTacToe::~ticTacToe()
{
delete[] board;
}
Or better yet use a std::vector
std::vector<int> board;
Then your constructor would be
ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
board.resize(_rows * _cols);
}
I suggest you to use pointer to pointer.
#include <iostream>
#include <cstdlib>
using namespace std;
class ticTacToe{
private:
int rows;
int cols;
int **board; // POINTER TO POINTER
public:
ticTacToe(int a,int b){
rows=a;
cols=b;
board=new int*[rows];
for (int k = 0; k < rows; ++k) {
board[k]=new int[cols];
}
/*LET'S INITIALIZE CELL VALUES TO= 0*/
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
board[i][j]=0;
}
}
}
void display();
bool moveIsValid();
};
How do you create multiple class instances without individually typing in their names?
int main(){
myClass myInstance_1;
myClass myInstance_2;
myClass myInstance_3;
...
myClass myInstace_10;
}
You may do the following:
int main(){
std::vector<myClass> myInstances;
for(int i = 0; i < 10; ++i) {
myInstances.emplace_back(i);
}
myInstances[5].myClassFunction();
}
How do you create multiple class instances without individually typing in their names?
The answer is you make an array, but not the way you tried it.
Like this:
int main()
{
MyClass myInstance[10];
for(int i = 0; i < 10; i++)
{
myInstance[i].myClassFunction();
}
}
TIP: Don't use arrays, use std::vector or std::array.
(see answer from #Jarod42)
Solution 1: Use an array of integers as an initializer, the constructor is used to convert the integer to myClass.
class myClass
{
public:
//constructor
myClass( int num) {m_number = num;};
void myClassFunction(){cout<< "I am " << m_number << endl;}
private:
int m_number;
};
int main(){
myClass myInstance[10] = {0,1,2,3,4,5,6,7,8,9};
for ( int i=0; i< 10; i++) myInstance[i].myClassFunction();
}
Solution 2: Use a static counter to set m_number, so no need to use a non-default constructor.
class myClass
{
public:
//constructor
myClass(){m_number=counter++;};
void myClassFunction(){cout<< "I am " << m_number << endl;}
private:
int m_number;
static int counter;
};
int myClass::counter = 0;
int main(){
myClass myInstance[10];
for ( int i=0; i< 10; i++) myInstance[i].myClassFunction();
}
Solution 3: Set the m_number after the constructor call, so the default constructor is enough.
class myClass
{
public:
//constructor
void setNum(int num){m_number=num;};
void myClassFunction(){cout<< "I am " << m_number << endl;}
private:
int m_number;
};
int main(){
myClass myInstance[10];
for ( int i=0; i< 10; i++) myInstance[i].setNum(i);
for ( int i=0; i< 10; i++) myInstance[i].myClassFunction();
}
Just like Jarod42's code:
int main(){
std::vector<myClass> myInstances;
for(int i = 0; i < 10; ++i) {
myInstances.push_back(myClass(i));
}
myInstances[5].myClassFunction();
}
I think these should work.
Use array:
myClass myInstance[10];
This will create an array with 10 instances but each instance will have its m_number set to 0.
Another approach:
myClass *myInstance = new myClass[10];
for (unsigned int i = 0; i < 10; i++)
{
myInstance[i] = new myClass(i);
}
Here each instance will have different m_number values
Edit for the sake of fixing the problem with above code. Better solutions have already been proposed.
myClass *myInstance[10];
// Allocate
for (unsigned int i = 0; i < 10; i++)
{
myInstance[i] = new myClass(i);
}
// At the end free
for (unsigned int i = 0; i < 10; i++)
{
delete myInstance[i];
}
I have a baseclass called gridObject
Here's the header file:
#ifndef ITEM_H
#define ITEM_H
class gridObject
{
public:
gridObject();
virtual ~gridObject();
virtual int get_GridID() = 0;
virtual int get_x() = 0;
virtual int get_y() = 0;
virtual int get_direction() = 0;
void set_x(int x);
void set_y(int y);
void set_direction(unsigned int direction);
protected:
private:
int _x;
int _y;
unsigned int _direction;
};
#endif // ITEM_H
I have a subclass called player
Here's the get_GridID() method in the class file:
int player::get_GridID() { return 2; }
There's also a grid class that keeps track of all the objects on it via a 2d vector. In the header file, there's that vector:
private:
vector<vector<gridObject*> > _position;
Here are the methods for setting and getting an object at a specific position, respectively:
void grid::setGridPosition(int x, int y, gridObject* obj) { _position[y][x] = obj; }
gridObject* grid::getGridPosition(int x, int y) { return _position[y][x]; }
The problem I'm having is here:
int main()
{
grid * gr = new grid(10, 10);
player p(0, 0, 100);
gridObject * go = &p;
gr->setGridPosition(0, 0, go);
cout << gr->getGridPosition(0, 0)->get_GridID();
return 0;
}
It crashes at: cout << gr->getGridPosition(0, 0)->get_GridID();
I have included all of the appropriate header files.
EDIT: Here is the constructor for grid and the initialization of _position:
grid::grid(int width, int length)
{
setSize(width, length);
}
void grid::setSize(int width, int length)
{
setLength(length);
setWidth(width);
}
void grid::setLength(int val) { _position.resize(val); }
void grid::setWidth(int val)
{
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(val);
}
You're working with vector of vectors:
vector<vector<gridObject*> > _position;
but the way you initialize _position is following:
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(width);
Note that the first resize constructs length objects of type vector<gridObject*>. Then you are iterating not through these newly-constructed vectors, but rather their elements (second nested loop), which in this case causes that the line _position.at(i).resize(width); is never executed and thus _position[y][x] = obj tries to access the invalid memory resulting in undefined behavior that you observe as segmentation fault.
Try this instead (in grid::setSize):
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; ++i)
_position[i].resize(width);
and also consider using typedef for creating an alias for std::vector<gridObject*> :)
Alright, I'm trying to implement a simple 2D matrix class right now. This is what it looks like so far:
template <typename Type>
class dyMatrix {
private:
Type *mat;
int width, height;
int length;
public:
dyMatrix (int _width, int _height)
: width(_width), height(_height), mat(0)
{
length = width * height;
mat = new Type[length];
};
// ---
int getWidth() {
return width;
};
int getHeight() {
return height;
};
int getLength() {
return length;
}
// ---
Type& operator() (int i, int j) {
return mat[j * width + i];
};
Type& operator() (int i) {
return mat[i];
};
// ---
~dyMatrix() {
delete[] mat;
};
};
To test it, and compare with static multi-dimensional arrays, I wrote the following snippet of code:
#include <iostream>
using namespace std;
/* matrix class goes here */
struct Coord {
int x, y;
Coord()
: x(0), y(0)
{};
Coord (int _x, int _y)
: x(_x), y(_y)
{};
void print() {
cout << x << ", " << y;
};
};
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
int i = 5, j = 0;
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
adabo(i, j).print();
return 0;
}
"Adabo" and "Inakos" being arbitrarily chosen names. Upon execution, inakos prints its contents but the program crashes before adabo can do anything. Another interesting thing is that, if I give i and j values other than 5 and 0, like 5 and 1, respectively, it works fine.
I don't know what exact numbers work and which make the program go haywire, I only know that there's a irregularity here. What am I possibly doing wrong? I'm an amateur at C++, so I may or not have misused something in any of the structures.
If anyone also has the time, I'd very much like to know if there's any other error of notice in my matrix class. Anything that's not possibly related to the problem, but is a fallacy nevertheless.
I've also tested it with the following main(), but it still crashes after inakos prints its contents in [5][1]. Maybe it has to do not with dyMatrix, but a loosely-implemented Coord?
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
for (int i = 0; i < adabo.getHeight(); i++) {
for (int j = 0; j < adabo.getWidth(); j++) {
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
cout << "; ";
}
cout << "\n\n";
}
cout << "\n\n\n";
Coord temp;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
temp = adabo(i, j);
temp.print();
cout << "; ";
}
cout << "\n\n";
}
return 0;
}
edit: It hasn't to do with Coord. Just tested with a dyMatrix of ints and static matrix of ints, and it crashes after [5][0] nevertheless.
In your first example, you declared inakos[5][7] so the indices range from 0 to 4 and 0 to 6. inakos[5][0] and inakos[5][1] could therefore crash.
In your second example, you again declare inakos[5][7] yet you let the first index loop from 0 to 6. Again inakos[i][j] can crash. One fix is to switch your indices (ie, change to i<adabo.getWidth() and j<adabo.getHeight()).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Operator[][] overload
I have made class which contains an array containing (in one row) all the numbers from the given 2d array. For example given: {{1,2}{3,4}} the b field in the object of class T contains {1,2,3,4}. I would like to overload[][] operator for this class so it will work like that
T* t.....new etc.
int val = (*t)[i][j]; //I get t->b[i*j + j] b is an 1dimension array
class T{
public:
int* b;
int m, n;
T(int** a, int m, int n){
b = new int[m*n];
this->m = m;
this->n = n;
int counter = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
b[counter] = a[i][j];
counter++;
}
}
}
int main()
{
int m = 3, n = 5, c = 0;
int** tab = new int*[m];
for(int i = 0; i < m; i++)
tab[i] = new int[n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
tab[i][j] = c;
c++;
cout<<tab[i][j]<<"\t";
}
cout<<"\n";
}
T* t = new T(tab,3,5);
};
You cannot. You have to overload operator[] to return a proxy object, that in turn, overloads operator[] to return the final value.
Something like:
class TRow
{
public:
TRow(T &t, int r)
:m_t(t), m_r(r)
{}
int operator[](int c)
{
return m_t.tab[m_t.n*m_r + c];
}
private:
T &m_t;
int m_r;
};
class T
{
friend class TRow;
/*...*/
public:
TRow operator[](int r)
{
return TRow(*this, r);
}
};
Instead of saving a T& in TRow you could save directly a pointer to the row, that's up to you.
A nice feature of this solution is that you can use the TRow for other things such as operator int*().
In the case of a 2d array, you don't need to create a proxy type. Just use int*:
#include <iostream>
class T {
public:
int m, n;
int *b;
T(int m, int n) : m(m), n(n), b(new int[m*n]) {
}
int*operator[](std::size_t i) {
return &b[i*m];
}
};
int main () {
T t(2,2);
t[0][0] = 1;
t[0][1] = 2;
t[1][0] = 3;
t[1][1] = 4;
std::cout << t.b[0] << t.b[1] << t.b[2] << t.b[3] << "\n";
}