Setting-up a 2D array using std::Vector - c++

I have already improved my array from this question in order to be created within a class, I also kind of optimized it using std::vector so it is not allocated on a heap but on a stack and thus it is faster and also I do not have to manage the memory manually.
But I was not able to create a function which would set a value to an element. I got errors like expression must have pointer-to-object type (when I try to declare my element as int cell or an array may not have element of this type (when I try to declare it as int cell[][]) and I get a segmentation error when I try to declare it like this int *cell[].
Here is my code
.hpp
#pragma once
#include <iostream>
#include <vector>
class myPlan
{
int slots;
int rows = 3;
int cell[][];
public:
myPlan(int slots);
void setCellValue(int row, int slot, int value)
};
.cpp
#include "myPlan.hpp"
myPlan::myPlan(int slots)
{
this->slots = slots;
std::vector<std::vector<int> > cell(STATUS_N);
for (int i = 0; i < STATUS_N; i++)
{
// declare the i-th row to size of column
cell[i] = std::vector<int>(slots);
}
//Print the array
for (int i = 0; i < STATUS_N; i++) {
for (int j = 0; j < cell[i].size(); j++)
{
cell[i][j] = 0;
std::cout << cell[i][j] << " ";
}
std::cout << "\n";
}
}
void myPlan::setCellValue(int row, int slot, int value)
{
cell[row][slot] = value;
}
main.cpp
#include "myPlan.hpp"
int main()
{
myPlan plan(N_PLAN);
plan.setCellValue(0,2,42);
}
Thank you very much in advance for any help
P.S. I hope that this is more optimal than this array, if there was even better optimized version, I would be glad to learn about it.

So here's what I think is the fundamental problem, it has nothing to do with arrays or vectors. You are just handling your class variable incorrectly. Here's your class
class myPlan
{
int slots;
int rows = 3;
int cell[][];
int cell[][]; is not legal C++, but we'll let that pass. The point is that you have some kind of 2D array called cell in your class.
Now here's your constructor
myPlan::myPlan(int slots)
{
this->slots = slots;
std::vector<std::vector<int> > cell(STATUS_N);
for (int i = 0; i < STATUS_N; i++)
{
// declare the i-th row to size of column
cell[i] = std::vector<int>(slots);
}
Now here you've declared a 2D vector called cell. But (and here's the point) this is not the same cell that's in your class, it a completely separate variable which just happens to have the same name. And like any variable declared inside a function it will no longer exist after the function exits.
Here's how it should be done.
class myPlan
{
int slots;
int rows = 3;
std::vector<std::vector<int> > cell;
...
myPlan::myPlan(int slots)
{
this->slots = slots;
cell.resize(STATUS_N);
for (int i = 0; i < STATUS_N; i++)
{
// declare the i-th row to size of column
cell[i] = std::vector<int>(slots);
}
See the difference? I didn't declare a new cell variable, I just resized the one that is declared in the class.

As far as I understood your problem, you need an array of arrays (a number of slots), which size is known at compile time. And you prefer it to be on the stack.
I encourage you to use std::array and forget about C-style arrays ([] - these guys). Or better learn the difference between them and make your own mind.
There is an example how to use it. The class has to be templated to provide parameters of the array sizes at compile time. It is pretty straighforward, but if you don't need it, you can just remove the template line before the class definition and replace RowNumber and SlotSize with you defines or constants known at compile time.
This solution will only work if sizes are known at compile time. If you want to provide the number of rows as myPlan constructor parameter, then you'll need to dynamically allocate memory and use std::vector or something similar.
#include <iostream>
#include <array>
template<std::size_t RowNumber, std::size_t SlotSize>
class myPlan {
std::array<std::array<int, SlotSize>, RowNumber> cells;
public:
myPlan() :
cells{} // initialize array with zeros
{
//Print the array
for (int i = 0; i < cells.size(); i++) {
for (int j = 0; j < cells[i].size(); j++)
{
std::cout << cells[i][j] << " ";
}
std::cout << "\n";
}
}
void setCellValue(int row, int slot, int value) {
cells[row][slot] = value;
}
};
#define N_PLAN 4
#define STATUS_N 3
int main()
{
myPlan<N_PLAN, STATUS_N> plan;
plan.setCellValue(0,2,42);
}

Related

Merging two sorted array on third by creating a new array on heap

I have a class array inside which I have declared an array its size and length. I am trying to merge two sorted arrays by creating the third array on the heap and both the sorted array will be merged on the third array. But whenever I create a new arr on heap the compiler gives me this error: request for member '..' in '..' which is of non-class type
class Array
{
public:
int A[10];
int length;
int Size;
};
void display(Array arr)
{
int i;
for(i=0;i<arr.length;i++)
{
cout<<arr.A[i]<<" ";
}
}
void Merge(Array *arr1,Array *arr2)
{
int i,j,k;
i=j=k=0;
int *arr3;
arr3=new int[10];
while(i<arr1->length && j<arr2->length)
{
if(arr1->A[i]<arr2->A[j])
arr3->A[k++]=arr1->A[i++];
else
arr3->A[k++]=arr2->A[j++];
}
for(;i<arr1->length;i++)
{
arr3->A[k++]=arr1->A[i];
}
for(;j<arr2->length;j++)
{
arr3->A[k++]=arr1->A[j];
}
}
int main()
{
Array arr1{{1,3,5,7},4,4};
Array arr2{{2,4,6,8},4,4};
Array *arr3;
arr3=Merge(&arr1,&arr2);
display(*arr3);
return 0;
}
The root cause of all your problems is that you use C-Style array with a magical size 10. Like in int A[10];. This is a major problem and should be avoided in C++.
Additionally, and the same, In C++ we usually do not use raw pointer for owned memories or newand such stuff.
Anyway. The design will never work, if the number of elements in both Array classes is greater then 5. Because then you will definitely get an out of bounds problem.
You must use a std::vector.
So, all bad. But I know that I will hear now, that the teacher said, no vector but new. The teacher should be fired or begin to teach C instead of C++.
Anyway again, I will fix the major bugs for you. But the sorting algorithm will work neither.
So,
If you want to return an Array, then change the signature of your function aand return an Array.
You do want to have a new Array, not new intes. So, please allocate a new Array instead.
Do not forget to release the newed Arrary at then end.
Set size and length of the new array.
Refactor your complete code.
Code example with some fixes:
#include <iostream>
class Array
{
public:
int A[10];
int length;
int Size;
};
void display(Array arr)
{
int i;
for (i = 0; i < arr.length; i++)
{
std::cout << arr.A[i] << " ";
}
}
Array* Merge(Array* arr1, Array* arr2)
{
int i, j, k;
i = j = k = 0;
Array *arr3 = new Array;
while (i < arr1->length && j < arr2->length)
{
if (arr1->A[i] < arr2->A[j])
arr3->A[k++] = arr1->A[i++];
else
arr3->A[k++] = arr2->A[j++];
}
for (; i < arr1->length; i++)
{
arr3->A[k++] = arr1->A[i];
}
for (; j < arr2->length; j++)
{
arr3->A[k++] = arr1->A[j];
}
arr3->length = arr1->length + arr2->length;
return arr3;
}
int main()
{
Array arr1{ {1,3,5,7},4,4 };
Array arr2{ {2,4,6,8},4,4 };
Array* arr3;
arr3 = Merge(&arr1, &arr2);
display(*arr3);
delete[]arr3;
return 0;
}

Initialization of user-defined array in C++ class?

I'm working on knight's tour problem, and want to define a class, but I am having trouble with initialize an array defined by user. So the user inputs from the command line argvs are the chessboard lengths mX and nY; and a starting position(x,y). So basically, how do I initialize an array that's defined by the user?
First question: In the public part, is it right to declare int ** tour?
Second question: How do I refer to the array tour in the following functions in the same class?
Third question: In main, I called K.knight to initialize an array of dimension specified by the user, but it wasn't initialized. How do I initialize an array in main using the function K.knigt(), and be able to use the array in the following function K.knightfunc()?
class Ktour{
public:
int xSize; //m
int ySize; //n
int ** tour; //array to be initialized
int solutionsCount; //tracking solutions
int position; //position count, from 0 to m * n -1
// initialize tour matrix
void knight(int M, int N) {
position = 1;
solutionsCount = 0;
xSize = M;
ySize = N;
tour = new int * [xSize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++) {
tour[i][j] = 0;
std::cout << tour[i][j] << std::endl;
}
}
}
....some other functions defined in between...
....
....
};
...
// main
int main(int argc, char *argv[])
{
Ktour K;
//user inputs chessboard length mX and nY; and a starting position(x,y)
int mX = atoi(argv[1]);
int nY = atoi(argv[2]);
int x = atoi(argv[3]);
int y = atoi(argv[4]);
//initialization
K.knight(mX, nY);
//run the recursive function;
K.knightFunc(x,y);
return 0;
}
Yeah, it seems more logical to initialize in the ctor. My take on this is you are creating an array of int pointers, and have not yet allocated the ints that are being pointed to.
You have a few possibilities:
If we are to think of a common chessboard, then since the array size is known in advance, and it's not especially big, just create it in the class:
class Ktour{
...
int tour[8][8];
...
}
although some purists might say you should only "new" such arrays. If it is a much larger array, you certainly should.
A more straightforward syntax like what you're trying to do, for handling arrays of unknown size would be:
class Ktour{
...
int **tour=0;
KTour(int M, int N) {
tour = new int * [M];
for (int i=0; i<M; ++i)
tour[i] = new int [N];
};
~KTour() {
for (int i=0; i<M; ++i)
delete [] tour[i];
delete [] tour;
};
...
}
You access it quite simply, with:
std::cout << tour[i][j];
The above kind of coding is error-prone. To reduce your future strife with memory access errors, you really should use STL container classes (or Boost ones, or Qt ones when using Qt, if their size isn't too limited - but you can use STL in Qt also), since they produce an error in debug when you access out-of-bounds subscripts for your arrays, instead of, e.g. overwriting important pointers, etc. Thus, you could use something like:
class Ktour{
...
std::vector < std::vector<int> > Tour;
KTour(int M, int N) {
// tour.resize(M); // not needed.
tour.assign(M, std::vector <int> (N, 0));
};
~KTour() {
// No need to delete
};
...
}
and you access it with
std::cout << tour[i][j];
(Note: The extra lines in the code are some artifact of the <pre> and <code> tags; necessitated by not all of my indented lines being recognized as code.)

How can return a matrix pointer in c++?

I have a big problem, i want to put a matrix pointer of objects to a function but i don't know how can do this, the objects that i use they are from derived class. This is an example of my code. Note: class Piece is a base class and class Queen is a derived class from Piece
#include "Queen.h"
void changeToQueen(Piece* mx)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
mx[i][j] = new Queen();
}
}
}
int main()
{
Piece * matrix[7][7];
changeToQueen(matrix); // this fails
return 0;
}
You can change the input argument to void changeToQueen(Piece * mx[7][7]).
Or you can change the input argument to void changeToQueen(Piece** mx).
Change the assignment operator to mx[7*i + j] = new Queen(); and pass in the first element as input changeToQueen(&(matrix[0][0]));
The reason why both work is because multidimensional array elements are stored contiguously in memory. So all you need is a pointer to the first element.
Both solutions are a bit flawed because if you need to change the dimensions of your matrix, you have to change your code a bit. Changing your prototype to void changeToQueen(Piece** mx, size_t width, size_t height) will be helpful for the future.
Alternatively this could be a way to handle things
template <unsigned int rows, unsigned int columns>
class Board
{
public:
Board() {}
void changeToQueen()
{
for (unsigned int y = 0 ; y < rows ; ++y)
{
for (unsigned int x = 0 ; x < columns ; ++x)
{ _pieces[y][x] = Queen(); }
}
}
Piece &at(unsigned int row, unsigned int column)
{ return _pieces[row][column]; } // you should check for out of range
// you could either have a default null value for Piece to return, or throw an exception
private:
Piece _pieces[rows][columns];
};
int main()
{
Board<8,8> board;
board.changeToQueen();
// return 0; // this is not mandatory in c++
}
So, yeah, no pointers almost no worries ;)
You still want pointers?? uhm... okay maybe you could do that: Piece *_pieces[rows][columns];, i'm not sure you really need it, but I can't tell how much it would modify your existing code to do this.
First of all, I do not understand dependencies between Queen and Piece, so I suppose that Piece is super-type of Queen and assignment Piece * mx = new Queen(); is correct.
To fix the obvious problem of type mismatch you can change your
void changeToQueen(Piece* mx)
to
void changeToQueen(Piece* mx[7][7])
and with changing loops border to 7 (for (int i = 0; i < 7; i++)) or size of matrix to 8 x 8 (with the same loops) this will work.
But my suggestion is to think over method of storing data.
Perhaps you will need to build matrix of size different from 7x7, so consider the following example, where dynamic memory is used to store the matrix (in this example only Queen is used):
void changeToQueen(Queen*** &mx, int size)
{
mx = new Queen**[size]; // allocation of memory for pointers of the first level
for (int i = 0; i < size; i++)
{
mx[i] = new Queen*[size]; // allocation of memory for pointers of the second level
for (int j = 0; j < size; j++)
{
mx[i][j] = new Queen(); // allocation of memory for object
}
}
}
int main()
{
int m_size = 7;
Queen *** matrix = NULL; // now memory not allocated for matrix
changeToQueen(matrix, m_size);
return 0;
}
Note: & sign in void changeToQueen(Queen*** &mx, int size) allows to change pointer Queen *** matrix; inside the function changeToQueen

Initializing multidimensional dynamical array in c++

I'm having problems declaring a multidimensional dynamical array in c style. I want to declare dynamically an array like permutazioni[variable][2][10], the code i'm using is as following (carte is a class i defined):
#include "carte.h"
//other code that works
int valide;
carte *** permutazioni=new carte**[valide];
for (int i=0; i<valide; i++){
permutazioni[i]=new carte*[2];
for (int j=0; j<2; j++) permutazioni[i][j]=new carte[10];
}
the problem is, whenever i take valide=2 or less than 2, the code just stops inside the last for (int i=0; i<valide; i++) iteration, but if i take valide=3 it runs clear without any problem. There's no problem as well if i declare the array permutazioni[variable][10][2] with the same code and any value of valide. I really have no clue on what the problem could be and why it works differently when using the two different 3d array i mentioned before
You show a 3D array declared as permutazioni[variable][10][2] but when you tried to dynamical allocate that you switched the last two dimensions.
You can do something like this:
#include <iostream>
#define NVAL 3
#define DIM_2 10 // use some more meaningfull name
#define DIM_3 2
// assuming something like
struct Card {
int suit;
int val;
};
int main() {
// You are comparing a 3D array declared like this:
Card permutations[NVAL][DIM_2][DIM_3];
// with a dynamical allocated one
int valid = NVAL;
Card ***perm = new Card**[valid];
// congrats, you are a 3 star programmer and you are about to become a 4...
for ( int i = 0; i < valid; i++ ){
perm[i] = new Card*[DIM_2];
// you inverted this ^^^ dimension with the inner one
for (int j = 0; j < DIM_2; j++)
// same value ^^^^^
perm[i][j] = new Card[DIM_3];
// inner dimension ^^^^^
}
// don't forget to initialize the data and to delete them
return 0;
}
A live example here.
Apart from that it is always a good idea to check the boundaries of the inddecs used to access to the elements of the array.
How about using this syntax? Haven't tested fully with 3 dimensional arrays, but I usually use this style for 2 dimensional arrays.
int variable = 30;
int (*three_dimension_array)[2][10] = new int[variable][2][10];
for(int c = 0; c < variable; c++) {
for(int x = 0; x < 2; x++) {
for(int i = 0; i < 10; i++) {
three_dimension_array[c][x][i] = i * x * c;
}
}
}
delete [] three_dimension_array;
Obviously this could be c++ 11/14 improved. Could be worth a shot.

C++ iterating a struct

Is it possible to iterate through a struct?
For example
struct team{
int player1;
int player2;
int player3;
int player4;
...
int player99;
int size = 99;
}
then run a for loop to set or access foo 1-4?
i guess pseudocode would look something like
for(int i = 0; i < size; i++){
player i = (i+1);
}
A more simplified explanation if that doesnt make sense is I Just want to be able to go through each variable without having to hard code player1 = 1; player2 =2.
One way is to put the players/elements into an array:
struct Team {
static int const size = 99;
int players[size];
};
And then:
for(int i = 0; i < size; ++i)
int player = players[i];
To answer your question as you've asked it, I believe that you can use the pre-compiler macro Pack (the exact phrase depends on your compiler) to guarantee the structure of the memory used to create an instance of your struct. And then you technically could increment a pointer to move through it... if you're mad. That would be a very poor way to do and not at all guaranteed to work on different compilers or even different days of the week. No what you want is a data structure to do the job for you; they come with a 100% cash-back guarantee!
The most basic structure to do this with is a fixed size array, e.g:
struct team
{
int players[99]; //an array
int manager;
int coach;
string teamName;
//etc etc
}
Then to access your players
team myTeam;
for(int i(0); i < 99; ++i)
{
myTeam.players[i]; //do whatever
}
The limitation of an array is that you cannot change its size once it's created.
So if you try
myTeam.players[99]; //accessing invalid memory - the array values are 0 - 98
More advanced
If you need a data structure that can change size after it's created, e.g you might want to add a few more players to your team at some point in the future. Then you can use a dynamic data structure such as the std::vector or the std::deque or std::list
I would propose to use container instead of many variables, for example you could use std::array or std::vector. This way it will be trivial to iterate, much easier to make a copy. But also it's better from design point of view: in case you decide to change the number of players it will be much easier to change the container rather than add/remove many fields
You can define pointer to member, like pointer to member function:
typedef int team::*member_t;
You can have array of pointers to all your members:
static member_t member[size];
With this approach defining member function to iterate over all members is easy:
template <class F>
void for_each(F f)
{
for (int i = 0; i < size; ++i)
f(this->*member[i]);
}
And with using of preprocessor macro - you can have in one place definition of all members, in other definition of pointer to members - so you will not make any mistake with changing their order. See full code:
struct team {
#define TEAM_MEMBERS(prefix,suffix) \
prefix player1 suffix, \
prefix player2 suffix, \
prefix player3 suffix
int TEAM_MEMBERS(,);
static const int size = 3;
typedef int team::*member_t;
static member_t member[size];
template <class F>
void for_each(F f)
{
for (int i = 0; i < size; ++i)
f(this->*member[i]);
}
};
team::member_t team::member[team::size] = {
TEAM_MEMBERS(&team::,)
};
And some test:
#include <iostream>
int main() {
team t = { 0 };
t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,0,0
int n = 0;
t.for_each([&n](int& m) { m = n++; });
t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,1,2
t.player2 = 7;
t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,7,2
}