how to assign two 2d array - c++

I have written a program which make a 2d array and then set its numbers.
The second step that I have problem in it is that when I want to shift rows and columns I face with a problem in this line nmatrix[i*c+j] = 0;
the error is this : error: incompatible types in assignment of 'int' to 'int [(((sizetype)(((ssizetype)(c + shiftc)) + -1)) + 1)]'
here is the code :
void shiftMatrix(int *matrix, int r,int c ,int shiftr,int shiftc){
int nmatrix [r+shiftr][c+shiftc];
for(int i = 0; i< shiftr; i++)
{
for(int j = 0; j<shiftc;j++)
{
nmatrix[i*c+j] = 0;
}
}
for(int i = shiftr; i< r; i++)
{
for(int j = shiftc; j<c;j++)
{
nmatrix[i*c+j] = matrix[i*c+j];
}
}
}
Any help please??
thanks in advance

int nmatrix [r+shiftr][c+shiftc];
First of all, you are using an array with non-constant bounds, which is a controversial feature.
In addition, here you are declaring a two-dimensional array nmatrix, but your other matrix (matrix) is a pointer to int (or a one-dimensional array, if you like to look at it this way). This is a recipe for confusion.
You can easily declare nmatrix ("new matrix"?) as a one-dimensional array:
int nmatrix[(r+shiftr) * (c+shiftc)];
Or (presumably better)
std::vector<int> nmatrix((r+shiftr) * (c+shiftc));
Then, your code nmatrix[i*c+j] = 0 will work (however, you have to change c to c+shiftc whenever you work with nmatrix).

You cannot define an array dynamically the way you do it.
You need to use the c++ keyword new:
int nmatrix[][] = new int [r+shiftr][c+shiftc];
You cannot define arrays the way you did, with non constant int value for dimension, because such static arrays are to be defined for memory at the compile stage. Thus dimensions should be const expression.
On the contrary with keyword new you can define dimensions for arrays at run-time stage, because it's dynamic allocation.
There are more detailed answers in this SO question here.

Related

C++ Avoiding Triple Pointers

I am trying to create an array of X pointers referencing matrices of dimensions Y by 16. Is there any way to accomplish this in C++ without the use of triple pointers?
Edit: Adding some context for the problem.
There are a number of geometries on the screen, each with a transform that has been flattened to a 1x16 array. Each snapshot represents the transforms for each of number of components. So the matrix dimensions are 16 by num_components by num_snapshots , where the latter two dimensions are known at run-time. In the end, we have many geometries with motion applied.
I'm creating a function that takes a triple pointer argument, though I cannot use triple pointers in my situation. What other ways can I pass this data (possibly via multiple arguments)? Worst case, I thought about flattening this entire 3D matrix to an array, though it seems like a sloppy thing to do. Any better suggestions?
What I have now:
function(..., double ***snapshot_transforms, ...)
What I want to accomplish:
function (..., <1+ non-triple pointer parameters>, ...)
Below isn't the function I'm creating that takes the triple pointer, but shows what the data is all about.
static double ***snapshot_transforms_function (int num_snapshots, int num_geometries)
{
double component_transform[16];
double ***snapshot_transforms = new double**[num_snapshots];
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms[i] = new double*[num_geometries];
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms[i][j] = new double[16];
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms[i][j][k] = k;
}
}
return snapshot_transforms;
}
Edit2: I cannot create new classes, nor use C++ features like std, as the exposed function prototype in the header file is getting put into a wrapper (that doesn't know how to interpret triple pointers) for translation to other languages.
Edit3: After everyone's input in the comments, I think going with a flattened array is probably the best solution. I was hoping there would be some way to split this triple pointer and organize this complex data across multiple data pieces neatly using simple data types including single pointers. Though I don't think there is a pretty way of doing this given my caveats here. I appreciate everyone's help =)
It is easier, better, and less error prone to use an std::vector. You are using C++ and not C after all. I replaced all of the C-style array pointers with vectors. The typedef doublecube makes it so that you don't have to type vector<vector<vector<double>>> over and over again. Other than that the code basically stays the same as what you had.
If you don't actually need dummy values I would remove that innermost k loop completely. reserve will reserve the memory space that you need for the real data.
#include <vector>
using std::vector; // so we can just call it "vector"
typedef vector<vector<vector<double>>> doublecube;
static doublecube snapshot_transforms_function (int num_snapshots, int num_geometries)
{
// I deleted component_transform. It was never used
doublecube snapshot_transforms;
snapshot_transforms.reserve(num_snapshots);
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms.at(i).reserve(num_geometries);
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms.at(i).at(j).reserve(16);
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms.at(i).at(j).at(k) = k;
}
}
return snapshot_transforms;
}
Adding a little bit of object-orientation usually makes the code easier to manage -- for example, here's some code that creates an array of 100 Matrix objects with varying numbers of rows per Matrix. (You could vary the number of columns in each Matrix too if you wanted to, but I left them at 16):
#include <vector>
#include <memory> // for shared_ptr (not strictly necessary, but used in main() to avoid unnecessarily copying of Matrix objects)
/** Represents a (numRows x numCols) 2D matrix of doubles */
class Matrix
{
public:
// constructor
Matrix(int numRows = 0, int numCols = 0)
: _numRows(numRows)
, _numCols(numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
// copy constructor
Matrix(const Matrix & rhs)
: _numRows(rhs._numRows)
, _numCols(rhs._numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
/** Returns the value at (row/col) */
double get(int row, int col) const {return _values[(row*_numCols)+col];}
/** Sets the value at (row/col) to the specified value */
double set(int row, int col, double val) {return _values[(row*_numCols)+col] = val;}
/** Assignment operator */
Matrix & operator = (const Matrix & rhs)
{
_numRows = rhs._numRows;
_numCols = rhs._numCols;
_values = rhs._values;
return *this;
}
private:
int _numRows;
int _numCols;
std::vector<double> _values;
};
int main(int, char **)
{
const int numCols = 16;
std::vector< std::shared_ptr<Matrix> > matrixList;
for (int i=0; i<100; i++) matrixList.push_back(std::make_shared<Matrix>(i, numCols));
return 0;
}

Unable to access the elements of a pointer to an array

I have a following array which I am passing as a pointer. BTW, I am new to C++ and just started pointers.
int arr[3][4]= {{2,3,4,8},{5,7,9,12},{1, 0, 6, 10}};
//int *a = &arr[0][0];
BuildStringFromMatrix((int *)arr, 3, 4);
I have a a following function with which I wanna access the elements of the passed array.
void BuildStringFromMatrix(int *a, int height, int width);
My implementation of the accessing the element is as follows
for(int i=0; i<height; i++){
for(int j=0; i<width; j++){
int x = *(*(a+i) + j);
std::cout<<x;
}
}
While using this implementation I am getting an error
invalid type argument of unary β€˜*’ (have β€˜int’
)
int x = *(*(a+i) + j);
How can I fix this issue.
P.S - I wanna implement this using single pointer.
Your function receives a pointer to int. It doesn't "remember" that it is actually pointing to an int that is in a 2-D array (let alone what the array dimensions are).
So if you want to access a certain element of the 2-D array you must perform a calculation to find how many units to offset from the pointer to get to the intended element. (This is sometimes called "flattening an array").
Typically row * row_length + column is the offset for a particular row-column entry, so in your case int x = a[i*width + j]; is the right statement to use.
If this is still unclear I suggest printing out the value of i*width+j at each iteration and seeing how it iterates over the array (or follow in your debugger).

How to use memset or fill_n to initialize a dynamic two dimensional array in C++

I have a 2D array created dynamically.
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
}
I want to fill the array with some value (say 1). I can loop over each item and do it.
But is there a simpler way. I am trying to use memset and std::fill_n as mentioned in this post.
std::fill_n(abc, rows * cols, 1);
memset(abc, 1, rows * cols * sizeof(int));
Using memset crashes my program. Using fill_n gives a compile error.
invalid conversion from 'int' to 'int*' [-fpermissive]
What am I doing wrong here ?
You could just use vector:
std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1));
You cannot use std::fill_n or memset on abc directly, it simply will not work. You can only use either on the sub-arrays:
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(abc[i], cols, 1);
}
Or make the whole thing single-dimensional:
int *abc = new int[rows * cols];
std::fill_n(abc, rows*cols, 1);
Or I guess you could use std::generate_n in combination with std::fill_n, but this just seems confusing:
int **abc = new int*[rows];
std::generate_n(abc, rows, [cols]{
int* row = new int[cols];
std::fill_n(row, cols, 1);
return row;
});
I think that your main problem here is that you don't have an array of int values. You have an array of pointers to ints.
You probably should start with int* abc = new int[rows * cols]; and work from there, if I understand what you are trying to achieve here.
Just use with * inside the loop you already have:
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(*(abc+i), cols, sizeof(int));
}
fill_n don't know where the memory maps the new int array, so you must be carefully coding that way.
I recommend to read:
A proper way to create a matrix in c++
Since you've already got good, workable answers to solve your problem, I want to add just two pointers left and right from the standard path ;-)
a) is just a link to the documentation of Boost.MultiArray
and b) is something I don't recommend you use, but it might help you to understand what you've initially tried. And since your profile shows visual studio tags, you might come in contact with something like this in the win32 api. If that is the case the documentation usually tells you not to use free()/LocalFree()/... on the elements and the "outer" pointer-pointer but to use a specialized function.
(note: I'm not trying to make this code look pretty or clever; it's a mishmash of c and a little c++-ish junk ;-))
const std::size_t rows = 3, cols =4;
int main()
{
std::size_t x,y;
// allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints
int **abc = (int**)malloc( (rows*sizeof(int*)) + cols*rows*sizeof(int) );
// the memory behind abc is large enough to hold the pointers for abc[0...rows-1]
// + the actual data when accessing abc[0...rows-1][0....cols-1]
int* data = (int*)((abc+rows));
// data now points to the memory right after the int*-pointer array
// i.e. &(abc[0][0]) and data should point to the same location when we're done:
// make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1)....
for(y=0;y<rows; y++) {
abc[y] = &(data[y*cols]);
}
// now you can use abc almost like a stack 2d array
for(y=0; y<rows; y++) {
for (x=0; x<cols; x++) {
abc[y][x] = 127;
}
}
// and -since the memory block is continuos- you can also (with care) use memset
memset(&abc[0][0], 1, sizeof(int)*rows*cols);
// and with equal care ....
std::fill_n( &(abc[0][0]), rows*cols, 127);
// and get rid of the whole thing with just one call to free
free(abc);
return 0;
}

Setting pointer to a double array in for loop

I have an algorithm that I want to run that uses a potentially long double array. Because the array can be millions in length, I'm putting it on the GPU so I need to export the array from a CPP file to a CU file. However, Im prototyping it in CPP only for now because it doesnt work in either case.
In my CPU prototype I get errors when I try to set the members of the double array with my for loop. For example, any operation including cout will give error c2109:subscript requires array or pointer type in the CPP file
or if the same code is run from a CU file, error: expression must have a pointer-to-object type
const int size = 100000;
double inputMeshPts_PROXY[size][4];
inputMeshPts.get(inputMeshPts_PROXY);
int lengthPts = inputMeshPts.length();
if (useCUDA == 1)
{
double *inputMeshPts_CUDA = &inputMeshPts_PROXY[size][4];
myArray(lengthPts, inputMeshPts_CUDA);
}
MStatus abjBlendShape::myArray(int length_CUDA, float weight_CUDA, double *inputMeshPts_CUDA)
{
for (int i = 0; i < length_CUDA; i++)
{
for (int j = 0; j < 3; j++)
{
cout << inputMeshPts_CUDA[i][j] << endl;
// inputMeshPts_CUDA[i][j] += (sculptedMeshPts_PROXY[i][j] - inputMeshPts_CUDA[i][j]); // WHAT I WANT, EVENTUALLY
}
}
}
When you are writing:
double *inputMeshPts_CUDA = &inputMeshPts_PROXY[size][4];
The variable inputMeshPts_CUDA is a pure pointer. You cannot use 2-dimensional indexing [][] as before. The right way to access it is now to linearize the indexes:
inputMeshPts_CUDA[i*4+j]
Alternatively you could declare "correctly" your pointer:
double (*inputMeshPts_CUDA)[4] = inputMeshPts_PROXY;
which allows you to use the 2-dimensional indexing again.
MStatus abjBlendShape::myArray(int length_CUDA, float weight_CUDA, double *inputMeshPts_CUDA)
{
inputMeshPts_CUDA is just a pointer, the compiler has lost all the dimension information. It needs that dimension information for inputMeshPts_CUDA[i][j], which gets converted to an access to address (byte arithmetic, not C++ pointer arithmetic)
inputMeshPts_CUDA + i * sizeof (double) * num_colums + j * sizeof (double)
You can either provide the missing information yourself and do the arithmetic like Angew suggests, or have the compiler pass the dimension information through:
template<size_t M, size_t N>
MStatus abjBlendShape::myArray(int length_CUDA, float weight_CUDA, double (&inputMeshPts_CUDA)[M][N])
Of course, this only works when the size is known at compile-time.
inputMeshPts_CUDA is a pointer to double - that is, it can represent a 1D array. You're accessing it as a 2D array: inputMeshPts_CUDA[i][j]. That doesn't make sense - you're effectively applying [j] to the double object storead at inputMeshPts_CUDA[i].
I believe you were looking for inputMeshPts_CUDA[i * 4 + j] - you have to compute the 2D addressing yourself.

Dynamically allocating 2D int array

Can someone please point out what I am doing wrong in the following code?
int* a = NULL;
int* b = NULL;
a = new int[map->mapSize.width];
b = new int[map->mapSize.height];
layer->tileGids = new int[a][b];
Here's what the code uses:
typedef struct _size {
int width, height;
} size;
class Map {
size mapSize;
}
class Layer {
int * tileGids;
}
EDIT: Compiler-Errors (in line 6 of the first bit of code):
error: expression in new-declarator must have integral or enumeration type|
error: 'b' cannot appear in a constant-expression|
Solution:
I have decided to accept lightalchemist's answer. In essence, what works for me is use a vector instead of the array. Vector manages the memory for you and hence is a lot easier to deal with.
You can't pass a pointer for initializing the size of an array. Others have now mentioned this.
This post (it's not mine) seems like it might help you: http://eli.thegreenplace.net/2003/07/23/allocating-multi-dimensional-arrays-in-c/
You should also consider doing the allocation in the class Layer's constructor and then deleting the memory in it's destructor (i.e. RAII - resource acquisition is initialization). This is considered good style.
Finally, you might consider using continuous memory and a custom indexing scheme, which you could easily use Layer to encapsulate. This of course depends upon how big things will get. The bigger they get the better the case for continuous memory becomes.
This should give you a flavor.
#include <iostream>
#include <cstdlib>
int main()
{
const size_t ROWS = 5;
const size_t COLS = 2;
const size_t size = ROWS*COLS;
int* arr = new int[size];
int i = 0;
for ( size_t r = 0 ; r < ROWS; ++r )
{
for (size_t c = 0; c < COLS; ++c )
{
arr[r*COLS+c] = i++;
}
}
for ( int j = 0; j < i; ++j)
{
std::cout << arr[j] << std::endl;
}
delete [] arr;
}
Firstly, your variables "a" and "b" are pointers. Your code:
layer->tileGids = new int[a][b]
is the root cause of the problem.
I'm trying to guess your intention here and I think what you are trying to do is make layer.tileGids a 2 dimension array to reference a "grid" of size (mapSize.Width, mapSize.height) so that you can refer to each "cell" in the grid using layer.tileGids[x][y].
If you are indeed trying to create a 2 dimension array, there are 2 methods to do it.
Method 1:
class Layer {
int ** tileGids; // NOTE the "**" to indicate tileGids is a pointer to pointer i.e. 2D array.
}
To initialize it:
int width = map->mapSize.width;
int height = map->mapSize.height;
layer.tileGids = new int*[width]; // NOTE the "int*" to indicate tileGids is a new array of pointers to int.
for (int i = 0; i < width; i++) // Initialize each element in layer.tileGids[] to be a pointer to int.
{
layer.tileGids[i] = new int[height];
}
Now you can access the items in layer.tileGids using:
int value = layer.tileGids[x][y] // where 0 <= x < width and 0 <= y < height
To deallocate this data structure, similar to how you allocate it, you need to deallocate each dynamically allocated array in each "row":
for (int i = 0; i < width; i++)
{
delete [] layer.tileGids[i]; // Deallocate each row.
}
delete [] layer.tileGids; // Deallocate "array" to the pointers itself.
Method 2:
Now another easier, less messy method (avoid pointers) is to use the C++ vector class. You need to make the following changes:
#include <vector>
class Layer {
vector<vector<int> > tileGids; // Note the space at "<int> >".
}
To initialize:
int width = map->mapSize.width;
int height = map->mapSize.height;
layer.tileGids = vector<vector<int> >(width, vector<int>(height, 0)); // Initialize all entries to 0.
To access the elements:
int value = layer.tileGids[x][y]; // Where 0 <= x < width and 0 <= y < height
Note that for the second method using vectors, you do not have to do any memory cleanup as is required in the first method because the vector will automatically take care of it. However, because a vector can grow dynamically i.e. you can add items to it, you lose the safety of having a fixed size array i.e. someone could accidentally increase the size of your grid if you use the vector method but if he tries to do that when you intialized it using the first method above an error will occur and you will immediately know that something is wrong.
Can someone please point out what I am doing wrong in the following code?
A lot. You're allocating two single arrays (a "row array" and a "column array", not what you need), and then you try to do something strange.
Generally you can't (strictly speaking) dynamically allocate a 2D array in C++ (because the type system would still need the type, along with the dimensions, to be known at compile time). You can emulate it with an array of arrays or so, but the best way is to allocate an 1D array:
int width=5;
std::vector<int> tab(width*height);
and then access the element by calculating the coordinates manually:
// access the element (1,2)
tab[1 + 2*width] = 10;
This way you're essentially interpreting a 1D array as a 2D array (with performance equal to static 2D arrays).
Then it's best to wrap the indexing with a class for convenience; boost::multi_array also has this done for you already.
a and b are int* here:
layer->tileGids = new int[a][b];
Perhaps you meant to say this?
layer->tileGids = new int[*a][*b];