I've problem with Initialize the element of multidimensional array.
Here's my code:
class A{
int *const e;
const int row, column;
public:
A::A(int r, int c) : row(r), column(c), e(new int[r*c])
{
for (int i = 0; i < r*c; i++)
{
e[i] = 0;
}
}
A(const A &matrix) : row(matrix.row), column(matrix.column) ,e(new int[matrix.row*matrix.column])
{
for (int i = 0; i < matrix.row*matrix.column; i++)
{
e[i] = matrix.e[i];
}
}
virtual ~A() //destructing a A
{
delete[] e;
}
};
But when I'm trying Initialize the element of multidimensional array I've got a error:
int main(int argc, char* argv[])
{
A c(2, 5);
c[0][0] = 1;
A a(c);
return 0;
}
1 IntelliSense: no operator "[]" matches these operands operand types are: MAT [ int ]
Edit:
According to comments I try to write operator []
virtual int *const operator[ ](int r)
{
return e[r][0];
}
It should get first element of the r row. But I've got a error:
1 IntelliSense: expression must have pointer-to-object type
You're trying to apply the [] to the class A, C++ only knows how to use the operator [] on arrays. In order to use them for A you have to tell how [] works for A, so inside your class definition you should put:
int *operator[](int x){
return &e[x*row];
}
It basically receives the number you have put between brackets, and returns the corresponding row(an array), so you can apply [] again easily, so for example:
c[0] returns the first row
c[0][1] access the second element of the first row
Related
I'm looking to define a 2 dimensional character array where arguments I pass to a function holding the array will be used to determine the size each dimension of the array.
int func(const int x, const int y) {
char maze[x][y] = { 0 };
return 0;
}
When defining x & y inside the function as constant integers the array is defined just fine. When x and y are arguments to the function the program won't compile. Why is this and how do I get around it?
You can make a wrapper around 1-dimensial array like this:
class Maze {
friend class Row;
public:
/* This helper class represents a single row of the maze */
class Row {
friend class Maze;
Maze& owner;
std::size_t row;
Row(Maze& owner_, std::size_t row_) : owner(owner_), row(row_) {}
/* this operator resolves 2nd pair of brackets */
public:
inline char& operator[](std::size_t col) { return owner.data[col + row*owner.cols]; }
};
Maze(std::size_t rows_, std::size_t cols_)
: data(rows_ * cols_, 0)
, cols(cols_)
{}
/* this operator resolves 1st pair of brackets */
inline Row operator[](std::size_t index) { return Row(*this, index); }
private:
std::vector<char> data;
std::size_t cols;
};
...
Maze m(5, 10);
m[2][3] = 1;
You need to use dynamic memory allocation. Variadic length arrays is not a part of c++ standart. However variadic length arrays available as an extension for GCC. Although you can use STL or implement your class, dont forget about new[] and the one-dimensional representation for two-dimensional array:
char* maze = new char[x*y]; // create
maze[i + j * x]; // access
delete[] maze; // delete
It is compact and in most cases fast.
When defining x & y inside the function as constant integers the array is defined just fine
It works because the size of your array is defined and known by your compiler, known at compile-time
When x and y are arguments to the function the program won't compile.
When you wish to define you array only when you call your function, you ask your program to do that during runtime
. As answered by Dmytro Dadyka, you have to use use dynamic memory allocation and manage yourself memory deallocation (delete[] maze; // delete)
Here is an alternative of defining dynamically your 2D array using template! Notice that it is always done at compile-time.
template<int X, int Y>
int f()
{
char c[X][Y];
for(int x=0; x < X; ++x)
{
for(int y=0; y < Y; ++y)
{
c[x][y] = '1';
}
}
// write your algorithm now!....
c[2][2] = 'a';
for(int x=0; x < X; ++x)
{
for(int y=0; y < Y; ++y)
{
std::cout << c[x][y] << " ";
}
std::cout << std::endl;
}
return 0;
}
int main()
{
f<5,5>();
f<7,4>();
return 0;
}
I am working on a homework assignment that involved converting matrix and array classes supplied by my professor into templates. I am getting an error '=': cannot convert from 'Array *' to 'int' in my line m[i] = new Array < Type >(cols);
I would assume this is because m[i] is returning an int but I don't think it should be if I wrote my templates correctly and I can't quite figure out why it is giving back an int instead of a array pointer since m is an array of array pointers here is the code to my array template minus some overloads for << not used in this code.
template
< typename Type >
class Array
{
private:
int len;
Type * buf;
public:
Array(int newLen)
: len(newLen), buf(new Type[newLen])
{
}
Array(const Array & l)
: len(l.len), buf(new Type[l.len])
{
for (int i = 0; i < l.len; i++)
buf[i] = l.buf[i];
}
int length()
{
return len;
}
int & operator [] (int i)
{
assert(0 <= i && i < len);
return buf[i];
}
}
Here is my matrix template the error occurs in minus the same << overloads
#pragma once
#include "Array.h"
template
< typename Type >
class Matrix
{
private:
int rows, cols;
Array< Array<Type> * > m;
public:
Matrix(int newRows, int newCols)
: rows(newRows), cols(newCols), m(rows)
{
for (int i = 0; i < rows; i++)
m[i] = new Array < Type >(cols);
}
int numRows()
{
return rows;
}
int numCols()
{
return cols;
}
Array < Type > & operator [] (int row)
{
return *m[row];
}
}
The [] operator overload in the array class is what's messing you up.
int & operator [] (int i)
{
assert(0 <= i && i < len);
return buf[i];
}
It clearly returns an int as its type and when you try to use it such that: m[i] = new Array < Type >(cols);
m[i] will return an int type which you're trying to assign a new Array to.
The proximal issue is that Array isn't fully templated:
int & operator [] (int i)
Indexing into an Array<T> shouldn't give you an int&, it should give you a T&!
The other issue with your code is that you have a new in your Array constructor - where's the corresponding delete? You're leaking memory!
Same for the Matrix constructor, which additionally has the potential of double deleting memory if you happen to copy it.
See Rule of Three
Hi I'm creating a Matrix object which is a containter for an int[3][3].
I want to add a get_matrix() function which returns the object itself or the pointer to it, but I'm not able.
eclipse says :
Type cannot convert ‘int (*)[3][3]’ to ‘int**’
enter code here
class Matrix
{
private:
int matrix[3][3];
public:
void set_matrix()
{
int c, d;
printf("Enter the elements of first matrix1\n");
for (c = 0; c < n_rows; c++)
for (d = 0; d < n_column; d++)
scanf("%d", &matrix[c][d]);
}
int get_matrix(){
return matrix;
}
void output_matrix()
{
int c, d;
for (c = 0; c < n_rows; c++) {
printf("\n");
for (d = 0; d < n_column; d++)
printf("%d\t", matrix[c][d]);
}
}
};
Try this:
int **get_matrix() const {
return reinterpret_cast<int **>(matrix);
}
or this:
int **get_matrix() const {
return (int **) matrix;
}
A two dimensioned array cannot be implicitly converted to a pointer to a pointer to an int, although there are several similarities between the two. You can, however, force a cast to an int **.
You could also (and probably should) use a C++ container that is readily available instead of trying to reinvent the wheel.
I have a program that looks like the following:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
No, there's no right way to do specifically that. A double[4][4] array is not convertible to a double ** pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
The simplest way to do the latter, i.e. to make your existing double[4][4] array compatible with the function, is to create temporary "index" arrays of type double *[4] pointing to the beginnings of each row in each matrix
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows and inverseRows arrays, since the result will be placed into your original inverseMatrix array correctly.
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
One thing you could do: templates. Make the size of the second dimension a template parameter.
#include <iostream>
template <unsigned N>
void print(double a[][N], unsigned order)
{
for (unsigned y = 0; y < order; ++y) {
for (unsigned x = 0; x < N; ++x) {
std::cout << a[y][x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(arr, 3);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
#include <iostream>
void print(double *a, unsigned height, unsigned width)
{
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
std::cout << a[y * width + x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(&arr[0][0], 3, 3);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
#include <iostream>
using namespace std;
template <int matrix_size>
class SquareMatrix
{
public:
int size(void) { return matrix_size; }
double array[matrix_size][matrix_size];
void copyInverse(const SquareMatrix<matrix_size> & src);
void print(void);
};
template <int matrix_size>
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
{
int inv_x;
int inv_y;
for (int x = 0; x < matrix_size; x++)
{
inv_x = matrix_size - 1 - x;
for (int y = 0; y < matrix_size; y++)
{
inv_y = matrix_size - 1 - y;
array[x][y] = src.array[inv_x][inv_y];
}
}
}
template <int matrix_size>
void SquareMatrix<matrix_size>::print(void)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
cout << array[x][y] << " ";
}
cout << endl;
}
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix);
int main(int argc, char * argList[])
{
SquareMatrix<4> startMatrix;
SquareMatrix<4> inverseMatrix;
Initialize(startMatrix);
inverseMatrix.copyInverse(startMatrix);
cout << "Start:" << endl;
startMatrix.print();
cout << "Inverse:" << endl;
inverseMatrix.print();
return 0;
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix)
{
for (int x = 0; x < matrix_size; x++)
{
for (int y = 0; y < matrix_size; y++)
{
matrix.array[x][y] = (x+1)*10+(y+1);
}
}
}
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]. For your function, the signature should be like:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
There is a solution using the pointer to point by bobobobo
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
int numRows = 16 ;
int numCols = 5 ;
int **a ;
a = new int*[ numRows* sizeof(int*) ];
for( int row = 0 ; row < numRows ; row++ )
{
a[row] = new int[ numCols*sizeof(int) ];
}
The rest of code is the same with bobobobo's.
You can definitely do something like the code below, if you want.
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][]).
by nice coding if c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interface would be
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
the interface is very simple and clear.
once need to modify "m" of matrix internally, you don't need to update the interface.
Or this way
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
void MatrixInversion(void *A, int order, void *B)
{
double _a[4][4];
double _b[4][4];
memcpy(_a, A, sizeof _a);
memcpy(_b, B, sizeof _b);
// processing data here
// copy back after done
memcpy(B, _b, sizeof _b);
}
I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?
By the letter of the law, here's how to do it:
// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}
// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}
Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.
However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.
It depends. It can be as simple as:
int main()
{
int* data[10][20]; // Fixed size known at compile time
data[2][3] = new int(4);
}
If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:
int main()
{
int x;
int y;
getWidthAndHeight(x,y);
// declare a 2D array of int*
boost::multi_array<int*,2> data(boost::extents[x][y]);
data[2][3] = new int(6);
}
If you are fine with jagged arrays that can grow dynamically:
int main()
{
std::vector<std::vector<int*> > data;
data.push_back(std::vector<int*>(10,NULL));
data[0][3] = new int(7);
}
Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;
That's how you make a true (contiguous in memory) multidimensional array.
But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:
int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array
foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
for (int col = 0; col < colCnt; ++col)
array[row][col] = 0;
You could try Boost::MultiArray.
Check out this page for details.
:)
I had these once in a piece of code I wrote.
I was the laughing stock of the team when the first bugs leaked out. On top of that we use Hungarian notation, leading to a name like papChannel - a pointer to an array of pointers...
It's not nice. It's nicer to use typedefs to define a 'row of columns' or vice versa. Makes indexing more clear, too.
typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];
Table * pTable = new Table;
for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
... do something with cells.
}
}
You can define a vector of vectors:
typedef my_type *my_pointer;
typedef vector<vector<my_pointer> > my_pointer2D;
Than create a class derived from my_pointer2D, like:
class PointersField: public my_pointer2D
{
PointsField(int n, int m)
{
// Resize vectors....
}
}
PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer
I prefer to use the () operator. There are lots of reasons for this (C++ FAQs 13.10). Change the internal representation to a std::vector if you like:
template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
const T& operator ()(size_t col, size_t row) const
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
T& operator ()(size_t col, size_t row)
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
private:
T m_data[WIDTH * HIEGHT];
};
You can use it like this:
Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();
See my code. It works on my FC9 x86_64 system:
#include <stdio.h>
template<typename t>
struct array_2d {
struct array_1d {
t *array;
array_1d(void) { array = 0; }
~array_1d()
{
if (array) {
delete[] array;
array = 0;
}
}
t &operator[](size_t index) { return array[index]; }
} *array;
array_2d(void) { array = 0; }
array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
void init(size_t a, size_t b)
{
array = new array_1d[a];
for (size_t i = 0; i < a; i++) {
array[i].array = new t[b];
}
}
~array_2d()
{
if (array) {
delete[] array;
array = 0;
}
}
array_1d &operator[](size_t index) { return array[index]; }
};
int main(int argc, char **argv)
{
array_2d<int> arr = new array_2d<int>;
arr.init(16, 8);
arr[8][2] = 18;
printf("%d\n",
arr[8][2]
);
return 0;
}
Effo UPD: a response to "Isn't that an array of pointers to arrays?", adding the example of array of pointers, very simple:
int main(int argc, char **argv)
{
array_2d<int*> parr = new array_2d<int*>;
int i = 10;
parr.init(16, 8);
parr[10][5] = &i;
printf("%p %d\n",
parr[10][5],
parr[10][5][0]
);
return 0;
}
Did I still misunderstand your question?
And you could even
typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;
int main(int argc, char **argv)
{
array_type parr = new array_type;
parr.init(16, 8);
parr[10][5] = new cell_type;
cell_type *cell = parr[10][5];
cell->init(8, 16);
int i = 10;
(*cell)[2][2] = &i;
printf("%p %d\n",
(*cell)[2][2],
(*cell)[2][2][0]
);
delete cell;
return 0;
}
It also works on my FC9 x86_64 system.