I am new to vector programming in C++. I want to initialize 2D matrix of unknown size so i came to vector side. I have two files 1) .h and 2).cpp. In .h file i initialized the vector like this
vector<vector<double> > vector_stor;
Then in .cpp after getting the size of each dimension from another source i re-sized the vector like this
size_X=5; //assumption
size_Y=5; //assumption
vector_stor.resize(size_X);
for(int i=0;i<size_X;i++)
vector_stor[i].resize(size_Y);
Now i want to store a data from a .mat file, initially read by matIO library, using Mat_VarRead function like this
Mat_VarReadData(vector_stor); //there are other arguments also but for demo just assume it
Mat_VarReadData take arguements in void* data and i have 2D vector. When i am doing like this its giving error
Error 1 error C2664: 'Mat_VarReadData' : cannot convert parameter
from 'std::vector<_Ty>' to 'void *'
Can anyone please guide me that how i can do this? It will be very helpful for me.
Edited Part:
matvar = Mat_VarReadInfo(mat,"data_struct");
field=Mat_VarGetStructFieldByName(matvar,"vect_stor",0);
int start[2]={0,0};
int stride[2]={1,1};
int edge[2];
edge[0]=field->dims[0];
edge[1]=field->dims[1];
Mat_VarReadData(mat,field,vector_stor,start,stride,edge);
where vector_stor is the variable for what i am seeking help.
Thanks
Check the ordering of your inputs to Mat_VarReadData. The function needs to be something like
Mat_VarReadData( ..., vector<vector<double> > mat, ... )
and you need to line up your inputs so that vector_stor lines up with that input.
If I have the function:
foo(int a, double b);
then when I call foo the first argument needs to be an int and the second a double. Same here, you need to match your input types to what your actually trying to pass.
Also check out:
http://libmatio.sourcearchive.com/documentation/1.3.3/group__MAT_g1845000f4fc6252ec5ff11c4b9f0759f.html
It looks like the function is going to dump the data into a single dimensional array, rather than a vector of vectors. Try this:
std::vector<double> mat;
mat.resize(size_X*size_Y);
// call Mat_VarReadData with &mat[0] as your void*
// now you can index with
mat[i*size_Y + j];
That assumes that the matrix is in column major form which MATLAB uses from memory. If it uses row major you'll need to index with
mat[i + j*size_X];
EDIT: If you're curious as to why &mat[0] or mat.data() (the second requires C++11, thanks for pointing it out) works is because the std::vector is guaranteed to be contiguous,see
Are std::vector elements guaranteed to be contiguous?
As others have already pointed out, you won't be able to pass neither vector <vector<double> > nor vector<double> directly to Mat_VarReadData in the form of void*, there's simply no safe way to do that. The best you can do is first to retrieve the data into some raw array, then convert it accordingly to the container you like.
I'm not familiar to MatIO, but I'll try to point you to the right direction. I took a look at the documentation for Mat_VarReadData. Not very helpful I must admit, but at any rate it states that any data can only be read once you have retrieved the information about the corresponding variable. That can be done using the function Mat_VarReadInfo. This function returns a matvar_t, which essentialy is a descriptor for variables. It seems to me, that matvar_t contains all the information you need to allocate data dynamically, that is, through the use of new[]. More precisely, matvar_t::data_size should hold exactly how many bytes are needed to store the data of a given variable.
I think that's more or less what you need to do:
warning, not tested
matvar_t* varInfo = Mat_VarReadInfo(matFileDescriptor, varName)
char* data = new char[varInfo->data_size];
Mat_VarReadData(matFileDescriptor, varInfo, (void*)(data), start, stride, edge);
I'll leave it to you to figure out what start, stride and edge actually stand for.
After you have the data read into the array data, you will have to convert it to the appropriate arithmetic type, probably double, but I can't be sure. Only then you will be able to fit them into a vector<double>. On this part I unfortunately can't help you, because it gets too deep into MatIO.
I understand you are struggling with basics c/c++ and also with MatIO. That's no simple library to be used by someone just starting out coding in c/c++, so I would strongly advise you to first carefuly read any documentations you have available on MatIO before trying any progress with your project. Some reading on basics c/c++ would also be very helpful.
Related
A C function API accepts uint8_t* and size_t as parameters:
bool foo(uint8_t* buff, size_t bufflen)
What is the best way to manage and handle in C++ layer invoking this API. Is string, vector or list a better option
Just make sure while calling this API from C++ you always pass a uint8_t type pointer . normal array uint8_t arr[x] (x is any +ve number) will also work. Just make sure address you passed has data of type uint8_t with correct size of the buffer.
e.g. uint8_t arr[6]; for this the call will be foo(arr,6);
You probably want std::vector<uint8_t> while passing data() and size().
You can't pass a container to the C function. You can still use one in your C++ code, but you'll need to pass a pointer to the data, in accordance to what the C function parameters are. Use a vector. This is equivalent to an array in C, in that the data is stored contiguously in memory.
std::vector<uint8_t> myData;
// ... fill myData
// for c++11 and later,
foo(myData.data(), myData.size());
// pre-c++11
foo(&(myData[0]), myData.size());
Is string, vector or list a better option?
Well, list is a non-starter, because it will not store the sequence in contiguous memory. In other words, the C code would not be able to take a pointer to the first element and increment it to get to the second element.
As for the other two, that depends on the rest of your C++ code. I would lean towards vector rather than string, but you haven't really provided enough context for that to be any more than a general feeling.
Usually I would go with a helper class that has an method that either takes a vector, or a custom structure that acts like a span - i.e. a pair<void*,int>, or perhaps even a span (but I'm not allowed the C++14 crayons).
If the data really is character-based the std::string and string spans can work well, but if it is really binary data, vector and vector spans are the better encapsulation, IMBO.
I still don't want to call that directly from application code if what is actually in there is structured data. You can easily write a method that takes an expected structure type and generates the pointer and sizeof(instance).
You can write a generic template that would accept any structure and convert it to a void*/char* and length, but that tends to open your code up to more accidents.
I am using C++ CURL library for sending emails.
My problem is that the text in my email may vary from time to time so I need to change size or dynamically re-allocate my variable:
const char *payload_text[10]
where 10 might be 20 or even 30
how can I change the size of this variable in my program?
By the way this variable must be allocated as I am using the example from CURL library:
https://curl.haxx.se/libcurl/c/smtp-mail.html
Whenever you are faced with a data structure that may need to change size you should be thinking std::vector.
In this specific case, a std::vector<std::string>> is what you want/need.
To pass the vector to a legacy API that expects a C-style array and a size, pass it std::vector::data() and std::vector::size(). A vector is guaranteed to be using contiguous memory, just like a C-style array, so the two interoperate well.
THANKS
It actually works just some points for others with the same problem:
In the function payload_source change the line:
data = payload_text.at(upload_ctx->lines_read)
What I was afraid to do and in the body of your code where you will fill the email array do the following thing:
payload_text.push_back(char_array)
The vector itself should be:
vector <const char*> payload_text
Again thank you all very much
I have searched on google but only found answers for single-dimension arrays.
I have a 3 dimension array storing data to be later processed by a function.
My array looks like this : levelcode[400][20][100]. It stores all the info that the decode level function needs. I get an stack overflow error immediately.
But how can i point to the entire array to get the values of it ( or how do i pass down the entire array? ) ?
I know i can technically call the function for each existing parameter but i think it would be faster and it would look better if the entire array was passed down or being used using a pointer of some sort.
How can i accomplish this?
I suggest you use a std::vector. It is basically a self managed grow-able array. It stores the data dynamically(heap) so you will be using the full system memory instead of the small bit of memory the program is given for automatic objects(stack). With your levelcode[400][20][100] you have 800,000 elements. if the array is of type int then you would more than likely need 3.2MB of space for the array. typically this is larger than than the space provided to the program and will cause a stack overflow
I would suggest you use single dimension vector and then you can use math to fake the 3 dimensions. This will make the data more cache friendly as multi-dimensional vectors do not have to have each dimension located right next to each other like a multi-dimensional array does.
So instead of having a
std::vector<std::vector<std::vector<some_type>>> name{DIM1, vector<vector<some_type>>{DIM2, vector<some_type>{DIM3}}};
and using it like
name[x][y][z]
We could have a
std::vector<some_type> name{DIM1 * DIM2 * DIM3};
and then you can access the elements with
name[x*DIM2*DIM3 + y*DIM3 + z]
Hmm, hello! I am trying to read a binary file that contains a number of float values at a specific position. As seemingly must be done with binary files, they were saved as arrays of bytes, and I have been searching for a way to convert them back to floats with no success. Basically I have a char* memory block, and am attempting to extract the floats stored at a particular location and seamlessly insert them into a vector. I wonder, would that be possible, or would I be forced to rely on arrays instead if I wished to save copying the data? And how could it possibly be done? Thank you ^_^
If you know where the floats are you can read them back:
float a = *(float*)buffer[position];
Then you can do whatever you need of a, including 'push_back'ing it into a vector.
Make sure you read the file in binary mode, and if you know the positions of the float in the file it should work.
I'd need to see the code that generated the file to be more efficient.
Currently I read arrays in C++ with ifstream, read and reinterpret_cast by making a loop on values. Is it possible to load for example an unsigned int array from a binary file in one time without making a loop ?
Thank you very much
Yes, simply pass the address of the first element of the array, and the size of the array in bytes:
// Allocate, for example, 47 ints
std::vector<int> numbers(47);
// Read in as many ints as 'numbers' has room for.
inFile.read(&numbers[0], numbers.size()*sizeof(numbers[0]));
Note: I almost never use raw arrays. If I need a sequence that looks like an array, I use std::vector. If you must use an array, the syntax is very similar.
The ability to read and write binary images is non-portable. You may not be able to re-read the data on another machine, or even on the same machine with a different compiler. But, you have that problem already, with the solution that you are using now.