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*> :)
Related
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
#include <iostream>
using namespace std;
typedef int vertex;
enum vertexstate { white, gray, black };
class graph
{
private:
bool**adjacencymatrix;
int vertexcount;
public:
graph(int vertexcount);
~graph();
void addedge(int i, int j);
void removeedge(int i, int j);
bool isedge(int i, int j);
void display();
void Dfs();
void runDfs(int u, vertexstate state[]);
};
graph::graph(char filename[], int vertexcount) //error is here
{
this->vertexcount = vertexcount;
adjacencymatrix = new bool*[vertexcount];
for (int i = 0; i<vertexcount; i++)
{
adjacencymatrix[i] = new bool[vertexcount];
for (int j = 0; j<vertexcount; j++)
adjacencymatrix[i][j] = false;
}
Apart from your code sample being incomplete and you not really formulating a question....
Your constructor is defined as graph(int vertexcount); yet your implementation uses different parameters: graph(char filename[], int vertexcount).
You have 2 possibilities depending on what you are tryin to achieve:
1) You can change the definition in your class to graph(char filename[], int vertexcount)
2) You can change your implementation to read like this:#
graph::graph(int vertexcount)
{
this->vertexcount = vertexcount;
adjacencymatrix = new bool*[vertexcount];
for (int i = 0; i<vertexcount; i++)
{
adjacencymatrix[i] = new bool[vertexcount];
for (int j = 0; j<vertexcount; j++)
adjacencymatrix[i][j] = false;
}
}
In case you need filename: I would recommend to use const std::string& as parameter type - or at least const char*...
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) { ... }
My code is trying to implement the union-find algorithm and I have the id[] array and the sz[] array. I initialize them in the Union-Find constructor, but once I try to use those arrays in the methods within the Union-Find class, it changes all the array values to 1. I don't understand why. Is there something obvious that I'm missing??
H File
class UnionFind{
public:
UnionFind(int size);
void join(int x, int y);
int connected(int x, int y);
int find(int x);
private:
int size;
int id[];
int sz[];
};
CPP File
UnionFind::UnionFind(int size){
this->id[size] = id[size];
for(int i = 0; i < size; i++){
id[i] = i;
}
for(int i = 0; i < size; i++){
sz[i] = 1;
}
}
int UnionFind::find(int l){
//Path Compression Finding the Root
for(int i = 0; i < 5; i++){
}
while(l != id[l]){
id[l] = id[id[l]];
l = id[l];
}
return l;
}
void UnionFind::join(int x, int y){
int m = find(x);
int n = find(y);
if(sz[m] < sz[n]){
id[m] = n;
sz[n] += sz[m];
}
else{
id[n] = m;
sz[m] += sz[n];
}
}
int UnionFind::connected(int x, int y){
if(find(x) == find(y)){
return 1;
}
else{
return 0;
}
}
From the comments.
you can't have int id[] as a class member,
use std::vector (resize and fill in constructor),
your forgot to set member size in constructor,
your find algorithm uses path halving not path compression (this does not affect the running time).
Side note: you can use a single array/vector to implement your disjoint set data structure.
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()).