Trying to create a jagged array c++ - c++

int** DATA = new int*[10];
DATA[0] = new int[100]; //works
DATA[1] = new int[100][5]; //dont work
DATA[1][100] = 1;
hello, i'm trying to create a jagged array, but need 5 columns. thanks

Do you really need a jagged array (different number of columns for each row) or just a two dimensional array, with 5 columns for each row. In both cases Ulrich's advice to prefer std::vector over bare arrays is good, and you should consider it.
However if you absolutely require a two dimensional array created in C-style, the way to do it is
int** p = new int*[10];
for( int i=0; i<10; i++ ) {
p[i] = new int[20];
}
p[7][17] = 177;
This will create a 2D array with 10 rows and 20 columns that can be accessed using 2D array syntax.

Related

Cycling through columns vs cycling through rows when working with 2D arrays

I am trying to understand this code. The first thing that's confusing to me is that in the second line of code I believe they are creating an array of pointers and the plan is that those pointers are going to point to arrays.
I know that the computer doesn't care but to me, it's most logical to have the array of pointers be horizontal and then each array can drop down from the points on that horizontal line.
So, is it reasonable to have "dynamicArray = new int *[COLUMNS];" instead?
int **dynamicArray = 0;
//memory allocated for elements of rows.
dynamicArray = new int *[ROWS] ;
//memory allocated for elements of each column.
for( int i = 0 ; i < ROWS ; i++ )
dynamicArray[i] = new int[COLUMNS];
//free the allocated memory
for( int i = 0 ; i < ROWS ; i++ )
delete [] dynamicArray[i] ;
delete [] dynamicArray ;
EDIT: I thought about this more and the thing that I am getting tripped up on a lot is that I think about the rows and columns in the wrong way.
dynamicArray = new int *[ROWS];
I understand this to be an array of pointers and each pointer is pointing to a column. The number of elements in each column is equal to the number of rows (columns have one vertical element for each row in our 2D array).
Am I understanding this right?
I also get tripped up a lot when I need to use nested for loops to initialize a 2 D array.
Rows/columns are symmetric/interchangeable, and as you say, "the computer doesn't care". Having said that, why do you think "it's most logical to have the array of pointers be horizontal and then each array can drop down from the points on that horizontal line"?
I would think the other way. I would find it much easier to "visualize" rows of horizontal objects (after all, we write horizontally (say, an array of chars), and the lines/rows go top to bottom (say, an array of arrays)). I think the code is more natural (to me) than what you suggest.
The point is, we all think differently, and at the end of the day, ROWS/COLUMNS are just variables, which could have been easily written as X/Y or V/H or W/H or whatever.

Pointer to 2 or 3 dimensional sub-array/sub-matrix

say you have a matrix of dimensions x per y (per z) defined like:
int** tab = new int*[x];
for(int i=0; i<x; ++i) tab[i] = new int[y];
or
int*** tab = new int**[x];
for(int i=0; i<x; ++i) {
tab[i] = new int*[y];
for(int j=0; j<y; ++y) tab[i][j] = new int[z];
}
is there any smart way to access sub-matrix (get int**(*) without data copying, plain C++) which will have top-left(-front) corner [a,b(,c)] and size of [A, B(,C)]?
Here are (better or worse) graphical examples of the problem.
You are using what is called a jagged array. It is an array of arrays, where nothing besides runtime enforces that the sub arrays are the same size. Hence jagged, because you could have the subarrays vary in size.
In order to have a submatrix that is also a jagged array, you need for there to exist a jagged array of pointers pointing at the subarrays of the submatrix. These don't exist in general, so no, you cannot do this "without copying" at least some arrays of pointers to subarrays.
Had your matrix been not jagged array based, but instead single array with stride, then views of subarrays could be created without allocating new subarray pointer arrays. Also it would be more cache friendly.
To write the non-jagged matrix, start by writing an array view or span class that handles one dimension.
For two dimensions, you augment the span class to store a tuple of dimension sizes or strides. [] instead of returning a reference to the calculated element, creates a one-dimension-lower span instance pointing at the calculated position, until the dimension 0 case where you return a reference.
This will be highly efficient, permit efficient subarrays, but requires a few dozen or 100 lines of code to get right.

c++ 2D array allocation

Could someone please explain what each line is really doing here. I know overall it allocates 4 spaces, but I don't understand the details.
int** arrayArray;
arrayArray= new int*[4];
for (int x = 0; x < 4; ++x)
{ arrayArray[x] = new int[4];}
Your array is a 2D array, so it size is in forms of "x by y". The total ints your array contains will be x*y. I will call x as the row number and y as the column number.
It seems like you need a array with total 4 ints, so your row number and column number should have a product of 4, for example 2x2. Keep in mind that the following answer is dealing with a 4x4 array, which has 16 total ints.
Allocation:
int** arrayArray;
This line decelar a variable arrayArray, which is a pointer of ( pointer of int ). Like
(arrayArray) -> * -> int
So arrayArray[0] gives you a pointer of int, and arrayArray[0][0] therefore give you an int (which is in the array).
arrayArray = new int*[4];
This line allocate a space that can contain 4 pointers of int, and set the arrayArray to point to that space (don't forget that arrayArray is a pointer of a pointer of int. ).
Here the 4 means row number.
for (int x = 0; x < 4; ++x)
arrayArray[x] = new int[4];
For every pointer in arrayArray, set it to point to a space for 4 ints.
Here the 4 in new int[4] means column number.
So the structure of this array will be something like
Deallocation (free):
Notice that arrayArray by it self is just a pointer to 4 other pointer. If you want to free the entire array, you don't just free the space for the 4 pointers. You need to free every space these pointer points to, else you will cause memory leak. For example you want to free the entire array, it is just the reverse of allocation, first free all the space arrayArray points to:
for (int x = 0; x < 4; ++x)
delete[] arrayArray[x];
In C++, if you want to delete a space allocated by new something[], you need delete[] instead of delete.
Then free the array itself:
delete[] arrayArray;
int** arrayArray;
arrayArray= new int*[4];
The above code initializes 4 locations that can hold pointers to 4 int*
The next couple of lines allocate 4 int spaces for each int*, so a total of 4*4=16 integer spaces.
for (int x = 0; x < 4; ++x)
{ arrayArray[x] = new int[4];}
Now as per your comment, you want only 4 integer spaces. So that means your 2d array would be 2x2.
So your code should look something like:
int** arrayArray;
arrayArray= new int*[2];
for (int x = 0; x < 2; ++x)
{ arrayArray[x] = new int[2];}
This way you will only allocate 2 int* locations and 2 int spaces that they can point to.

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

how to create multidimensional, dynamically defined array?

i know how to create a single-dimensional, dynamically defined array
string *names = new string[number]; //number specified by the user
however, when i try to make it multidimensional
string *names = new string[number][number]; //doesn't work
it doesn't work. what gives? i found this http://www.cplusplus.com/forum/beginner/63/ but am completely confused by what they are saying. anyone care to explain? thanks so much.
I tried to provide some explanations to example from your link:
// To dynamically allocate two-dimensional array we will allocate array of pointers to int first.
// Each pointer will represent a row in your matrix.
// Next step we allocate enough memory for each row and assign this memory for row pointers.
const int rows = 4; //number of rows in your matrix
const int cols = 4; //number of columns in your matrix
// declaration
int ** a;
/* allocating memory for pointers to rows. Each row will be a dynamically allocated array of int */
a = new int*[rows];
/* for each row you allocate enough memory to contain cols elements. cols - number of columns*/
for(int i = 0; i < rows; i++)
a[i] = new int[cols];
The memory layout of single-dimension array (let's say with three elements) looks like,
names ------> [0] [1] [2]
And the two-dimensional array (let's say with 3 X 3 elements) would look like,
names ------> [0] --> [0] [1] [2]
[1] --> [0] [1] [2]
[2] --> [0] [1] [2]
^
|
this is an array of pointers
i.e. two dimensional array is array of pointers to arrays, therefore you would need **names in first place.
string **names = new string*[number]; // allocating space for array of string pointers
Now, you want each element of this array of string pointers to point to an array of strings.
Therefore, you would need to do
for(int i = 0; i < number, i++) {
names[i] = new string[number];
}
I hope this helps to understand it better.