Access an element of a 2d dynamic array--c++ - c++

I created a dynamic array.
typedef float* DynamicMatrix[MAT_SIZE];
DynamicMatrix matDyn;
// allocate rows and initialize to 0
for (r = 0; r < MAT_SIZE; r++) {
matDyn[r] = new float[MAT_SIZE];
for (c = 0; c < MAT_SIZE; c++) {
(matDyn[r])[c] = 0; // IS THIS CORRECT???
}
}
The whole idea was that I create an array of pointers which is my spine of a matrix I am creating. This spine is the leftmost-vertical part of the matrix. Each row of this array will point to another array of floats, therefore making it a dynamic 2d array.
I am unsure how to access an element of this matrix. Please let me know how to.

You can access it just like a "normal" matrix:
matDyn[r][c].

You can just access it by stating matDyn[r][c]
My error was that later in my program(not shown), I was trying to set matDyn[MAT_SIZE][MAT_SIZE] which isn't possible (it can only be matDyn[MAT_SIZE-1][MAT_SIZE-1]) and that is why I was getting my segmentation error.

Related

c++ Sudokou Grid initialisation

So I'm very new to c++, studying it at present and have a piece of work to do that's stumping me. You guys are the first port of call.
I need to make what is essentially a 2d array of objects. The header file includes Cell objects for rows, columns and blocks. The idea that I have a 9x9 array of objects, with relevant pointers based on column, row and internal 3x3 block therein. What I'm stuck on is that the below line fills out the 9x9 but how am I pointing to each Cell?
Or is that in something separate and this is all I need to do for just setting up that grid??
void SudokuPuzzle::InitialiseGrid()
{
for (int row = 0; row < 9; row++)
{
for (int column = 0; column < 9; column++)
{
m_gridRows[row].SetCell(column, new SudokuSquare());
// have the cell point to both it's position in the column and block
}
}
}
Maybe try to create the 2d array of the Type "SudokuSquare".
SudokuSquare sSquare [9][9];
So you can acces any object by
sSquare[row][column];
If your array is fixed size e.g. 3x3 just use std::array:
#include <array>
using std::array;
int main()
{
array<array<int, 3>, 3> sudoku_squares{};
sudoku_squares[0][1] = 1; // sets cell at first row, second column to 1
return 0;
}
In your case you can store 9 of those 3x3 arrays in another array or just use 9x9 array and you don't need to use any pointers. I used int in my example but you can store SudokuSquare exactly the same way.

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

How do I declare MULTIPLE 2d arrays in C++ using new?

There is a similar topic about this.
How do I declare a 2d array in C++ using new?
What I want to do is to create multiple 2d arrays according to some integer which determines how many 2d arrays there should be.
I want to create a single dimensional array first for pointers and assing every pointer to a multidimensional array, using new. But it seems like you can't ask for memory to create multidimensional array. Why can't we just write:
int** howManyPointers = new int*[translate];
for (int i = 0; i < translate; i++){
howManyPointers[i] = new char[rowsUsed][2000];
}
In my project, 2d array must have 2000 columns but row size is undetermined first. It will be given by the user. Assume you've already got it [rowsUsed]
So what?
You allocate array of pointers, and then for each pointer you allocate 1d array like this:
int** 2dArray = new int*[rows];
for (int i = 0; i < rows; ++i) {
2dArray[i] = new int[cols];
}
and then you can do 2dArray[X][Y] for each X < rows and Y < cols;

Passing a 2D Array to CUDA Device and Using it [duplicate]

This question already has answers here:
How can I add up two 2d (pitched) arrays using nested for loops?
(2 answers)
Closed 8 years ago.
I have a problem related to CUDA. I create a array which is 2D with :
char **WordMatrix = new char*[N]; // M and N set by the user
for(int i = 0; i < N; ++i)
{
WordMatrix[i] = new char[M];
}
I fill the array with a loop. After that where my problem is lying : I can't managed to allocate the memory in device and copy from host to device.
I saw other questions related to this but I did not understand the logic.
Like in this topic : https://devtalk.nvidia.com/default/topic/410182/double-pointer-allocation/ or in here.
I want to understand how to do it with an code example which uses cudaMemcpy and cudaMalloc and 2D Array also explanation of why we need supporting(if you use the approach in the link) pointer?
My understanding is CUDA accepts only linearized 2D arrays, so really a 1D array.
int *my_array = new int[height*width];
for (int h = 0; h < height; h++){
for (int w = 0; w < width; w++)
my_array[width * h + w] = value;
}
You can then copy that to device memory as in the other answer.
Also, this question has more info:
Allocate 2D Array on Device Memory in CUDA.
Create your 2D array in one piece new char[N*M]
Allocate the same amout of memory on GPU cudaMalloc(... sizeof(char)*N*M)
Copy your CPU memory (1.) to GPU (2.) with cudaMemcpy(... hostToDevice)

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];