I understand that reinterpret_cast may do it, but I think it did not do the data conversion. I don't want to loop over and do them one by one, and wonder whether there is an elegant way to do both the pointer type and data type conversion.
Thanks!
If, as I am assuming, you have some float* that points to the first element in an array of floats and you want to use them as ints then I suggest a few options:
If you don't want float, don't get floats. Just store an array of ints in the first place.
Likewise, if you don't want ints, then change your code to use floats throughout.
If you do indeed want to have an array of floats and at some point want to convert them to ints, do it when you need it. Use static_cast<int> to do the conversion on each element in a safe manner.
If you'd like to convert the whole array at once, then I suggest you do something like so:
float float_array[N] = /* ... */;
std::vector<int> ints(float_array, float_array + N);
Alternatively, if you really want to stick with arrays, use std::copy:
float float_array[N] = /* ... */;
int int_array[N];
std::copy(float_array, float_array + N, int_array);
The std::vector above is much preferred, however.
Related
I'm solving a question where a function is defined as following:
vector <int> func(int a, vector<vector<int>> B[]){
// Some stuff
}
I'm confused about why the second parameter is not simply vector<vector<int>> B. Why the extra [] part in the parameter? Can someone clarify the meaning of this?
The vector, B, is populated by a similar code snippet:
vector<vector<int>> B[10];
while(num--){
cin>>u>>v>>w;
vector<int> t1,t2;
t1.push_back(v);
t1.push_back(w);
B[u].push_back(t1);
t2.push_back(u);
t2.push_back(w);
B[v].push_back(t2);
}
Just as int foo(char str[]) is a function that takes a (c-style) array of characters, so int foo(vector<vector<int>> B[]) takes an array of vectors of vectors ... of integers. This means that it's three-dimensional data, requiring 3 indices to access the elements (fundamental data type; in this case, int), like B[i][j][k] = 5. Without the extra [] in the API it'd be two-dimensional data: a vector of vectors.
Note that int foo(char str[]) is equivalent to int foo(char str[5]) which is equivalent to int foo(char * str).
In C we usually add the [] to a function declaration to imply that we expect to receive an array of those elements; while * is often used when we expect at most one element. Likewise, adding the number [5] is basically just a comment to the user of the code that they expect 5 elements, but the compiler won't enforce this. These conventions carry over to C++ when we use these c-style arrays ... which is rare.
With c-style arrays there's either going to be a maximum array size in the comments somewhere; or, more commonly, it's provided as an input. That may be what the first argument of the function is supposed to represent.
I agree with KungPhoo here that this API looks suspiciously bad. I'd expect bugs/bad performance just because the choices seem very amateurish. The c-style array means the function can't know where the end of the c-style array is - but the vectors mean that we give up some of the (niche) benefits of c-style simplicity (especially because they're nested!). It seems to be getting the worst of both worlds. But, perhaps, there may be a very niche justification for the API.
B ist a static array (C-style) of 10 elements [0 .. 9]. It's not safe and this code is a terrible mess.
Better use std::array<std::vector<str::vector<int>>, 10> B; instead to have index checking.
I have a 1D dimensional vector of floats I just read in from a file.
std::vector<float> result(s.size() / sizeof(float));
I want to use this data like this
myTable[rl][gl][bl][0];
So is there any easy way to convert my 1D vector to a multidimensional vector or multidimensional array that is simple?
float myTable[100][10][20][30];
vector<vector<vector<vector<int> >>> myTable;
Where I can still easily use the indexing that is setup all over the code.
and not have to convert it to a 1D access like : myTable[indexmathhere]
I wouldn't actually rewrite the data, unless you have cache requirements (though we don't know anything about the layout of your data).
Store the vector inside a class, and write an accessor function that takes four index arguments and performs the necessary arithmetic to flatten them into the single vector index.
class MyMatrix
{
std::vector<float> result;
public:
float at(int r, int g, int b, int a) const
{
return result[r+W*g+W*H*b+W*H*D*a]; // or whatevs
}
};
You could even write some operator() overloads, but you'd need three proxy types to get four dimensions of indexing out of that.
If you have fixed size array you probably should use std::array.
Something like it is in this question: Multidimensional std::array
Unfortunately, there is no oneliner to put your data into this array, you need to do it manually.
While passing a 2-Dimensional array we have to specify the the column.
eg:
void funtion1(a[])// works
{
}
void function2(a[][4])//works
{
}
void function3(a[][])//doesn't work
{
}
What could be the possible reasons that the function3 is considered an incorrect definition.
Is there a different way to define function3 so that we can leave both row and column blank.
Reading some replies:
Can you explain how x[n] and x[] are different?. I guess the former represents a specific array position and the latter is unspecified array. More explanation will be deeply appreciated.
You cannot pass a 2D array without specifying the second dimension, since otherwise, parameter "a" will decay to a pointer, the compiler needs to know how long the second dimension is to calculate the offsets (reason is that 2D array is stored as 1D in memory). Therefore, compiler must know size of *a, which requires that the second dimension be given. You can use vector of vectors to replace 2D array.
with void function2(a[][4]) it knows that there are 4 elements in each row. With void function3(a[][]) it doesn't know, so it can't calculate where a[i] should be.
Use a vector, since it's c++
C style arrays don't work the way you think. Think of them as a block of memory, and the dimensions tell the compiler how far to offset from the original address.
int a[] is basically a pointer and every element is an int, which means a[1] is equivalent of *(a + 1), where each 1 is sizeof(int) bytes. There's no limit or end (simplistically speaking) of the a array. You could use a[999999] and the compiler won't care.
int a[][4] is similar, but now the compiler knows that each row is 4*sizeof(int). So a[2][1] is *(a + 2*4 + 1)
int a[][] on the other hand, is an incomplete type, so to the compiler, a[2][1] is *(a + 2*?? + 1), and who know what ?? means.
Don't use int **a, that means an array of pointers, which is most likely what you don't want.
As some have said, with STL, use vectors instead. It's pretty safe to use std::vector<std::vector<int> > a. You'll still be able to get a[2][1].
And while you're at it, use references instead, const std::vector<std::vector<int> > &a. That way, you're not copying the whole array with each function call.
how does compiler calculate address of a[x][y]?
well simply:
address_of_a+(x*SECOND_SIZE+y)
imagine now that you want
a[2][3]
compiler has to computes:
address_of_a+(2*SECOND_SIZE+3)
if compiler doesn't know SECOND_SIZE how it can compute this?
you have to give it to him explicitly. you are using a[2][1], a[100][13] in your code, so compiler has to know how to compute addresses of these objects.
see more here
If I manually type this script and call the calculator :
integer array[100];
Then my calculator will create a vector<int> object with the name "array" contains 100 elements.
But C++ code is unique. For example if I type and call :
integer array[100][100];
integer array[100][100][100];
//etc
Then the template vector<int> is illegal.... :(
So annoying! I tried but I could not find the better solution. Could anyone give me some hint?
This answer covers to generally different approaches.
To support arbitrarily nested, dynamically sized arrays (so the depth of the nested arrays is not limited during compile time), you should use something like the following.
The type of a variable in your scripting language should be either:
integer
float
(... other primitive types you want to support ...)
an array of any of these types (including array)
(... other container types such as an associative map if you want to support it ...)
This is typically done using a "variant" type, such as Boost Variant or QVariant in Qt. A variant type is basically a union of a set of types (so it is one of them) plus a type descriptor which tells which type it actually contains.
So an array of any type can be represented, also if this "any type" is an array again. So you can support a dynamic depth of nested arrays.
Note that the "array of any types" should actually be a vector of this variant type. The problem with Boost Variant is that you have to explicitly list the types it can hold as template arguments. This will result in a recursion:
boost::variant<int, float, ..., std::vector<boost::variant<..., ...> > >
^^^^^^^^^^^^^^^^^^^^^^^^
recursion
In Qt there is the type QVariant which can hold basically any type supported by Qt. QVariant is not a template class and thus its type doesn't contain such a recursion. I don't know if there is a comparable boost type, but I doubt it.
If your arrays can't be resized during execution of the script (or if they should be resized, you can allocate a new one and copy the contents), there is a simpler solution. Just store the arrays in a one-dimensional vector, also store the dimensions of the array in your scripting language in another vector. Then you can use an index method like the following.
class ScriptArray {
vector<int> dim;
vector<int> elements;
int getIndex(vector<int> indexList) const {
int multiplicator = 1;
int index = 0;
for (int i = 0; i < dim.size(); ++i) {
index = multiplicator * indexList[i];
multiplicator *= dim[i];
}
return index;
}
};
This is basically a generalization of the following idea. Consider a two-dimensional array (100 x 100 elements) you want to represent as a one-dimensional one (10000 elements). For any index in the original array (x, y) you can map this to a one-dimensional index for your internal array (x + 100 * y). For a three-dimensional array this just contains another multiplication (x + 100 * y + 100*100 * z) and so on...
The problem with this solution and resizing the array is that the elements "move" within the array when the size of a dimension changes (special case: last dimension, as this dimension is the "outermost" one). So either you can live with the fact that the array would be invalid when resized, or you copy the contents in a new array with the new size, or you implement some complicated resize method which carefully inserts spaces / removes some elements in the array at the correct places.
I am assuming that you have created your own language that you want to parse using C++. Your parser knows that you are defining a variable, since it finds the type integer before an identifier. What you then have to do is check if you have to create a normal variable or a multi-dimensional array.
If no brackets ([]) exist -> Normal variable
If brackets exist -> Make a loop to count how many there are. Then allocate nested
vectors. Only the final vector will have elements of type int.
So the easiest way to implement this is to forget about an array and just view it as a special case of a multi-dimensional array with only one bracket.
i have a std::vector, namely
vector<vector<vector> > > mdata;
i want pass data from my mdata vector to the GSL function
gsl_spline_init(gsl_spline * spline, const double xa[], const double ya[], size_t size);
as ya. i already figured out that i can do things like
gsl_spline_init(spline, &(mgrid.front()), &(mdata[i][j][k].front()), mgrid.size());
this is fine if i want to pass the data from mdata for fixed i,j to gsl_spline_init().
however, now i would need to pass along the first dimension of mdata, so for fixed j,k.
i know that for any two fixed indices, all vectors along the remaining dimensions have the same length, so my vector is a 'regular cube'. so the offset between all the values i need should be the same.
of course i could create a temporary vector
int j = 123;
int k = 321;
vector<double> tmp;
for (int i = 0: i < mdata.size(); i++)
tmp.push_back(mdata[i][j][k]);
gsl_spline_init(spline, &(mgrid.front()), &(tmp.front()), mgrid.size());
but this seems too complicated. perhaps there is a way to achieve my goal with pointer arithmetic?
any help is greatly appreciated :)
You really can't do that without redesigning the array consumer function gsl_spline_init() - it relies on the data passed being a contiguous block of data. This is not the case with you three-level vector - not only it is a cube but also each level has a separate buffer allocated on heap.
This can't be done. Not only with vectors, but even with plain arrays only the last dimension is a contiguous block of data. If gsl_spline_init took an iterator instead of array, you could try to craft some functor to choose appropriate data but I'm not sure it's worth trying. No pointer arithmetic can help you.