Getting and setting a three dimensional array - c++

I have to get a three dimensional array c[] w[] h[] from a class and convert it into a single dimensional array of unsigned char[]. I tried this way. But it doesnt work !!.. When I give the input through command line the execution halts and breaks...
Implementation:
#include <iostream>
#include<fstream>
#include<stdlib.h>
#include<vector>
//#include "E:\Marvin_To_UnsignedChar\MetisImg.hpp"
//#include "C:\Users\padmanab\Documents\Visual Studio 2013\Projects\Marvin_To_UnsignedChar\MetisImg.hpp"
extern "C"
{
#include "C:\Users\padmanab\Desktop\Marvin_To_UnsignedChar\multiplyImage\multiplyImage.h"
//#include "C:\Users\padmanab\Documents\Visual Studio 2013\Projects\Marvin_To_UnsignedChar\multiplyImage\multiplyImage.h"
}
using namespace std;
class Marvin_To_UnsignedChar
{
public:
int Color;
int Width;
int Height;
std::vector<unsigned char> values;
Marvin_To_UnsignedChar(int c, int w, int h) : Color(c), Width(w), Height(h), values(c*w*h){}
unsigned char operator()(int color, int width, int height) const
{
return values[Height*Width*color + Height*width + height];
}
unsigned char& operator()(int color, int width, int height)
{
return values[Height*Width*color + Height*width + height];
}
};
In Main():
int color; int width; int height;
std::cout << "Please enter the color value";
std::cin >> color;
std::cout << "Please enter the width value";
std::cin >> width;
std::cout << "Please enter the height value";
std::cin >> height;
Marvin_To_UnsignedChar M_To_V(color,width,height);
unsigned char test = M_To_V(color, width, height);
std::cout << test << '\n';
It would be great to have some guidance about the issue or may be a better method to implement it !

The class code is fine. The problem is that in
unsigned char test = M_To_V(color, width, height);
you are invoking the operator() with the dimensions as parameters (remember that you used before color, width, height to construct the Marvin_To_UnsignedChar object), so it will effectively output values[Color*Width*Height], which is one element past the end of the vector. Otherwise the code is fine, you probably want to use something like
unsigned char test = M_To_V(x, y, z);
where x, y, z are such that x<color, y<width, z<height.
For example, the code below works (I am initializing in the constructor the array with 'x' so you can see that something is printed out)
#include <iostream>
#include <vector>
using namespace std;
class Marvin_To_UnsignedChar
{
public:
int Color;
int Width;
int Height;
std::vector<unsigned char> values;
Marvin_To_UnsignedChar(int c, int w, int h) :
Color(c), Width(w), Height(h), values(c*w*h,'x'){}
unsigned char operator()(int color, int width, int height) const
{
return values.at(Height*Width*color + Height*width + height);
}
unsigned char& operator()(int color, int width, int height)
{
return values.at(Height*Width*color + Height*width + height);
}
};
int main()
{
int color = 3, width = 777, height = 600;
Marvin_To_UnsignedChar M_To_V(color,width,height);
M_To_V(2, 776, 599)='a'; // set the last element to `a`
std::cout << M_To_V(2, 776, 599) << '\n';
unsigned char test = M_To_V(1, 200, 300); // this element is pre-initialized with 'x'
std::cout << test << '\n';
}
PS: you can use values.at(position) instead of values[position] for a std::vector, and the former will check for out of bounds, i.e. throw an exception if you get an out of bound, so you can figure out what's going on. The values[position] form is faster, but I recommend using at at least in debug mode if you are not 100% sure that you may overflow.

Related

Crash while accessing specific index of vector in class

I am currently trying to make a 2d vector representing pixels.
The problem is that when I try to set a value at a specific index the program crash.
The compilation is good.
Here is the .h :
#include "../include/graphics.h"
#include <stdlib.h>
#include <stdio.h>
#include <functional>
#include <vector>
#include <string>
using namespace rgb_matrix;
class Viewport
{
public:
Viewport(std::string id,int xMn,int yMn,int xMx,int yMx,Canvas *c)
{
canvas_=c;
_id = id;
_x = xMn;
_y = yMn;
width=xMx-xMn;
height=yMx-yMn;
}
void SetPixel(int x_vport,int y_vport,rgb_matrix::Color c);
int getXMax(){
return _x + height;
}
int getHeight(){
return height;
}
int getWidth(){
return width;
}
int getX(){
return _x;
}
void clear();
std::string getId(){return _id;}
void show();
void fill(int r,int g,int b);
private :
Canvas *canvas_;
int width,height;
int _x,_y;
std::string _id;
std::vector<std::vector<rgb_matrix::Color> > colors;
};
The weird point is that I can access to the values into the .h but not into the .cpp :
void Viewport::SetPixel(int x, int y, rgb_matrix::Color c) {
if(x>=0 && y>= 0 && x< width && y < height) {//if in rectangle
colors.at(x).at(y) = c;
}
}
This is not how you fill values in the vector:
void Viewport::SetPixel(int x, int y, rgb_matrix::Color c) {
if(x>=0 && y>= 0 && x< width && y < height) {//if in rectangle
colors.at(x).at(y) = c;
}
}
Before you visit an element of the vector colors.at(x) you must assure that the size of the vector colors.size() is bigger than x. So, maybe you call colors.resize() somewhere in other place, before filling vector with values.
The crash is intended, that's an exception thrown due to the out-of-bounds access.
I would question the choice of the data structure:
std::vector<rgb_matrix::Color> can be chosen if you need the continuous block of memory (just remember to either resize it or construct it with width*height parameter =)
vector of vectors implies a dense nonrectangular structure - normally it's used for something like triangle matrices to save the memory.
using x = unsigned; using y = unsigned;vector::<std::tuple<x, y, rgb::matrix::Color> can be used for a sparse structure with a few pixels in random places.
Also x>=0 && y>= 0 can be avoided if you switch to unsigned instead of int=)

How to switch to a dynamic array?

I'm trying to set the size of an array to an input received by the program, currently the size of the array is defined as a const static int.
Board.h
#include <iostream>
using namespace std;
class Board {
private:
const static int BOARDSIZE = 5;
char board[BOARDSIZE][BOARDSIZE];
const char p1Symbol = 'R';
const char p2Symbol = 'B';
const char trail = 'O';
const char crash = '*';
int p1Row;
int p1Col;
int p2Row;
int p2Col;
public:
void setBoardSize(int size);
bool isValidMove(int row, int col);
bool isValidInput(char input);
bool getNextMove();
void initializeArray();
void drawHorizontalSeparator();
void drawSeparatedValues(int row);
void displayBoard();
};
Main
#include <iostream>
#include "Board.h"
using namespace std;
int main() {
int size;
cout << "Enter and integer between 4 and 20 for the BoardSize: " << endl;
cin >> size;
Board b;
b.setBoardSize(size);
b.initializeArray();
b.displayBoard();
bool done = false;
while (!done) {
done = b.getNextMove();
}
return 0;
}
I'm trying to use this function called setBoardSize to change the size of the board in the Board.H file. I've tried removing const static but then I get all sorts of errors. Apparently it isn't possible to define an array that doesn't have a predefined size?
Instead of char board[BOARDSIZE][BOARDSIZE] go for std::vector<char>(BOARDSIZE * BOARDSIZE, 0) and access elements as vector[y * BOARDSIZE + x] where x and y run within <0, BOARDSIZE).
You would resize simply as vector.resize(size * size).

How to access class variable inside a vector iterator?

I'd like to access a public variable of a class instance, where the instances are kept in a vector of the class type. I have to run through all elements of vector using an iterator, but it confuses me as to how I get the variables with the iterator present. I'm using C++98.
source.cpp:
#include <iostream>
#include <vector>
#include "Rectangle.h"
using namespace std;
int main() {
int len = 2, hen = 5;
int len2 = 4, hen2 = 10;
Rectangle rect1(len, hen);
Rectangle rect2(len2, hen2);
vector<Rectangle> Rects;
Rects.push_back(rect1);
Rects.push_back(rect2);
for (std::vector<Rectangle>::iterator it = Rects.begin(); it != Rects.end(); ++it) {
//how to access length and height here?
}
system("pause");
return 0;
}
Rectangle.h:
#pragma once
class Rectangle
{
private:
public:
int length;
int height;
Rectangle(int& length, int& height);
~Rectangle();
};
Rectangle.cpp:
#include "Rectangle.h"
Rectangle::Rectangle(int& length, int& height)
: length(length), height(height)
{ }
Rectangle::~Rectangle() {}
Add the rectangle to vector first, dereference iterator and access the elements.
int main() {
int len = 2, hen = 5;
int len2 = 4, hen2 = 10;
Rectangle rect1(len, hen);
Rectangle rect2(len2, hen2);
vector<Rectangle> Rects;
Rects.push_back(rect1);
Rects.push_back(rect2);
for (std::vector<Rectangle>::iterator it = Rects.begin(); it != Rects.end(); ++it) {
std::cout << "length " <<(*it).length<<std::endl;
std::cout << "height " <<(*it).height<<std::endl;
}
system("pause");
return 0;
}

Error when resizing vector of object

I am trying to create a vector of objects but i have some issues. I can't push_back over 19 objects to my vector because it shows up an error message of bad_alloc.
I try to resize my vector with resize() or reserve() but still nothing.
For resize(), I read that you need to provide 2 arguments to resize a vector.But still nothing.
When I try to use it without push_back it shows error: expected primary-expression before ')' token.
#define N 10 //ari8mos seirwn tou xarth
#define M 10 //ari8mos sthlwn tou xarth
#define TREAS 100//posothta 8usaurou
#define PORTS 100//ari8mos limaniwn
extern void ships(map (&myArray)[N][M], vector<ship> &myShips);
void ships(map (&myArray)[N][M], vector<ship> &myShips)
{
int i,j,y;
srand ( time(NULL) );
//myShips.reserve(21);
//myShips.resize(20,ship);
cout << myShips.capacity() << endl;
int x=0;
for( i = 0; i <19 ; i++){
myShips.push_back(pirate(rand() % N,rand() % M,100,100,100,1,'#',myArray,myShips));
}
for( i=0;i<myShips.size();i++ ){
cout << myShips[i].get_symbol() << " ";
}
}
here is the rest of code to help you understand:
class ship
{
protected:
int i,j,x2,y2;
//vector<vector<map> > myArray;
//ship (&myShips)[N][M];
int x;
int y;
map (myArray)[N][M];
vector<ship> myShips;
int max_resistance;
int current_resistance;
int speed;
int reserve_treasure;
char symbol;
public:
ship(int x_, int y_, int max_res, int cur_res, int res_treas, int sp, char sy, map (&myArr)[N] [M], vector<ship> &Ship)
:x(x_)
,y(y_)
,max_resistance(max_res)
,current_resistance(cur_res)
,reserve_treasure(res_treas)
,speed(sp)
,symbol(sy)
,myArray(myArr)
,myShips(Ship)
{cout << "eimai o 'ship' 2" << endl; }
~ship() {}
int get_x();
int get_y();
float get_max_resistance();
float get_current_resistance();
int get_speed();
float get_reserve_treasure();
char get_symbol();
void set_x(int pos_x);
void set_y(int pos_y);
void set_max_resistance(float maxres);
void set_current_resistance(float curres);
void set_speed(int sp);
void set_reserve_treasure(float restrea);
void set_symbol(char sy);
void movement();
void operation();
};
int ship::get_x(){
return x;
}
int ship::get_y(){
return y;
}
float ship::get_max_resistance(){
return max_resistance;
}
float ship::get_current_resistance(){
return current_resistance;
}
int ship::get_speed(){
return speed;
}
float ship::get_reserve_treasure(){
return reserve_treasure;
}
char ship::get_symbol(){
return symbol;
}
void ship::set_x(int pos_x){
x = pos_x;
}
void ship::set_y(int pos_y){
y = pos_y;
}
void ship::set_max_resistance(float maxres){
max_resistance = maxres;
}
void ship::set_speed(int sp){
speed = sp;
}
void ship::set_current_resistance(float curres){
current_resistance = curres;
}
void ship::set_reserve_treasure(float restrea){
reserve_treasure = restrea;
}
void ship::set_symbol(char sy){
symbol = sy;
}
class pirate : public ship
{
public:
pirate(int posx, int posy, float mr, float cr, float rt, int spe, char sym, map (&Array)[N] [M],vector<ship> &Ship ):ship(posx,posy,mr,cr,rt,spe,sym,Array,Ship){
cout << "eimai o 'pirate' 1" << endl;
// ship(90,90,1,50,'#',Array,Ship) {//vector<vector<map> > Array, vector<vector<ship> > Ship) {}
};
Hope you can help
Looking through this code, did you create a custom definition for map? Otherwise, if you are trying to create an [N][M] array of Map objects, you are missing the type declaration of map. e.g. map<int,string>
If you are trying to use map as a multidimensional array, this is not what std::map is for. Map is a generic container for storing key/value pairs.

For-Loop Segmentation -- Excessive run ( i < SIZE, but i = SIZE)

This is a function in a program replicating Sierpinski's gasket. This function is supposed to attach the points in the triangle for the fractal.
After much deliberation I've figured out where the issue lies:
void add_pts(int &x, int &y)
{
Vector_ref<Rectangle> pt;
for (int i = 0; i < POINTS; ++i)
{
pt_test; //generates changing x, y vals within the limits of the triangle
cout << "pass" << i <<endl;
pt.push_back(new Rectangle(Point(x,y),5,5));
pt[i].set_fill_color(Color::yellow);
win.attach(pt[i]);
}
}
The output is "pass1...pass[POINTS-1]", but for whatever reason it runs when i = POINTS and runs into the segmentation error. I have no clue as to why. Can anyone assist, please?
Here is my code. The pt_test and coord are a bit sloppy but seeing as it can't run properly it's very hard to ascertain what I can streamline.
#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <time.h>
#include "Simple_window.h"
#include "Graph.h"
#include "Point.h"
#include "GUI.h"
#include "Window.h"
using namespace std;
using namespace Graph_lib;
// globals
const int POINTS = 5000;
unsigned int seed = (unsigned int)time(0);
Simple_window win(Point(100,100),1100,700,"Homework 9");
// function declarations
double random(unsigned int &seed);
bool coords(int &x, int &y);
void pt_test(int x, int y);
void add_pts(int &x, int &y);
int main()
{
int x, y;
// title
Text title(Point(400,50), "The Sierpinski Gasket");
title.set_font(Graph_lib::Font::helvetica_bold);
title.set_font_size(25);
title.set_color(Color::cyan);
win.attach(title);
// triangle
Closed_polyline tri;
tri.add(Point(250,75)); // A
tri.add(Point(850,75)); // B
tri.add(Point(550,675)); // C
tri.set_fill_color(Color::white);
tri.set_color(Color::dark_red);
tri.set_style(Line_style(Line_style::solid,3));
win.attach(tri);
// vertices
Text vert_a(Point(225,70), "A (250, 75)");
vert_a.set_font(Graph_lib::Font::helvetica_bold);
vert_a.set_font_size(15);
vert_a.set_color(Color::cyan);
Text vert_b(Point(855,70), "B (850, 75)");
vert_b.set_font(Graph_lib::Font::helvetica_bold);
vert_b.set_font_size(15);
vert_b.set_color(Color::cyan);
Text vert_c(Point(575,670), "C (550, 675)");
vert_c.set_font(Graph_lib::Font::helvetica_bold);
vert_c.set_font_size(15);
vert_c.set_color(Color::cyan);
win.attach(vert_a);
win.attach(vert_b);
win.attach(vert_c);
// point selection
add_pts(x, y);
// window title and display
win.wait_for_button();
}
double random(unsigned int &seed)
{
const int MODULUS = 15749;
const int MULTIPLIER = 69069;
const int INCREMENT = 1;
seed = ((MULTIPLIER*seed)+INCREMENT)%MODULUS;
return double(seed)/double(MODULUS);
}
bool coords(int &x, int &y) // generates the points
{
x = int(251 + 600*random(seed));
y = int(76 + 600*random(seed));
if( y > (2*x-425) && x<= 550 || x>=550 && y < (-2*x + 1775))
return true;
}
void pt_test(int x, int y) // tests the points until they are within the range
{
coords;
while(coords == 0)
coords;
}
void add_pts(int &x, int &y) // attaches the points as shapes
{
Vector_ref<Rectangle> pt;
for (int i = 0; i < POINTS; ++i)
{
pt_test;
cout << "i == " << i << " points == " << POINTS << endl;
pt.push_back(new Rectangle(Point(x,y),5,5));
pt[i].set_fill_color(Color::yellow);
win.attach(pt[i]);
}
}
I've also noticed that the function add_pts doesn't work when the body is in the loop, but if you put the body in int_main(), it runs indefinitely but doesn't reach the segmentation fault as quickly, if at all.