How to read a line in C++ [duplicate] - c++

vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.

In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);

Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row

You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.

If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.

vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).

Related

Vector assignment crashing

vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.
In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);
Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row
You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.
If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.
vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).

two dimensional vector matrices addition

vector<vector<int>> AsumB(
int kolumny, vector<vector<int>> matrix1, vector<vector<int>> matrix2) {
vector<vector<int>>matrix(kolumny);
matrix = vector<vector<int>>(matrix1.size());
for (int i = 0; i < kolumny; ++i)
for (int j = 0; i <(static_cast<signed int>(matrix1.size())); ++i)
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
return matrix;
}
Please tell me what I don't understand and help me solve this problem
because for 1dimensional vector this kind of description would work;
What about
vector<vector<int>> AsumB(vector<vector<int>> const & matrix1,
vector<vector<int>> const & matrix2) {
vector<vector<int>> matrix(matrix1);
for (std::size_t i = 0U; i < matrix.size(); ++i)
for (std::size_t j = 0U; j < matrix[j].size(); ++j)
matrix[i][j] += matrix2[i][j];
return matrix;
}
?
Unable to reproduce, and OP's reported compiler error doesn't look like it matches the code, so the problem is probably somewhere else.
However, there is a lot wrong here that could be causing all sorts of bad that should be addressed. I've taken the liberty of reformatting the code a bit to make explaining easier
vector<vector<int>> AsumB(int kolumny,
vector<vector<int>> matrix1,
vector<vector<int>> matrix2)
matrix1 and matrix2 are passed by value. There is nothing wrong logically, but this means there is the potential for a lot of unnecessary copying unless the compiler is very sharp.
{
vector<vector<int>> matrix(kolumny);
Declares a vector of vectors with the outer vector sized to kolumny. There are no inner vectors allocated, so 2D operations are doomed.
matrix = vector<vector<int>>(matrix1.size());
Makes a temporary vector of vectors with the outer vector sized to match the outer vector of matrix1. This temporary vector is then assigned to the just created matrix, replacing it's current contents, and is then destroyed. matrix still has no inner vectors allocated, so 2D operations are still doomed.
for (int i = 0; i < kolumny; ++i)
for (int j = 0; i < (static_cast<signed int>(matrix1.size())); ++i)
i and j should never go negative (huge logic problem if they do), so use an unsigned type. Use the right unsigned type and the static_cast is meaningless.
In addition the inner for loop increments and tests i, not j
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
I see nothing wrong here other than matrix having nothing for j to index. This will result in Undefined Behaviour as access go out of bounds.
return matrix;
}
Cleaning this up so that it is logically sound:
vector<vector<int>> AsumB(const vector<vector<int>> & matrix1,
const vector<vector<int>> & matrix2)
We don't need the number of columns. The vector already knows all the sizes involved. A caveat, though: vector<vector<int>> allows different sizes of all of the inner vectors. Don't do this and you should be good.
Next, this function now takes parameters by constant reference.. With the reference there is no copying. With const the compiler knows the vectors will not be changed insode the function and can prevent errors and make a bunch of optimizations.
{
size_t row = matrix1.size();
size_t is an unsigned data type guaranteed to be large enough to index any representable object. It will be bg enough and you don't have to worry about pesky negaitve numbers. Also eliminates the need for any casting later.
if (!(row > 0 && row == matrix2.size()))
{
return vector<vector<int>>();
}
Here we make sure that everyone agrees ont he number of rows inviolved and return an empty vector if they don't. You could also throw an exception. The exception may be a better solution, but I don't know the use case.
size_t column = matrix1[0].size();
if (!(column > 0 && column == matrix2[0].size()))
{
return vector<vector<int>>();
}
Dowes the same as above, but makes sure the number of columns makes sense.
vector<vector<int>> matrix(row, vector<int>(column));
Created a local row by column matrix to store the result. Note the second parameter. vector<int>(column) tells the compiler that all row inner vectors will be initialized to a vector of size column.
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
Here we simplified the loops just a bit since we know all the sizes.
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix;
The compiler has a number of tricks at its disposal to eliminate copying matrix on return. Look up Return Value Optimization with your preferred web search engine if you want to know more.
}
All together:
vector<vector<int>> AsumB(const vector<vector<int>> & matrix1,
const vector<vector<int>> & matrix2)
{
size_t row = matrix1.size();
if (!(row > 0 && row == matrix2.size()))
{
return vector<vector<int>>();
}
size_t column = matrix1[0].size();
if (!(column > 0 && column == matrix2[0].size()))
{
return vector<vector<int>>();
}
vector<vector<int>> matrix(row, vector<int>(column));
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix;
}

Initializing a member vector<vector<int>> in the constructor value-by-value

I have a class that should generate a 2D vector of ints (in the range of 0-1) that I want to use as a map (called matrix).
class generator
{
public:
void draw(void);
void iterate(void);
generator();
~generator();
private:
vector<vector<int>> matrix;
};
In the constructor I want to fill the matrix with random data:
vector<vector<int>> matrix(height, vector<int>(width));
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++) {
matrix[i][j] = rand() % 2;
}
}
But I get a read acess violation.
Thank you for your time and effort.
DEPRECATED UPDATE:
I tried using the member function .data() to retrieve the pointer to the data and accessing it directly
ptr = matrix[i][j].data();
*ptr = rand() % 2;
But the result doesn't differ. I'm fairly convinced that this isn't about how I want to access the vector but how I set it up.
UPDATE 2:
The correction provided below does result in the vector being filled as intended. When trying to
cout << matrix[i][j];
in the draw member function I get a read-acess-violation again.
UPDATE 3:
As suggested I checked when exactly this error happens. It happens on the very first try do print out the first integer at matrix[0][0]. The value returned is 0x8. Important: If not replaced by a constant matrix.size() already causes the error.
UPDATE 4:
This is basically my draw()
void generator::draw() {
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j];
}
cout << endl;
}
}
The original source has been updated to reflect the current one.
UPDATE 4:
Slightly cut source code at http://pastebin.com/83vrDJWZ
UPDATE 5:
One more simple mistake on my part has been resolved in the comments. Problem is silved. Thank you all.
Looks like the problem is an invalid pointer due to:
vector<vector<int>*> matrix;
You have a vector of pointers to vector of int, but you never actually allocate the inner elements.
Instead use:
vector<vector<int>> matrix;
And during the initialization steps:
matrix[i].resize(width); // instead of: matrix[i]->resize(width);
Actually, you could simplify it a bit:
std::vector<std::vector<int>> matrix(height, std::vector<int>(width));
Still have to iterate to fill the data, though.

sorting an array and maintaining element's old index

I have an array A:
A = [10 11 3 15 8 7]
index = 0 1 2 3 4 5
I want to sort this array.After sorting I want the information of old index.For this I can create a structure like this.
struct VnI{
int value;
int index;
};
sorting the array of structure with respect to value solve my problem.But I want to know that is it possible to solve this using sort or any other function in C++11.
I have tried this way:
struct VnI{
int V;
int I;
};
bool comparator(VnI x,VnI y){
if(x.V < y.V)
return true;
return false;
}
int maximumGap(const vector<int> &A) {
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
sort(B.begin(),B.end(),comparator);
for(int i = 0;i < B.size();i++){
cout<<B[i].I<<" "<<B[i].V<<endl;
}
}
But I got runtime error.
Please help.
This code is wrong:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
When you write B[i], it assumes that B is at least of size i+1. Since the maximum value of i (which you used an index to B) is A.size()-1. The assumption in your code is that B is at least of size A.size(). This assumption is wrong — the fact is that B is of size 0.
Unfortunately operator[] of std::vector doesn't check for out of range index. If you use at(), the code will throw std::out_of_range exception:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B.at(i).I = i;
B.at(i).V = A[i];
}
Now this would throw std::out_of_range exception.
Anyway, one simple fix could be this:
vector<VnI> B (A.size()); //initialize B with the size of A.
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
However, I'd suggest this solution:
vector<VnI> B;
B.reserve(A.size());
for(int i = 0;i < A.size(); i++){
B.emplace_back(i, A[i]);
}
I'd also suggest you read more about std::vector, especially the following functions:
size()
capacity()
resize()
reserve()
push_back()
operator[]
at()
emplace_back()
and all the constructors.
Also, learn to naming your variables properly and be consistent with it.
Hope that helps.
do you pefer to use vector and pair?
each pair has "first" and "second", put "first"=value to sort,"second"=original index, create a pair for each element and put them into vector to sort:
int N[]={10,11,3,15,8,7};
std::vector<std::pair<int,int> > v;
//create pair for each element
for(int i=0;i<sizeof(N)/sizeof(int);i++){
//first is value of array,second is original index
v.push_back(std::make_pair(N[i],i));
}
//sort the vector of pair
sort(v.begin(),v.end());
//get original index from second of pair
for(std::pair<int,int>& p : v){
std::cout << p.first << ":" << p.second << std::endl;
}
output
3:2
7:5
8:4
10:0
11:1
15:3
Normally what is done is the opposite... i.e. given an array x of elements compute an array of integers ix so that x[ix[i]] appears to be sorted under a certain criteria.
This allows representing the container with different orderings without actually having to move/copy the elements.
With C++11 this can easily be done using lambdas:
// Build the index vector ix
std::vector<int> ix(x.size());
for (int i=0,n=x.size(); i<n; i++) ix[i] = i;
// Sort ix according to the corresponding values in x
// (without touching x)
std::sort(ix.begin(), ix.end(),
[&x](int a, int b) { return x[a] < x[b]; });
This ix index array is what you are asking for (i.e. the "old" position of an element: ix[i] is where the i-th element of the sorted list was in the original array) and there is no need to modify the input array.
You are trying to sort a list of custom objects, answerd here:
SO Link
Once you list the list of VnI objects you can then access there old index's through the I member that I presume is the index.

C++ Vector of vectors, cannot edit

I have a MatrixGraph class with a member variable M that is of type vector<vector<double> >. I have a constructor that takes in an unsigned, and makes a NxN matrix from that input, and I want to initialize it to zero. The problem is when I run my code the debugger kicks in when I am trying to assign stuff. I have tried to methods, the first:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
for(int j = 0;j < num_nodes;j++) {
M[i][j] = 0.0;//breaks on this line
}//end i for loop
}//end j for loop
}
and the second method i tried i found on here but that didn't work either:
MatrixGraph::MatrixGraph(unsigned num_nodes) {
for(int i = 0;i < num_nodes;i++) {
M[i].resize(num_nodes);//breaks on this line
}
}
i commented on here where the last line on the call stack is before i get errors. The next line after that on the call stack shows me the class vector and is saying that my Pos is greater than the size of my vector. I assume that this is a size zero matrix, but i don't know why i cant make it bigger. Any suggestions?
Thanks!
The reason your code is failing is that you cant use the [] operation on a vector before that element exists. The usual way to add a value to a vector is to use push_back.
If you want to initialize to 0 you want assign(). Resize the outer vector to the required size and then assign each of the inner vectors with 0
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].assign(num_nodes,0.0f);
}//end i for loop
This can also be done. It is cleaner code but a tad less efficient since it makes 1 extra vector object.
vector<double> temp;
temp.assign(num_nodes,0.0);
M.assign(num_nodes,temp);
or just
M.assign(num_nodes,vector<double>(num_nodes,0.0));
neatest one(courtesy #Mike Seymour) would be
MatrixGraph(unsigned num_nodes)
: M(num_nodes, vector<double>(num_nodes,0.0))
{}
(thanks Mike Seymour for the constructor syntax)
What you are doing here is initializing the outer vector with a temp vector full of 0.0s
You need to populate your vector M with data: M.resize(num_nodes)
This should do it:
MatrixGraph::MatrixGraph(unsigned num_nodes)
{
M.resize(num_nodes);
for(int i = 0;i < num_nodes;i++)
{
M[i].resize(num_nodes);
for(int j = 0;j < num_nodes;j++)
{
M[i][j] = 0.0;
}//end j for loop
}//end i for loop
}