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

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.)

Related

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

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);
}

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.

Is it possible in c++ for a class to have a member which is a multidimensional array whose dimensions and extents are not known until runtime?

I originally asked using nested std::array to create an multidimensional array without knowing dimensions or extents until runtime but this had The XY Problem of trying to accomplish it with std::array.
The questions One-line initialiser for Boost.MultiArray and How do I make a multidimensional array of undetermined size a member of a class in c++? and their answers give some helpful information how to use Boost::MultiArray to avoid needing to know the extents of the dimensions at runtime, but fail to demonstrate how to have a class member that can store an array (created at runtime) whose dimensions and extents are not known until runtime.
Just avoid multidimensional arrays:
template<typename T>
class Matrix
{
public:
Matrix(unsigned m, unsigned n)
: n(n), data(m * n)
{}
T& operator ()(unsigned i, unsigned j) {
return data[ i * n + j ];
}
private:
unsigned n;
std::vector<T> data;
};
int main()
{
Matrix<int> m(3, 5);
m(0, 0) = 0;
// ...
return 0;
}
A 3D access (in a proper 3D matrix) would be:
T& operator ()(unsigned i, unsigned j, unsigned k) {
// Please optimize this (See #Alexandre C)
return data[ i*m*n + j*n + k ];
}
Getting arbitrary dimensions and extent would follow the scheme and add overloads (and dimensional/extent information) and/or take advantage of variadic templates.
Having a lot of dimensions you may avoid above (even in C++11) and replace the arguments by a std::vector. Eg: T& operator(std::vector indices).
Each dimension (besides the last) would have an extend stored in a vector n (as the first dimension in the 2D example above).
Yes. with a single pointer member.
A n multidimensional array is actually a pointer. so you can alocate a dynamic n array and with casting, and put this array in the member pointer.
In your class should be something like this
int * holder;
void setHolder(int* anyArray){
holder = anyArray;
}
use:
int *** multy = new int[2][1][56];
yourClass.setHolder((int*)multy);
You can solve the problem in at least two ways, depending on your preferences. First of all - you don't need the Boost library, and you can do it yourself.
class array{
unsigned int dimNumber;
vector<unsigned int> dimSizes;
float *array;
array(const unsigned int dimNumber, ...){
va_list arguments;
va_start(arguments,dimNumber);
this->dimNumber = dimNumber;
unsigned int totalSize = 1;
for(unsigned int i=0;i<dimNumber;i++)
{
dimSizes.push_back(va_arg(arguments,double));
totalSize *= dimSizes[dimSizes.size()-1];
}
va_end(arguments);
array = new float[totalSize];
};
float getElement(unsigned int dimNumber, ...){
va_list arguments;
va_start(arguments,dimNumber);
unsgned int elementPos = 0, dimAdd = 1;
for(unsigned int i=0;i<dimNumber;i++)
{
unsigned int val = va_arg(arguments,double);
elementPos += dimAdd * val;
dimAdd *= dimsizes[i];
}
return array[elementPos]
};
};
Setting an element value would be the same, you will just have to specify the new value. Of course you can use any type you want, not just float... and of course remember to delete[] the array in the destructor.
I haven't tested the code (just wrote it straight down here from memory), so there can be some problems with calculating the position, but I'm sure you'll fix them if you encounter them. This code should give you the general idea.
The second way would be to create a dimension class, which would store a vector<dimension*> which would store sub-dimensions. But that's a bit complicated and too long to write down here.
Instead of a multidimensional array you could use a 1D-array with an equal amount of indices. I could not test this code, but I hope it will work or give you an idea of how to solve your problem. You should remember that arrays, which do not have a constant length from the time of being compiled, should be allocated via malloc() or your code might not run on other computers.
(Maybe you should create a class array for the code below)
#include <malloc.h>
int* IndexOffset; //Array which contains how many indices need to be skipped per dimension
int DimAmount; //Amount of dimensions
int SizeOfArray = 1; //Amount of indices of the array
void AllocateArray(int* output, //pointer to the array which will be allocated
int* dimLengths, //Amount of indices for each dimension: {1D, 2D, 3D,..., nD}
int dimCount){ //Length of the array above
DimAmount = dimCount;
int* IndexOffset = (int*) malloc(sizeof(int) * dimCount);
int temp = 1;
for(int i = 0; i < dimCount; i++){
temp = temp * dimLengths[i];
IndexOffset[i] = temp;
}
for(int i = 0; i < dimCount; i++){
SizeOfArray = SizeOfArray * dimLengths[i];
}
output = (int*)malloc(sizeof(int) * SizeOfArray);
}
To get an index use this:
int getArrayIndex(int* coordinates //Coordinates of the wished index as an array (like dimLengths)
){
int index;
int temp = coordinates[0];
for(int i = 1; i < DimAmount; i++){
temp = temp + IndexOffset[i-1] * coordinates[i];
}
index = temp;
return index;
}
Remember to free() your array as soon as you do not need it anymore:
for(int i = 0; i < SizeOfArray; i++){
free(output[i]);
}
free(output);

Best way to represent a 2-D array in C++ with size determined at run time

In C++ I'd like to do something like:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
but of course this doesn't work. What is the best way to do something similar? I've seen some solutions to this but they seem pretty messy.
The manual dynamic way:
Let's say you want an array of width*height, the most efficient way is to just use a single dimensional array:
char *matrix = new char[width*height];
To delete it:
delete[] matrix;
To access it:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
To modify it:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Boost Matrix:
Consider using boost::matrix if you can have the dependency.
You could then tie into the boost linear algebra libraries.
Here is some sample code of boost::matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
On the stack for some compilers:
Some compilers actually allow you to create arrays on the stack with runtime determined sizes. g++ is an example of such a compiler. You cannot do this by default VC++ though.
So in g++ this is valid code:
int width = 10;
int height = 10;
int matrix[width][height];
Drew Hall mentioned that this C99 feature is called Variable Length Arrays (VLAs) and it can probably be turned on in any modern compiler.
I usually do something like this:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
You seem to be missing the whole point of C++ (C with classes) :-). This is the sort of use that's crying out for a class to implement it.
You could just use STL or other 3rd party class library which I'm sure would have the data structure you're looking for but, if you need to roll your own, just create a class with the following properties.
constructor which, given n, will just create a new n*n array of char (e.g., charray)..
member functions which get and set values based on x.y which simply refer to charray[x*n+y];
destructor which delete[]'s the array.
What about std::vector< std::vector<int> > array2d; ?
For a true two dimensional array:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Just off the top of my head. Mistakes, no doubt. However, other people have posted a more elegant approach, I think.
I like the 1-d array approach (the selected answer by Brian R. Bondy) with the extension that you wrap the data members into a class so that you don't need to keep track of the width separately:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
The implementation is an exercise for the reader. ;)
I think this would be a good one.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Then call m.resize() at runtime.
int* matrix = new int[w*h];
if you want to do something like Gaussian elimination your matrix should be
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(in Gaussian elimination we usually need to exchange one row with another so it's better to swap pointers to rows in constant time rather than swapping by copying in linear time).