How to get constant size of vector for an array declaration? - c++

I am reading the data from text file which is basically has rows and columns of double data types.
Part of the code is as shown below:
m_data = vector<vector<double> >(columns, vector<double>(lineCount - 3));
for (int x = 0; x < lineCount - 3; x++)
{
for (int y = 0; y < columns; y++)
{
m_data[y][x] = total_Data[it]; //total_Data is the complete data set read from a file
it++; //which contain all data sets from a simulation and they are
//separated into vectors here in this code
}
}
size_t len = m_data[1].size(); //m_data[1] vector represents the signal data set
double signaldata[len];
copy(m_data[1].begin,m_data[1].end,signaldata);
So the problem is when I copy the data from vector to array it requires the constant length of the array for initialization. But size() gives the length of the vector which is not a constant.
And sizeof(vector) returns the size of the object itself which is 16 bytes.
So how I can overcome this problem of getting a constant size from vector for array initialization

The answer is: You can't.
An std::vector is designed to have dynamic size, that is its size can change at runtime (i.e by loop from user input). In C++ it is not legal to create an 'array' of a non-compile time constant size. You can however create a dynamically allocated 'array' with new (e.g auto my_array = new char[vector.size()]). You really should not do this however, especially without doing any sanity checks on the size of the vector.
An alternative would be to use std::vector directly. If you have to work with an older (or C) API which requires a pointer to the beginning of your 'array' as an argument you can use vector::<T>::data which will return &vector[0].
So if I have this code:
void my_old_api_function(char* c) {
...
}
I can do this:
std::vector<char> my_data;
my_data.emplace_back('c');
...
my_old_api_function(my_data.data()); // Pass a pointer to the first element

Related

How to convert between flat and multidimensional arrays without copying data?

I've got some data structured as a multi-dimensional array, i.e. double[][], and I need to pass it to a function that expects a single linear array of double[] along with dimensional metadata for the multi-dimensional representation.
For example, I might have a 3 x 5 multidimensional array, which I need to pass as a 15-element flat array along with height and width parameters so that the function knows it is a 3x5 array rather than a 5x3 array.
The function will then return a flat array and size metadata, which I need to use to convert the data back into a multidimensional type.
I believe the data layout in memory is exactly the same for both the flat and multi-dimensional representations; the only difference is how the indexing operations are performed. So I'd like to do the "conversion" with typecasting rather than copying the array values.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
I actually know what the dimensions of the multi-dimensional array will be at compile time. The array sizes aren't dynamic.
The most correct way has been given by #Maxim Egorushkin and #ypnos: double *flat = &multi[0][0];. And it will work fine with any decent compiler. But unfortunately is not valid C++ code and invokes Undefined Bahaviour.
The problem is that for an array double multi[N][M]; (N and M being compile time contant expressions), &multi[0][0] is the address of the first element of an array of size M. So it is legal to do pointer arithmetics only up to M. See this other question of mine for more details.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
The address of the first array element coincides with the address of the array. You can pass around the address of the first element, no casting is necessary.
I would assume the most popular way to do it is:
double *flat = &multi[0][0];
This is how it is done in C, and you do operate with simple C arrays.
You could also have a look at std::array in your use case (dimensions known at compile time), but that one is not multi-dimensional, so if you would cascade it, you would lose the contiguous layout.
You can use cast to a reference to an array. This require to use some fancy C++ type syntax but in return it allows to use all features that work on arrays, like for each loop.
#include <iostream>
using namespace std;
int main()
{
static constexpr size_t x = 5, y = 3;
unsigned multiArray[x][y];
for (size_t i = 0; i != x; ++i)
for (size_t j = 0; j != y; ++j)
multiArray[i][j] = i * j;
static constexpr size_t z = x * y;
unsigned (&singleArray)[z] = (unsigned (&)[z])multiArray[0][0];
for (const unsigned value : singleArray)
cout << value << ' ';
cout << endl;
return 0;
}
Take into account that this and other methods basing on casts work only with real multi-dimensional arrays. If it is an array of arrays (like unsigned **multiArray;), it isn't allocated in a continuous block of memory and a cast cannot bypass that.

Assign values from vector to dynamic array (C++)

I have a vector of vertices of a line called lineVertices and I am going to pass this data to draw an OpenGL shape, so this vector must be in the form of an array, I'm assuming. I've tried the following code:
float* lineArray = new float[lineVertices.size()]();
for (unsigned i = 0; i < lineVertices.size(); i++) {
lineArray[i] = lineVertices.at(i);
}
However, it appears that the each element of the vector is getting assigned to the first element of the array only. Even though the lineArray identifier is a pointer to the first element, is there another way to access the different elements of the dynamic array?
If it helps, when I am debugging, it says that the size of lineArray is always 1, although lineVertices' size is clearly greater than 1.
I have also tried the code below, but this also does not work.
float* lineArray = &lineVertices[0];
Any help is appreciated!
You can pass a std::vector directly to OpenGL functions taking a pointer to an array. Just use the ::data() member function. Example:
std::vector<float> vec = ...;
glVertex2fv(vec.data()); // only uses the first two elements
OpenGL functions like this take a pointer to one or more elements. This doesn't have to be a raw array created with new; it just has to be a pointer to a consecutive list of elements. Use vector.data() to get a pointer to a std::vector's contents (first element).
If you really want to create a new array with manual memory management, you can do this (same effect as the code you posted):
float* arr = new float[vec.size()]; // NO () - not a constructor, but operator new[]
for (size_t i = 0; i < vec.size(); i++) {
arr[i] = vec[i];
}

How to get the dimensions of a 2d dynamic array of strings in C++?

I have a dynamically populated array of strings in C++:
string** A;
it is populated like this:
A = new string*[size1];
and then:
for (unsigned int i = 0; i < size1; i++)
{
A[i] = new string[size2];
for (unsigned int j = 0; j < size2; j++)
{
A[i][j] = whatever[j];
}
}
elsewhere, I want to find out the dimensions (size1 and size2).
I tries using this:
sizeof(A[i]) / sizeof(A[i][0])
but it doesn't work.
Any ideas ?
Thanks
When you allocate memory via new T[N], the value N is not stored anywhere . If you need to know it later, you will need to keep track of it in your code.
There are pre-existing classes for allocating memory that also remember the length that was allocated. In your code:
vector<vector<string>> A(size1, vector<string>(size2));
// (code to populate...)
then you can access A.size() to get size1, and A[0].size() to get size2.
If the dimensions are known at compile-time you may use array instead of vector.
It is very simple to find the size of a two dimensional (more exactly of one-dimensional dynamically allocated arrays) array. Just declare it like
std::vector<std::vector<std::string>> A;
and use
std::cout << A.size() << std::endl;
As for your approach then you have to store the sizes in some variables when the array is allocated.
If you are learning C++, I would recommend that you learn Classes. With a class you can encapsulate int variables along with your 2D array that you can use to store the dimensions of your array. For example:
class 2Darray{
string **array;
int rows;
int cols;
}
You can then get the dimensions of your 2Darray object anytime by reading these member variables.
vectors will do this for you behind the scenes but its good for you to learn how to do this.
You can't create an array just using pointer operator. Every array is basically a pointer with allocated memory. That's why compiler wants constant before creating array.
Basically; sizeof(A[i]) won't give you the size of array. Because sizeof() function will return the a pointers size which is points to A[i] location. sizeof(A[i]) / sizeof(A[i][1]) will probably give you 1 because you are basically doing sizeof(int)/sizeof(int*)
So you need to store the boundary yourself or use vectors. I would prefer vectors.
Can't get array dimensions through pointer(s)

C++ Pointer of Array of Ints Initialization

I want to have an array accessible by all functions of a class.
I put the array as private variable in the header file.
private:
int* arrayName;
In the .cpp file where I implement the class, the constructor takes in an int value (size) and creates the array. The goal is to fill it up
ClassName::ClassName(int numElements){
arrayName = new int[numElements]; //make arrays the size of numElements
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
}
I feel like this is quite inefficient. I know you can do int array[5] = {0}; but how do you do it when you don't initially know the size.
If you want to zero-initialize a newed array, just do value-initialize it. This has the effect of zero-initializing its elements:
arrayName = new int[numElements]();
// ^^
But you really want to be using an std::vector<int>.
private:
std::vector<int> vname;
and
ClassName::ClassName(int numElements) : vname(numElements) {}
This way you don't have to worry about deleting an array and implementing copy constructors and assignment operators.
You can use the memset function:
memset(arrayName,0,sizeof(int)*numElements);
This void * memset ( void * ptr, int value, size_t num ); function sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
To use it you must include the string.h header file.
For more information: http://www.cplusplus.com/reference/cstring/memset/
What you want to do is progressively expand the array on demand.
arrayName = new int[numElements];
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
The above code (what you gave) will give you an array of size numElements, and THEN the for loop will fill it. This is allocated now, and can't, as I understand it, be simply or easily resized (memset will overwrite previously held values in the array).
You could copy the whole array over every time you want to resize it:
int * oldarr = new int[OldSize];
//fill your old array
int * newarr = new int[NewSize];
for(int i = 0; i<OldSize; i++)
newarr[i] = oldarr[i];
Other than that, you could make the array much larger, or you could use various STLs, such as std::vector. Vector can be increased with a simple push_back function, and allows [] operator access (like arr[5] and whatnot).
Hope this helps!

Access Violation with static arrays?

I need to parallelise an application using win32 threads. One of the portions of the code involves modifying an static array using threads.
I pass the array as a parameter like this:
struct threadParameter {
float **array;
int row;
}
An example code would be like this:
// Main
float data[100][100]
for (int i = 0; i < 100; i ++) {
tp = (*threadParameter) new threadParameter;
tp->array = (float **) data;
tp->row = i;
AfxBeginThread... // Begin thread code
}
// Thread Code
UINT myThread(LPVOID param) {
threadParameter *pp = (threadParameter *) param;
for (int j = 0; j < 100; j ++) {
pp->array[pp->row][j] = NEWVALUE;
}
}
However, when executing the project, I get an "Access Violation Error" when I try to acceess the array via the **array pointer. This problem does not occur if the array data is
dynamic. Is there any way to sort this problem out (I am not allowed to change the array data from static to dynamic)?
Static arrays are NOT pointers to pointers -- the entire array is a single huge chunk of data, and addressable with a single pointer, namely, the pointer to the base of the array. Hence
tp->array = (float **) data;
is incorrect, because you're dereferencing a number inside the array. (The fact that you needed to cast also should've raised a red flag, since arrays are implicitly converted to the appropriate pointer types.)
That's why the common phrase "arrays are just pointers" is incorrect; it's half-true for single-dimensional arrays, but completely false with multidimensional arrays. If you need to use two indices, convert a single index into a row-column index by multiplying the row by the row size, then adding the column and indexing into the array with a pointer.