I'm writing assignment (creating virtual world) and I've encountered one thing I can't go over. I have class Organism which is an abstract for all the future inheriting ones (animals etc.) and class World which represents the world of these objects. In the latter I can't create an array of Organisms though - to store position of every existing organism.
It throws:
"syntax error : missing 'token1' before 'token2'
I was thinking that maybe it has something to do with that it refers to each other (organism has reference to certain world and certain world wants to create array of organisms) but default constructor is solving that thing imo.
Could you tell what have I overseen? Thanks in advance.
World.h
#pragma once
class World
{
private:
int sizeX;
int sizeY;
Organism * worldMesh;
public:
World(int sizeX, int sizeY);
void nextTurn();
void drawWorld();
int getWorldX();
int getWorldY();
~World();
};
World.cpp
#include "stdafx.h"
#include "World.h"
#include <iostream>
using namespace std;
World::World(int sizeX, int sizeY)
{
this->sizeX = sizeX;
this->sizeY = sizeY;
worldMesh = new Organism[sizeX][sizeY];
for (int i = 0; i < sizeX; i++) {
for (int j = 0; j < sizeY; j++) {
worldMesh[i][j] = NULL;
}
}
} ....
Organism.h
#pragma once
#include "World.h"
#include "Position.h"
class Organism
{
protected:
int strength;
int initiative;
Position * position;
static World * world;
public:
Organism();
Organism(World * world);
int randValue();
virtual void spawn();
virtual void action();
virtual void collision();
void kill();
virtual ~Organism();
};
There is no such new Type[size1][size2] construction in C++, but you can do something like this:
int** mesh = new int*[size1];
for( int i = 0; i < size1; i++ ) {
mesh[i] = new int[size2];
for( int j = 0; j < size2; j++ ) {
mesh[i][j] = 0;
}
}
or just use std::vector
std::vector< std::vector<Type> > mesh;
or use single std::vector with size size1 * size2 and calculate index fromi and j: index = i * size1 + j
Related
I am currently working on C++, creating a program of the analysis of matrices.
As far as i saw those can be created using an arrays of arrays like this array2D[3][3]={{1,2,3},{4,5,6},{7,8,9}}.
Therefore, what i did was to generate a function in a class, such a function must return a 2D array. Then i created another class in order to generate the other array of array of arrays, but this 3D arrays need the data obtained by the previous class, remember the previous class holds the values of the matrix in a variable called int **degreesOfFreedom. Here is where the problem arises this second class needs the values of the double pointer and the problem like this appears.
error: cannot convert ‘int***’ to ‘int**’ in assignment
As far as i can see the error comes when trying to pass the 2D pointers arrays into the 3D pointers function.
By the way i already checked several ways and i saw that one of them is replacing the double pointer ** in the declaration of the variable inside of the function, and replace it by [][]. I already tried that, it didn't solve the problem, also i would not like to do that way because in the future i will have matrices of millions per millions elements.
This is my code
#include <iostream>
#include <string>
#include <fstream>
class MatrixOfDegreesOfFreedom
{
public:
int X, Y;
int M = 0;
public:
int **matrixOfDegreesOfFreedom(int rows, int cols)
{
X = rows;
Y = cols;
int** matrix = new int*[X];
for (int i = 0; i < X; ++i)
{
matrix[i] = new int[Y];
for (int j = 0; j < Y; ++j)
{
matrix[i][j] = M;
M = M + 1;
}
}
return matrix;
}
//constructor
MatrixOfDegreesOfFreedom()
{
}
//destructor
~MatrixOfDegreesOfFreedom()
{
}
};
class MatrixOfIndexes
{
public:
int X, Y, Z;
int M = 0;
public:
int ***matrixOfIndexes(int rows, int cols, int colsTwo, int conect[][2], int **DoF)
{
X = rows;
Y = cols;
Z = colsTwo;
int*** matrix = new int**[X];
for (int i = 0; i < X; ++i)
{
M = 0;
matrix[i] = new int*[Y];
for (int j = 0; j < Y; ++j)
{
matrix[i][j] = new int [Z];
for (int t = 0; t < Z; ++t)
{
matrix[i][j][t] = DoF[conect[i][j]][t];
}
M = M + 1;
}
}
return matrix;
}
//constructor
MatrixOfIndexes()
{
}
//destructor
~MatrixOfIndexes()
{
}
};
int main(int argc, char const *argv[])
{
#ifndef OUTPUT
freopen("output.txt", "w", stdout); // file to store the output data.
#endif
int numberOfNodes = 3; // number of nodes
int numberOfDegreesOfFreedomPerNode = 2; //Number of Degrees of Freedom per node
int **degreesOfFreedom = {}; //number of degree of freedom
int numberOfDegreesOfFreedomPerElement = 4; //Number of Degrees of Freedom per element
int numberOfElements = 3;
int connectivity[numberOfElements][2] = {{0,1},{2,1},{0,2}}; // Conectivity matrix along with the property
int **indexes = {};
MatrixOfDegreesOfFreedom tableOfDegreesOfFreedom;
degreesOfFreedom = tableOfDegreesOfFreedom.matrixOfDegreesOfFreedom(numberOfNodes, numberOfDegreesOfFreedomPerNode);
MatrixOfIndexes tableOfIndexes;
indexes = tableOfIndexes.matrixOfIndexes(numberOfElements, numberOfDegreesOfFreedomPerElement, numberOfDegreesOfFreedomPerNode, connectivity, degreesOfFreedom);
std::cout<< "finishing" << std::endl;
return 0;
}
The problem is that the function matrixOfIndexes returns a 3-dimensional pointer (int***) but the array you're assigning that return value to is a two-dimensional one (int**). The types have to match.
To fix it just add an extra * to the declaration of indexes:
int*** indexes = {};
I am trying to nest some of my enums within structs so that I can use them in functions involving the other struct variables further down the line. I keep getting an error in the new code for loop:
name followed by a :: must be a class or namespace
However, that's not an issue in the old code for loop, which doesn't use classes or namespaces.
Why is the new code throwing up this error? How can I fix it without converting my structs to classes?
oldcode.h
const int LONGBUTTON_HEIGHT = 128;
const int LONGBUTTON_WIDTH = 256;
enum CreateForestButtonState { CREATE_DEFAULT, CREATE_HOVER, CREATE_INACTIVE, CREATE_PRESSED, CREATE_TOTAL };
oldcode.cpp
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "oldcode.h"
SDL_Rect create_clips[CreateForestButtonState::CREATE_TOTAL];
for (int i = 0; i < CreateForestButtonState::CREATE_TOTAL; i++)
{
create_clips[i].x = i * LONGBUTTON_WIDTH;
create_clips[i].y = 0;
create_clips[i].w = LONGBUTTON_WIDTH;
create_clips[i].h = LONGBUTTON_HEIGHT;
}
int useCreate_Clip = CREATE_DEFAULT;
newcode.h
const int LONGBUTTON_HEIGHT = 128;
const int LONGBUTTON_WIDTH = 256;
struct Graphic
{
enum state {DEFAULT, HOVER, INACTIVE, PRESSED, TOTAL};
int use_clip;
int x;
int y;
int h;
int w;
};
newcode.cpp
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "newcode.h"
Graphic create_plain;
create_plain.type = "long button";
create_plain.state::DEFAULT;
create_plain.use_clip;
SDL_Rect clips[create_plain.state::TOTAL];
for (int i = 0; i < create_plain.state::TOTAL; i++)
{
clips[i].x = i * LONGBUTTON_WIDTH;
clips[i].y = 0;
clips[i].w = LONGBUTTON_WIDTH;
clips[i].h = LONGBUTTON_HEIGHT;
}
create_plain.use_clip = create_plain.DEFAULT;
Don't name the enum :
struct Graphic
{
enum {DEFAULT, HOVER, INACTIVE, PRESSED, TOTAL};
int use_clip;
int x;
int y;
int h;
int w;
};
and
SDL_Rect clips[Graphic::TOTAL];
Use
for (int i = 0; i < Graphic::state::TOTAL; i++)
You should use the scope, not an object.
This arrangement works. I don't know why.
for (int i = 0; i < create_plain.TOTAL; i++)
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) { ... }
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();
};
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*> :)