Updating a variable in a struct - c++

So I just created a struct that makes a rectangle. the struct itself look likes this
struct _rect
{
//bottom left vertex
int x = 0;
int y = 0;
// width and height
int width = 0;
int height = 0;
//top right vertex
int y2 = y + height;
int x2 = x + width;
};
//init rect
_rect rect01;
rect01.x = rect01.y = 50;
rect01.width = rect01.height = 200;
in the main cpp when I want to create an instance of it I just want to enter bottom left x and y, plus width and height and I want it to calculate top right vertex by itself, is there a way to assign x2 and y2 their values without manuly doing so ?

You should create a specific class:
class Rect
{
public:
Rect(int x, int y, unsigned int width, unsigned int height)
: m_x(x), m_y(y), m_width(width), m_height(height)
{}
int x() { return m_x; }
int y() { return m_y; }
int top() { return m_y + m_height; }
int right() { return m_x + m_width; }
private:
int m_x;
int m_y;
unsigned int m_width;
unsigned int m_height;
};
That give you the possibility to do the computation you need in the class methods.
You can also create setters and more getters if you want.

Below is the complete working example:
#include <iostream>
class Rect
{
public:
//parameterized constructor
Rect(int px, int py, unsigned int pwidth, unsigned int pheight): x(px), y(py), width(pwidth), height(pheight), x2(x + width), y2(y + height)
{
};
//getter so that we can get the value of x2
int getX2()
{
return x2;
}
//getter so that we can get the value of y2
int getY2()
{
return y2;
}
private:
int x = 0;
int y = 0;
unsigned int width = 0;
unsigned int height = 0;
int x2 = 0, y2 = 0;
};
int main()
{
//create Rect instance
Rect r(50, 50, 200, 200);
//lets check if x2 and y2 were calculate correctly
std::cout<<"x2 is: "<< r.getX2()<<std::endl;
std::cout<<"y2 is: "<< r.getY2()<<std::endl;
}
The output of the above program can be seen here.

Related

Dynamically create a Three-Dimensional array OR a Two-Dimensional Array in C++

I'm currently trying to make a program that will generate a maze to be exported to a game. This program will take user input to set some properties of the maze. I want one of the options to be if the maze will have only two dimensions (a single floor), or three (two or more floors). To achieve that, I'm dynamically allocating an array int the Maze class like so:
In Maze.hpp:
class Maze {
private:
unsigned int width_, length_, height_;
Cell*** matrix = nullptr;
};
In Maze.cpp:
Maze::Maze() { // Default constructor
width_ = 20;
length_ = 20;
height_ = 0;
matrix = new Cell**[width_];
for (unsigned int x {}; x < width_; ++x) {
matrix[x] = new Cell*[length_];
for (unsigned int y {}; y < length_; ++y) {
matrix[x][y] = new Cell(x, y);
}
}
}
Maze::Maze(int width, int length) { // 2D maze constructor
width_ = width;
length_ = length;
height_ = 0;
matrix = new Cell**[width_];
for (unsigned int x {}; x < width_; ++x) {
matrix[x] = new Cell*[length_];
for (unsigned int y {}; y < length_; ++y) {
matrix[x][y] = new Cell(x, y);
}
}
}
Maze::Maze(int width, int length, int height) { // 3D maze constructor
width_ = width;
length_ = length;
height_ = height;
matrix = new Cell**[width_];
for (unsigned int x {}; x < width_; ++x) {
matrix[x] = new Cell*[length_];
for (unsigned int y {}; y < length_; ++y) {
matrix[x][y] = new Cell[height];
for (unsigned int z {}; z < height_; ++z) {
matrix[x][y][z] = Cell(x, y, z);
}
}
}
}
But as you can see, if I use two dimensions, I end up with a pointer for every individual cell in the maze, meanwhile, with three dimensions I end up with a cell object. I would prefer if in both cases I could have a cell object, but I don't know how to achieve that.
Is there a way to do this? Or is this the only option I have?
As asked, here is the declaration of Cell:
Cell.hpp:
class Cell {
private:
unsigned int xPos_, yPos_, zPos_;
public:
Cell(unsigned int xPos, unsigned int yPos);
Cell(unsigned int xPos, unsigned int yPos, unsigned int zPos);
Cell();
};
Cell.cpp:
Cell::Cell(unsigned int xPos, unsigned int yPos) {
xPos_ = xPos;
yPos_ = yPos;
}
Cell::Cell(unsigned int xPos, unsigned int yPos, unsigned int zPos) {
xPos_ = xPos;
yPos_ = yPos;
zPos_ = zPos;
}
As suggested in the comments of the question, I'll change to std::vector instead of using triple pointers.
Also, as a 2D array is simply a 3D array with only one value in the third dimension, I will just change the code to that. (This was also suggested in the comments)
I'll update this answer with the new code when I'm done with it.
UPDATE:
Here's what the final code looks like:
Cell.hpp:
class Cell {
private:
unsigned xPos_, yPos_, zPos_;
public:
Cell(unsigned xPos, unsigned yPos, unsigned zPos);
Cell();
};
Cell.cpp:
Cell::Cell(unsigned xPos, unsigned yPos, unsigned zPos) {
xPos_ = xPos;
yPos_ = yPos;
zPos_ = zPos;
}
Maze.hpp:
class Maze {
private:
unsigned width_, length_, height_;
std::vector<std::vector<std::vector<Cell>>> matrix;
void generateMatrix();
public:
Maze();
Maze(unsigned width, unsigned length);
Maze(unsigned width, unsigned length, unsigned height);
};
Maze.cpp:
Maze::Maze() { // Default constructor
width_ = 20;
length_ = 20;
height_ = 1;
Maze::generateMatrix();
}
Maze::Maze(unsigned width, unsigned length) { // 2D maze constructor
width_ = width;
length_ = length;
height_ = 1;
Maze::generateMatrix();
}
Maze::Maze(unsigned width, unsigned length, unsigned height) { // 3D maze constructor
width_ = width;
length_ = length;
height_ = height;
Maze::generateMatrix();
}
void Maze::generateMatrix() {
for (unsigned x {}; x < width_; ++x) {
matrix.push_back(std::vector<std::vector<Cell>>());
for (unsigned y {}; y < length_; ++y) {
matrix.at(x).push_back(std::vector<Cell>());
for (unsigned z {}; z < height_; ++z) {
matrix.at(x).at(y).push_back(Cell(x,y,z));
}
}
}
}

Calculating distance between to points of a triangle using pointers

I'm writing a program, where you input triangle point coordinates, the program checks if the triangle exists and outputs the area of the triangle. I have to use pointers in the program.
class Vertex
{
private:
int x, y;
public:
Vertex(int x, int y) : x(x), y(y) {}
int getX() {
return x;
}
int getY() {
return y;
}
float getDistance(Vertex *anotherVertex)
{
float dist;
int tempx = 0, tempy = 0;
tempx = anotherVertex->getX();
tempy = anotherVertex->getY();
dist = ((tempx - x) * (tempx - x) + (tempy - y) * (tempy - y));
return dist;
}
void setCoord(int x, int y)
{
this->x = x;
this->y = y;
}
};
class Triangle
{
private:
Vertex *a, *b, *c;
public:
Triangle()
{
a = new Vertex(0, 0);
b = new Vertex(0, 0);
c = new Vertex(0, 0);
}
void Set_coord()
{
int x1, y1, x2, y2, x3, y3;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
a->setCoord(x1, y1);
b->setCoord(x2, y2);
c->setCoord(x3, y3);
}
bool existTriangle() {
float ab = a->getDistance(b);
float bc = b->getDistance(c);
float ca = c->getDistance(a);
if (ab + bc > ca && ab + ca > bc && bc + ca > ab) {
return true;
}
else {
return false;
}
}
float getArea() {
float p;
float ab = a->getDistance(b);
float bc = b->getDistance(c);
float ca = c->getDistance(a);
p = (ab + bc + ca) / 2;
return sqrt(p * ((p - ab)*(p - bc)*(p - ca)));
}
};
I'm struggling to make the getDistance function working as I'm inexperienced with using pointers, when debugging i'm getting this error in the getX() function.
Exception thrown: read access violation.
this was 0xDDDDDDDD.
EDIT:
here is my main()
int main() {
int n = 0;
cin >> n;
vector<Triangle*> vertices;
for (int i = 0; i < n; i++) {
Triangle* newVertices = new Triangle();
newVertices->Set_coord();
vertices.push_back(newVertices);
delete newVertices;
}
for (int i = 0; i < n; i++)
{
if (vertices[i]->existTriangle())
{
cout << vertices[i]->getArea();
}
}
}
The problem is in your main function ( that's why I asked you to post it:) ):
Triangle* newVertices = new Triangle();
vertices.push_back(newVertices);
delete newVertices;
You dynamically allocate memory, that is pointed to by newVertices.
You store the pointer into the vector.
You delete the memory pointed by newVertices.
As a result, now that pointer is a dangling pointer.
So, you must not delete newVertices into the loop.
Do your thing (computer areas, check it a triangle exists, etc.), and then, when you are done, start deleting your dynamically allocating memory...

C++ const array change without reason

I have a problem with a piece of code. I'll provide you a simplified version :
class AdvancedImage
{
Image *_source;
int _w;
int _h;
AdvancedImage(const Image *src, const PointFloat corners[], int w, int h)
{
InitializeInstanceFields();
_source = new Image(src->data, src->h, src->w);
_w = w;
_h = h;
PointFloat newPoints[4];
for (int i = 0; i < 4; i++)
{
newPoints[i] = corners[i];
}
/* Initialisation continue... */
}
InitializeInstanceFields()
{
_w = 0;
_h = 0;
}
}
class Image
{
unsigned char *data;
int width;
int height;
int size;
Image(const unsigned char newData[], int h, int w)
{
InitializeInstanceFields();
this->height = h;
this->width = w;
this->size = h * w;
this->data = new unsigned char[this->size];
for (int i = 0; i < this->size; i++)
{
this->data[i] = newData[i];
}
}
}
class PointFloat
{
float X;
float Y;
PointFloat(float x, float y)
{
this->X = x;
this->Y = y;
}
}
And I'm using the AdvancedImage like this :
void myFunction (const Image *img, const PointFloat corners[])
{
AdvancedImage *advImg = 0;
/* Some code */
advImg = new AdvancedImage(img, corners, 15, 30);
/* Code continue */
}
My problem is that the values in corners change after doing the new AdvancedImage. I try to debug, and I saw something I can't explain. In constructor AdvancedImage, corners[0] is {76.0, 45.0}. I added a watch to &corners, in constructor new Image values don't change, but when code return from constructor (goes to line _w = w;) values are now something like {7.7877970e40, 0.2554460e-20}.
I've looked for a solution but nothing do. How can I solve this problem ? Where can it come from ?

segmentation fault setting private data

I have a 7 x 7 matrix of probes that deliver a signal representing the level measured at that point in the area under investigation. Each element of the matrix is a cpp (g++) class and I get segmentation fault when I try to set private data element rect.x an element of SDL_Rect to a value.
class Probe
{
public:
Probe();
~Probe();
void SetColor(int x);
void Set_id(int x, int y, int z);
void Level_id(void);
private:
int OldColor;
int Xcord;
int Ycord;
SDL_Rect rect;
};
//When I access rec using the public functions, rect.x returns 0
//and setting it to a value give a segment fault at run time.
//ie.
rect.x = Xcord; //segment fault
foo = rect.x; // returns 0, the starting value I suppose.
//My workround is to create a rect locally in each public function
SDL_Rect rect = {BLOCK_W * Xcord, BLOCK_H * Ycord, BLOCK_W, BLOCK_H};
//and it is like I think it should be. So I'm not stuck. Ian
//More details
//#include etc
Probe Level[7][7]; //49 instances of the class
void Probe::Set_id(int x, int y, int z)
{
Xcord = x;
//Segment fault
Ycord = y;
OldColor = z;
// Defininlg rectangles
SDL_Rect rect = {BLOCK_W * Xcord, BLOCK_H * Ycord, BLOCK_W, BLOCK_H};
// rect.x = BLOCK_W * Xcord; //Segment fault
// rect.y = BLOCK_H * Ycord;
SDL_SetRenderDrawColor( ren, OldColor, 0, 0, 255 );
SDL_RenderFillRect( ren, &rect );
// if (0 != SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, OldColor, 0, 0)));
// { std::cout << "SDL_FillRect failed in Set_id" << std::endl; }
}
void SDL_init()
{
int x, y, z;
z = 10;
for(y = 0; y <= 7; ++y)
{
for(x = 0; x <= 7; ++x)
{
z += 25;
Level[x][y].Set_id(x, y, z);
}
}
for(y = 0; y < 7; ++y)
{
for(x = 0; x < 7; ++x)
{ Level[x][y].Level_id(); }
}
}
void MouthPad() {
std::cout << "In MouthPad" << std::endl;
//Start up SDL and create window
if( !init() )
{ printf( "Failed to initialize!\n" ); }
else
{
SDL_init(); //Get the class going.
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//etc I hope this helps. Ian.

Need help on getArea() function

I'm trying to calculate the area of the circle and the rectangle by using the existing data (radius ,width, and height). But i have some errors, i hope you can help me fix it.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Shape
{
public:
virtual void Draw () = 0;
virtual void MoveTo (int newx, int newy) = 0;
virtual int GetArea()const = 0;
};
class Rectangle : public Shape
{
public:
Rectangle (int x, int y, int w, int h);
virtual void Draw ();
virtual void MoveTo (int newx, int newy);
int GetArea() {return height * width;}
private:
int x, y;
int width;
int height;
};
void Rectangle::Draw ()
{
cout << "Drawing a Rectangle at (" << x << "," << y
<< "), width " << width << ", height " << height << "\n";
};
void Rectangle::MoveTo (int newx, int newy)
{
x = newx;
y = newy;
}
Rectangle::Rectangle (int initx, int inity, int initw, int inith)
{
x = initx;
y = inity;
width = initw;
height = inith;
}
class Circle : public Shape
{
public:
Circle (int initx, int inity, int initr);
virtual void Draw ();
virtual void MoveTo (int newx, int newy);
int GetArea() {return 3.14 * radius * radius;}
private:
int x, y;
int radius;
};
void Circle::Draw ()
{
cout << "Drawing a Circle at (" << x << "," << y
<< "), radius " << radius <<"\n";
}
void Circle::MoveTo (int newx, int newy)
{
x = newx;
y = newy;
}
Circle::Circle (int initx, int inity, int initr)
{
x = initx;
y = inity;
radius = initr;
}
int main ()
{
Shape * shapes[2];
shapes[0] = new Rectangle (10, 20, 5, 6);
shapes[1] = new Circle (15, 25, 8);
for (int i=0; i<2; ++i) {
shapes[i]->Draw();
shapes[i]->GetArea();
}
return 0;
}
Rectangle::GetArea method should be const. You declared it non-const, so it is not considered an override of Shape::GetArea, so Rectangle is considered abstract.
You may want to rethink your return type too.
int Circle::GetArea() {return 3.14 * radius * radius;}
As pointed by #Cătălin Pitiș, the GetArea() methods in derived classes need to be const. Otherwise compiler will complain that you have not provided the implementation for pure virtual functions (hence the derived classes become abstract) and will not allow you to create objects of the. Additionally, you need to declare a virtual destructor for Shape class. Otherwise, you will not be able release the memory properly. Also, you are not releasing the memory in main() function. You should use delete to release the memory allocated for the objects.