Vector of vectors to 1D array - c++

I was wondering if there is a clever way of presenting the information in a vector as a 1D array. Example:
Let's create a vector of vectors of 5x3 int elements
vector< vector<int>> iVector;
ivector.resize( 5 );
for(i = 0; i < 5; i++){
iVector[i].resize(3);
}
But now I want this structure to be converted into a 1D array:
int* myArray = new int[5*3];
So I could access each element which I want as follows:
for (i =0;i < 5; i++)
for(j =0; j< 3; j++)
myArray[i*3+j] = ...
I know I could just copy the vector to the array element by element, but I was wondering if there is a method that directly addresses the vector to array conversion. I also know that the vector can me addressed as iVector[i][j] , but unfortunately it needs to be an array as it will be sent to a GPU and GPUs dont understand vectors.

Just use std::copy 5 times.
int* ptrArray = myArray;
for (i =0;i < 5; i++) {
std::copy(iVector[i].begin(), iVector[i].end(), ptrArray);
ptrArray += iVector[i].size();
}

There's really nothing you can do here except copy it into an array. The GPU will not understand any abstraction you create any more than it can understand std::vector. All you can do is make an array and copy it over.

Vectors supposed to store the elements in a linear fashion, so in theory you can refer to the entire underlying vector (only a single vector):
std::vector<int> numbers;
int data[4] = &(numbers[0]);
Similarily, perhaps you can try the same approach for the 2D version.
However in your place I would consider to use a class that is specifically designed to handle matrices (it is easy to write one similar to std::vector().

Or you can use plain old C.
You first initialize the array size to be the number of rows * the number of columns your vector of vectors has. Then you use memcpy to copy each vector to the array.
vector<vector<int> > v = { {1,2},{3,4},{5,6} }; //v is 3 by 2 matrix
int *arr = (int*)malloc( (3*2) * sizeof(int)); // arr has size 3*2 = 6
for (int i = 0; i < 3; i++)
memcpy(arr + v[i].size() * i, &(v[i][0]), v[i].size() * sizeof(int));
Here's a function that I wrote that does this for you:
template<typename T>
T *vectorToArray(vector<vector<T> > const &v) {
T *rv = (T*)malloc((v.size()*v[0].size()) * sizeof(T)); //Assuming all rows have the same size
for (unsigned i = 0; i < v.size(); i++)
memcpy(rv + v[i].size() * i, &(v[i][0]), v[i].size() * sizeof(T));
return rv;
}
So now you can do something like this:
vector<vector<int> > v = { {1,2},{3,4},{5,6} }; //v is 3 by 2 matrix
int *arr = vectorToArray(v);
I hope this helps

Related

Reserve 2D Vector in C++ and copy data from array

I hope to use vector to process the 2d array data obtained by calling a third-party library.
Although I can simply use the loop to assign values one by one, But I prefer to use methods such as insert and copy to deal with this.
I found that reserve doesn't seem to work here. So I used resize instead.
double **a = new double *[1024];
for (int i = 0; i < 1024; ++i) {
a[i] = new double[512];
}
std::vector<std::vector<double>> a_v;
a_v.resize(1024, std::vector<double>(512));
// Copy a -> a_v
I made these attempts:
// Not Working, just 0 in vector
for (int i = 0; i < 1024; ++i){
a_v[i].insert(a_v[i].end(), a[i], a[i] + 512);
}
Is there any good way to solve this problem.
For a 1D array I write like this:
double *b = new double[1024];
std::vector<double> b_v;
b_v.reserve(1024);
b_v.insert(b_v.end(), b, b + 1024);
If the size of the source array is fixed, it is strongly recommended to use std::array instead of std::vector. std::array has continuous memory layout for multidimensional structures, thus std::memcpy can be used for copy if the source array is also continuous in memory.
Look back to the original question. If you want to construct a std::vector<std::vector<double>> from the source array, use a single loop to construct 1D vectors from the source:
std::vector<std::vector<double>> a_v;
a_v.reserve(1024);
for (int i = 0; i < 1024; ++i) {
a_v.emplace_back(std::vector<double>(&(a[i][0]), &(a[i][512])));
}
If there is already a std::vector<std::vector<double>> with the proper size, and you literally just want to do a copy from the source, use the assign member function:
for (int i = 0; i < 1024; ++i) {
a_v[i].assign(&(a[i][0]), &(a[i][512]));
}
std::vector<std::vector<double>> a_v;
a_v.resize(1024, std::vector<double>(512));
is just
std::vector<std::vector<double>> a_v{1024, std::vector<double>(512)};
Unfortunately there is no vector constructor that takes over ownership of a C-style array. So you have to copy all 1024 * 512 doubles. And with the above definition of the vector you needlessly initialize all the doubles before you overwrite them.
You can do it with reserve so none of the double get initialized before you overwrite them and no vector gets copied or moved:
std::vector<std::vector<double>> a_v;
a_v.reserve(1024);
for (std::size_t i = 0; i < 1024; ++i) {
a_v.emplace_back();
std::vector<double> &b_v = a_v.back();
b_v.reserve(512);
b_v.insert(b_v.end(), a[i], a[i] + 512);
}

Define an array which the number of rows(clos) is unknown in C++

I have a 2048x2048 matrix of grayscale image,i want to find some points which value are > 0 ,and store its position into an array of 2 columns and n rows (n is also the number of founded points) Here is my algorithm :
int icount;
icount = 0;
for (int i = 0; i < 2048; i++)
{
for (int j = 0; j < 2048; j++)
{
if (iout.at<double>(i, j) > 0)
{
icount++;
temp[icount][1] = i;
temp[icount][2] = j;
}
}
}
I have 2 problems :
temp is an array which the number of rows is unknown 'cause after each loop the number of rows increases ,so how can i define the temp array ? I need the exact number of rows for another implementation later so i can't give some random number for it.
My algorithm above doesn't work,the results is
temp[1][1]=0 , temp[1][2]=0 , temp[2][1]=262 , temp[2][2]=655
which is completely wrong,the right one is :
temp[1][1]=1779 , temp[1][2]=149 , temp[2][1]=1780 , temp[2][2]=149
i got the right result because i implemented it in Matlab, it is
[a,b]=find(iout>0);
How about a std::vector of std::pair:
std::vector<std::pair<int, int>> temp;
Then add (i, j) pairs to it using push_back. No size needed to be known in advance:
temp.push_back(make_pair(i, j));
We'll need to know more about your problem and your code to be able to tell what's wrong with the algorithm.
When you define a variable of pointer type, you need to allocate memory and have the pointer point to that memory address. In your case, you have a multidimensional pointer so it requires multiple allocations. For example:
int **temp = new int *[100]; // This means you have room for 100 arrays (in the 2nd dimension)
int icount = 0;
for(int i = 0; i < 2048; i++) {
for(int j = 0; j < 2048; j++) {
if(iout.at<double>(i, j) > 0) {
temp[icount] = new int[2]; // only 2 variables needed at this dimension
temp[icount][1] = i;
temp[icount][2] = j;
icount++;
}
}
}
This will work for you, but it's only good if you know for sure you're not going to need any more than the pre-allocated array size (100 in this example). If you know exactly how much you need, this method is ok. If you know the maximum possible, it's also ok, but could be wasteful. If you have no idea what size you need in the first dimension, you have to use a dynamic collection, for example std::vector as suggested by IVlad. In case you do use the method I suggested, don't forget to free the allocated memory using delete []temp[i]; and delete []temp;

How to create a two dimensional array of given size in C++

I need to create a square matrix of a given size. I know how to create a dynamic one-dimensional array of a given size. Doesn't the same work for two dimensinal arrays like the lines below?
cin>>size;
int* a[][]=new int[size][size]
int* a[][]=new int[size][size]
No, this doesn't work.
main.cpp:4: error: only the first dimension of an allocated array may have dynamic size
new int[size][size];
^~~~
If the size of the rows were fixed then you could do:
// allocate an array with `size` rows and 10 columns
int (*array)[10] = new int[size][10];
In C++ you can't have raw arrays with two dimensions where both dimensions are dynamic. This is because raw array indexing works in terms of pointers; for example, in order to access the second row a pointer to the first needs to be incremented by the size of the row. But when the size of a row is dynamic the array doesn't know that size and so C++ doesn't know how to figure out how to do the pointer increment.
If you want an array with multiple dynamic dimensions, then you need to either structure the array allocations such that C++'s default array indexing logic can handle it (such as the top answers to this duplicate question), or you need to implement the logic for figuring out the appropriate pointer increments yourself.
For an array where each row has the same size I would recommend against using multiple allocations such as those answers suggest, or using a vector of vectors. Using a vector of vectors addresses the difficulty and dangerousness of doing the allocations by hand, but it still uses more memory than necessary and doesn't allow faster memory access patterns.
A different approach, flattening the multi-dimensional array, can make for code as easy to read and write as any other approach, doesn't use extra memory, and can perform much, much better.
A flattened array means you use just a single dimentional array that has the same number of elements as your desired 2D array, and you perform arithmetic for converting between the multi-dimensional indices and the corresponding single dimensional index. With new it looks like:
int *arr = new int[row_count * column_count];
Row i, column j in the 2d array corresponds to arr[column_count*i + j]. arr[n] corresponds to the element at row n/column_count and column n% column_count. For example, in an array with 10 columns, row 0 column 0 corresponds to arr[0]; row 0, column 1 correponds to arr[1]; row 1 column 0 correponds to arr[10]; row 1, column 1 corresponds to arr[11].
You should avoid doing manual memory management using raw new and delete, such as in the case of int *arr = new int[size];. Instead resource management should be wrapped up inside a RAII class. One example of a RAII class for managing dynamically allocated memory is std::vector.
std::vector<int> arr(row_count * column_count);
arr[column_count*i + j]
You can further wrap the logic for computing indices up in another class:
#include <vector>
class Array2d {
std::vector<int> arr;
int columns;
public:
Array2d(int rows, int columns)
: arr(rows * columns)
, columns(columns)
{}
struct Array2dindex { int row; int column; };
int &operator[] (Array2dindex i) {
return arr[columns*i.row + i.column];
}
};
#include <iostream>
int main() {
int size;
std::cin >> size;
Array2d arr(size, size);
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
arr[{i, j}] = 100;
}
}
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
std::cout << arr[{i, j}] << ' ';
}
std::cout << '\n';
}
}
If you're using C++11 you can also use std::array.
const int iRows = 3, iCols = 3; // number of rows and columns
std::array<std::array<int, iCols>, iRows> matrix;
// fill with 1,2,3 4,5,6 7,8,9
for(int i=0;i<iRows;++i)
for(int j=0;j<iCols;++j)
matrix[i][j] = i * iCols + j + 1;
This class also allows for bounds checking by using the function
std::array::at
which (just like operator[]) returns a const reference if the array-object is const-qualified or a reference if it is not. Please note that
std::array
is not a variable-sized array-type, like
std::vector
You can use std::vector:
std::vector<std::vector<int*>> a(size, std::vector<int*>(size));
This will create a dynamically allocated 2D array of int* with width and height equal to size.
Or the same with new:
int*** a = new int**[size];
for (size_t i = 0; i < size; ++i)
a[i] = new int*[size];
...
for (size_t i = 0; i < size; ++i)
delete a[i];
delete a;
Note that there's no new[][] operator in C++, you just have to call new[] twice.
However, if you want to do it with new and delete instead of std::vector, you should use smart pointers instead of raw pointers, for example:
std::unique_ptr<std::unique_ptr<int*>[]> a(new std::unique_ptr<int*>[size]);
for (size_t i = 0; i < size; ++i)
a[i].reset(new int*[size]);
...
// No need to call `delete`, std::unique_ptr does it automatically.

2D pointer pointing 2D array in C

How to make a 2d pointer like **check point a 2d array like
mycheck[][]?
How to convert a 1d like check[16], to 2d array like mycheck[4][4]?
My attempt
float (*mycheck)[4] = (float (*)[4]) check;
But if second time I want to use mycheck again for some other 1d array, how can I do? My attempt:
float (*mycheck)[4] = (float (*)[4]) other1darray;
this will definitely give a re-declaration error.
The answer to the first question is that you cannot do that. All you can do is allocate some memory and copy the data over.
The answer to the second question is very simple
mycheck = (float (*)[4]) other1darray;
You only have to declare variables once, after that just use the variable name.
Array a[] decays to a pointer to the first element when you drop the []. This does not happen recursively, in other words, it doesn't work for a[][].
Secondly, you can't assign arrays in C. You can ONLY initialize them. You will have to set each member yourself.
You can create a 2D array in C like this.
Use a typedef to make it easier.
typedef int **matrix;
matrix create2Darray(int row, int col)
{
int idx;
matrix m = malloc(row * sizeof(int*));
for (idx = 0; idx < row; ++idx)
{
m[idx] = malloc(col * sizeof(int));
}
return m;
}
And then call this in another function;
matrix check = create2Darray(2, 2);
To assign a 1D array to a 2D array you can assign the pointers to the right position in the array. An example below. It also show how to create a 2D array dynamically, but I commented it out, since it is not needed for the example.
#include <stdio.h>
#include <stdlib.h>
int main()
{
float **matrix;
float *array;
array = (float *) malloc(16 * sizeof(float));
for (size_t idx = 0; idx != 16; ++idx)
{
array[idx] = idx;
}
matrix = (float **) malloc(4 * sizeof(float *));
for (size_t idx = 0; idx != 4; ++idx)
{
// matrix[idx] = malloc(4 * sizeof(int));
matrix[idx] = &array[idx * 4];
}
for (size_t row = 0; row != 4; ++row)
{
for (size_t col = 0; col != 4; ++col)
{
printf("%.1f ", matrix[row][col]);
}
printf("\n");
}
}
Note: this makes the 1D array and 2D array point to the same memory. If you change something in the 1D it also changes in the 2D and vice-versa. If you don't want this, first copy the array.

Need help regarding Dynamic Memory Allocation for two dimensional arrays in C++

I had been trying to allocate dynamic memory for a two-dimensional array. After searchin a lot I've found a code that looks easier than others still I'm unable to understand each and every detail of it. Can someone explain me how does the following code assigns memory to the array dynamically. Really looking forward for help and sorry but I'm new to C++ and want to learn it.
void main()
{
int m,n;
cin>>m;
cin>>n;
//Allocate
int *a = new int[m*n];
//Use a[m][n]
for( int i = 0 ; i < m ; i++)
for ( int j = 0 ; j < n ; j++)
a[i*n + j] = 1;
}
The code just uses a single memory block to represent all elements, so to access a sample ( i, j ) it needs to calculate the index being i * num_rows + j (or num_colums depending how you look at it).
But as commented, don't use new int...., use something like
std::vector< int > a( m * n );
First of all, what you're doing, is adding 1 to different slots of a ONE-dimensional array.
Here's a commented version of your code:
int *a = new int[m*n]; // declares a pointer a, that points to a newly
// allocated space on the heap, for an array of size m*n.
for( int i = 0 ; i < m ; i++) // loop through m number of times
for ( int j = 0 ; j < n ; j++) // loop through n number of times PER m
a[i*n + j] = 1; // assigns 1 to a spot [i*n + j]
THIS is how you make a dynamic 2D array (in other words, array of pointers to arrays):
const int sizeX = 10;
const int sizeY = 5;
int** arrayOfPointers = new int*[sizeX];
for(int i = 0; i < sizeX; i++)
arrayOfPointers[i] = new int[sizeY];
Then, you can add multiple elements to that array using a double loop (NOT TESTED):
for(int i = 0 ; i < sizeY ; i++) // loop through all the rows
for (int j = 0 ; j < sizeX ; j++) // loop through all columns for row i
arrayOfPointers[i][j] = i*j; // assigns i*j to a spot at row i, column j
This is how you can print out the contents of the 2D array:
for(int i = 0 ; i < sizeY ; i++) {
for (int j = 0 ; j < sizeX ; j++)
cout << arrayOfPointers[i][j];
cout << endl; // go to the next line when the row is finished
}
First, let me point out that this is not a two-dimensional array, but rather a one-dimensional one. You can see that int* a = new int[ m*n ] allocates an array for integers of size m*n.
To obtain a two-dimensional array, you might use int** a = new int*[m]. Note the two asterisks (*) that are used here. Having allocated the "first" dimension of the array, you now have to allocate the second one via:
for( int i = 0; i < m; i++ )
{
a[i] = new int[n];
}
Afterwards, you can loop over m and n and use a[i][j] to access the array contents.
Using the STL in C++, you can obtain two-dimensional arrays by using a two-dimensional vector, like so:
std::vector< std::vector<int> > array( rows,
std::vector<int>( columns ) );
This would allocate a two-dimensional vector containing integers, with rows elements in the first dimension and columns elements in the second dimension. Such use is sometimes frowned upon, but std::vector manages memory for your, which might be nice.
Despite what Paul R said and which I fully support, the comment in the code above is wrong, you cannot use a[m][n] for proper addressing of an array that has been allocated as one dimensional memory.
what you can do, if you really must work without using C++ standard containers like vector or array is to allocate the full block and then store addresses to the start of the rows
int** createTwoDimMatrix(unsinged int rows, unsigned int columns)
{
int** rowAdressTable = new int*[rows];
int* baseMemory = new int[rows*columns];
//fill the rowAddressTable
for(unsinged int r=1; r<rows; ++r)
{
rowAdressTable[r] = rowsAdressTable[r-1]+columns*sizeof(int)
}
return rowAdressTable;
}
But let me repeat: Please, consider using C++ containers
For the memory it doesn't matter what kind of arrays you have they are all stored as one block of memory, those can the visualised as an 1d array.
In this example, since you want to cave an m x n array you alocate a block of m*n size. The difference between this way and the others is that now you have to acess your array as 1d.
For exemple having the follwoing 2d array:
1 2 3
4 5 6
7 8 9
It will be stored in the memory as follows:
1 2 3 4 5 6 7 8 9
I think you can see the pattern: in order to acces a[i][j] from your 2d array, the 1d equivalent would be a[i*dim+j] where dim is the length of your row.
The way you access your array depends solely on the way you allocate it. In order to be able to acces you elements directly as arr[i][j] you have to allocate the memory ass follows:
int **arr = new int *[n];
for (int i=0; i<n; i++)
arr[i] = new int [m];
This will create an nxm array.
Dynamic is like
int *p = new int [10][10]
then *(p+(i*noofcols)+j) gives value