I am relatively new to C++ and kind of stuck in this problem. I have 999x1 vector of point coordinates and I want to convert it in 333x3 matrix dyanamically. Besides this, I am using different Cpp files for one project so the function which reads the points set is in different file. How to make this matrix and how should I access it in my main code?
I tried using vector<vector<float> > Mymatrix thing but you need to specify the rows and column size in this kind of definition which I cannot get until I read the file. If I try to declare above Mymatrix variable in the function which is reading the pointset file, its scope gets limited and I cannot use that Mymatrix in main.cpp.
Its little bit difficult to write the code here because it has many links with other files. I hope you have got my problem! Please help me in this issue...Thanks in advance!
vector is really just a container for array. So basically what you have is a int A[999] and want to convert this into int M[333][3];
Considering that in memory both a 1D and a 2D array are stored in a contiguous memory region, you can achieve this in several ways:
- use a pointer and two indexes i, j: the first 3 elements are your first row,
the next 3 elements your second row and so on.
int vector<int> v;
int *p, i=0,j=0; // i=[0..332], j=[0..2]
p=&v[0];
*(p+(i*3)+j); //this is the same as p[i][j];
Or declare matrix (either allocate static or dynamic memory for it) and copy all the elements int the matrix:
int M[333][3]; //i'll go with static allocation for this example
for(i=0;i<333;i++)
for(j=0;j<3;j++)
M[i][j] = v[i*3 + j];
choose which ever method you want - the advantage of the first one is that it does not us the extra memory.
You can create your MyMatrix as a pointer and pass to your function as parameter:
vector<vector<float> >* Mymatrix; //Don't forget to initialize the pointer
functionThatReadsFiles(Mymatrix); //That function makes changes to Mymatrix
With this, any changes you make to Mymatrix inside "functionThatReadsFiles" will remain after its call. Anyway, make sure you fully understand how to operate with pointers before trying this.
As #erlc says, you can also declare your function with:
void functionThatReadsFiles(vector<vector<float> >& Mymatrix);
And call just call it normally (without pointers), and again the changes will remain into your Mymatrix.
Related
I have a quite complex Problem and couldn't find out, where the Problem is. Part of the Problem might be, that i didn't fully understand the data structures. I have the following custom template class, with this member variables:
template <class T>
class Matrix
{
private:
T * *M; /* array of row pointers */
size_t n_rows, /* number of rows */
n_cols; /* number of columns */
size_t row_start, /* first row of submatrix */
col_start, /* first column of submatrix */
origcols; /* refers to original matrix */
bool hasownvalues, /* has matrix own value? */
initialized; /* are matrix values initialed? */
I also made a custom constructor, which makes a 2D array out of a file with tab-separated data:
Matrix(const std::string &filename)
{ do.stuff }
I'm not sure, if it is really important how this exactly works, it quite a bunch of code. if so, i could edit it later, but the constructor works well as long as i declare a single variable for such an object.
My problem occurs when i try to make a bunch of the objects and try to wrap them up in a vector. Lets say i have x different files, each containing data for a matrix. I also have a vector in which the filenames are stored:
std::vector<std::string> filenames{};
for (int idx = 3; idx < argc; idx++)
{
filenames.push_back(argv[idx]);
}
So far this code works and it is mandatory that i keep it unchanged to keep the rest of the program working.
The following is flexible and thats where i have problem:
std::vector<Matrix<T>> coredata; /* initialize the vector for the wrap */
...
for (auto& it : filenames)
{
Matrix<T> M(it); /* call the special constructor*/
coredata.push_back(M); /* add new object to the vector */
}
The first assignment works well, but from the second on it seems that it appends the new Matrix, but also overwrites the old one or at least a part of it. And in the third one i get a segmentation fault when running the program.
Some information of the program around:
the constructor works with space allocated by the "new" command, maybe that could be part of the problem.
the real size of the Matrix object isn't known before run time. (the arrays can be of different size), but i could arrange, that the read data in fact always is of the same size
T is constant within the vector. it can't happen, that M is sometimes Matrix int and sometimes Matrix float
the vector would be embedded in another superclass and the snippet above is part of a constructor of this class, coredata is a member variable.
I'm quite puzzled what the problem exactly is. Maybe some variables don't live long enough. I also thought of assigning just a reference to the address in the vector, but as far as i understand, a vector already stores just a reference, so it seems not that plausible.
I also thought of initializing the vector with a bunch of "0"-matrices and then overwrite them with the constructed objects. But i don't know how to do that and on top of that,
i don't know at compile time how many rows and columns the read Matrices will have.
Maybe a vector isn't a useful solution at all, i also thought of making a plain C-array.
But there i have the problem again, that i have to initialize this array first and can't just append another Matrix-Object to it.
I'm trying to pass a variable of type vector<vector<double> > to a function F(double ** mat, int m, int n). The F function comes from another lib so I have no option of changing it. Can someone give me some hints on this? Thanks.
vector<vector<double>> and double** are quite different types. But it is possible to feed this function with the help of another vector that stores some double pointers:
#include <vector>
void your_function(double** mat, int m, int n) {}
int main() {
std::vector<std::vector<double>> thing = ...;
std::vector<double*> ptrs;
for (auto& vec : thing) {
// ^ very important to avoid `vec` being
// a temporary copy of a `thing` element.
ptrs.push_back(vec.data());
}
your_function(ptrs.data(), thing.size(), thing[0].size());
}
One of the reasons this works is because std::vector guarantees that all the elements are stored consecutivly in memory.
If possible, consider changing the signature of your function. Usually, matrices are layed out linearly in memory. This means, accessing a matrix element can be done with some base pointer p of type double* for the top left coefficient and some computed linear index based on row and columns like p[row*row_step+col*col_step] where row_step and col_step are layout-dependent offsets. The standard library doesn't really offer any help with these sorts of data structures. But you could try using Boost's multi_array or GSL's multi_span to help with this.
The way I see it, you need to convert your vector<vector<double> > to the correct data type, copying all the values into a nested array in the process
A vector is organised in a completely different way than an array, so even if you could force the data types to match, it still wouldn't work.
Unfortunately, my C++ experience lies a couple of years back, so I can't give you a concrete example here.
Vector< Vector< double> > is not nearly the same as a double pointer to m. From the looks of it, m is assumed to be a 2-dimensional array while the vector is could be stored jagged and is not necessarily adjacent in memory. If you want to pass it in, you need to copy the vector values into a temp 2dim double array as pass that value in instead.
I have a 2d vector of string and need to isolate out three of the columns into 3 separate 1d arrays so i can convert them to doubles and perform operations on them.
Simply using:
for (int i = 0; i < 100; i++)
{
vectorname[i][2] = arrayname[i];
}
doesn't work and I don't understand why.
Sorry im new to coding and thanks in advance.
Thanks to first reply, i don't care if i remove the data or not, i just need it so i can operate on it, my vectors are declared as:
string vectorname[101][5];
string arrayname[99];
string arrayname2[99];
string arrayname3[99];
Ok I dont have my vectorname defined as a vector, it's just a 2d string, can i extract a column from that?
Do the columns still need to remain in the 2D vector, or be pulled out completely as independent data?
If you need independent data, I would do
vector<double> col(vectorname[i]);
Then manipulate col as needed. You could even do move construction if you don't need that data in the 2D vector anymore.
I think you have actual logic problems elsewhere though. Show us your vector declarations.
EDIT: What...? You're not declaring vectors at all. You're using pure arrays. And a 2D array shouldn't be called a vector. You're confusing other programmers with your name scheme.
The proper way to declare a vector of strings is
std::vector<string> vectorname(100);
And a vector of vector of strings (a 2D vector) is
std::vector<std::vector<string>(5)> vectorname(101);
But moreover, your dimensions mismatch. Your 1D vectors need to be the same length as the given dimension of your 2D, or 5 (101?) in this case.
If you're trying to copy the values along the first dimension of values, there's no direct constructor for that. You have to manually loop from 0 to 100 and say
arrayname[i] = vectorname[i][n];
Where n is your column number.
I've been working off of Passing a 2D array to a C++ function , as well as a few other similar articles. However, I'm running into a problem wherein the array I'm creating has two dimensions of variable size.
The initialization looks like:
int** mulePosition;
mulePosition = new int *[boardSize][boardSize][2];
The function looks like:
int moveMule (int boardSize, int ***mulePosition)
And the references look like
moveMule (boardSize, mulePosition)
Boardsize is defined at the beginning of the function, but may change per execution.
The array, properly sized, would be int [boardSize][boardSize][2].
Either use a plain '3-dimensional' array via
int* mulePosition = new int[boardsize*boardsize*2];
and address its elements calculating the offset from the beginning: mulePosition[a][b][c] is mulePosition[boardSize*2*a + 2*b + c],
or use array of arrays of arrays (which would correspond to your int*** declaration) or better (and simpler) vector of vectors of vectors, although the initialization would be a little more complex (you would need to initialize every array/vector).
Either use a std::vector<std::vector<int>> if boardSize is not a const or std::array<std::array<boardSize>, boardSize> (see Multidimensional std::array for how to initialize the std::array).
That being said, it looks like a good idea to hide this in a class Board which provides a nice interface.
I am developing a program in which one of the task is to read points (x,y and z) from a text file and then store them in an array. Now the text file may contain 10^2 or even 10^6 points, depending upon the text file user selects. Therefore I am defining a dynamic array.
For allocating a dynamic 2D array, I wrote as below and it works fine:
const int array_size = 100000;
float** array = new float* [array_size];
for(int i = 0; i < array_size; ++i){
ary[i] = new float[2]; // 0,1,2 being the columns for x,y,z co-ordinates
}
After the points are saved in the array, I write the following to deallocate the unallocated memory :
for (int i = 0; i < array_size; i++){
delete [] array[i];
}
delete [] array;
and then my program stops working and shows "Project.exe stopped working".
If I don't deallocate, the program works just fine.
In your comment you say 0,1,2 being the columns for x,y,z co-ordinates, if that's the case, you need to be allocating as float[3]. When you allocate an array of float[N], you are allocating a chunk of the memory of the size N * sizeof(float), and you will index them in the array from 1 to N - 1. Therefore if you need indeces 0,1,2, you will need to allocate a memory of the size 3 * sizeof(float), which makes it float[3].
Because other than that, I can compile and run the code without an error. If you fix it and still get an error, it might be your compiler problem. Then try to decrease 100000 to a small number and try again.
You are saying that you are trying to implement a dynamic array, this is what std::vector does and I would highly recommend that you use it. This way you are using something from the standard library that's extremely well tested and you won't run into issues by essentially trying to roll your own version of std::vector. Additionally this approach wraps memory better as it uses RAII which leverages the language to solve a lot of memory management issues. This has other benefits too like making your code more exception safe.
Also if you are storing x,y,z coordinates consider using a struct or a tuple, I think that enhances readability a lot. You can typedef the coordinate type too. Something like std::vector< coord_t > is more readable to me.
(Thanx a lot for suggestions!!)
Finally I am using vectors for the stated problem for reasons as below:
1.Unlike Arrays (not array object ofcourse), I don't need to manually deallocate unallocated memory.
2.There are numerous built in methods defined under vector class
Vector size can be extended at later stages
Below is how I used 2D Vector to store points (x,y,z co-ordinates)
Initialized (allocated memory) a 2D vector:
vector<vector<float>> array (1000, vector<float> array (3));
Where 1000 is the number of rows, and 3 is the number of columns
Once declared, values can be passed simply as:
array[i][j] = some value;
Also, at later stage I declared functions taking vector arguments and returning vectors as:
vector <vector <float>> function_name ( vector <vector <float>>);
vector <vector <float>> function_name ( vector <vector <float>> input_vector_name)
{
return output_vector_name_created_inside_function
}
Note: This method crates a copy of vector while returning, use pointer to return by reference. Even though mine is not working when I return vector by reference :(
For multi arrays I recommended use boost::multi_array.
Example:
typedef boost::multi_array<double, 3> array_type;
array_type A(boost::extents[3][4][2]);
A[0][0][0] = 3.14;