Vector of Vectors to create matrix
Solution 1
As it is, both dimensions of your vector are 0.
Instead, initialize the vector as this:
vector<vector<int> > matrix(RR);
for ( int i = 0 ; i < RR ; i++ )
matrix[i].resize(CC);
This will give you a matrix of dimensions RR * CC
with all elements set to 0
.
Solution 2
You have to initialize the vector of vectors to the appropriate size before accessing any elements. You can do it like this:
// assumes using std::vector for brevity
vector<vector<int>> matrix(RR, vector<int>(CC));
This creates a vector of RR
size CC
vectors, filled with 0
.
Solution 3
I'm not familiar with c++, but a quick look at the documentation suggests that this should work:
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
vector<int> myvector;
for(int j = 0; j<CC; j++)
{
int tempVal = 0;
cout<<"Enter the number for Matrix 1";
cin>>tempVal;
myvector.push_back(tempVal);
}
matrix.push_back(myvector);
}
Solution 4
Assume we have the following class:
#include <vector>
class Matrix {
private:
std::vector<std::vector<int>> data;
};
First of all I would like suggest you to implement a default constructor:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
private:
std::vector<std::vector<int>> data;
};
At this time we can create Matrix instance as follows:
Matrix one;
The next strategic step is to implement a Reset
method, which takes two integer parameters that specify the new number of rows and columns of the matrix, respectively:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
if (rows == 0 || cols == 0) {
data.assign(0, std::vector<int>(0));
} else {
data.assign(rows, std::vector<int>(cols));
}
}
private:
std::vector<std::vector<int>> data;
};
At this time the Reset
method changes the dimensions of the 2D-matrix to the given ones and resets all its elements. Let me show you a bit later why we may need this.
Well, we can create and initialize our matrix:
Matrix two(3, 5);
Lets add info methods for our matrix:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
At this time we can get some trivial matrix debug info:
#include <iostream>
void MatrixInfo(const Matrix& m) {
std::cout << "{ \"rows\": " << m.GetNumRows()
<< ", \"cols\": " << m.GetNumColumns() << " }" << std::endl;
}
int main() {
Matrix three(3, 4);
MatrixInfo(three);
}
The second class method we need at this time is At
. A sort of getter for our private data:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int At(const int &row, const int &col) const {
return data.at(row).at(col);
}
int& At(const int &row, const int &col) {
return data.at(row).at(col);
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
The constant At
method takes the row number and column number and returns the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
std::cout << three.At(1, 2); // 0 at this time
}
The second, non-constant At
method with the same parameters returns a reference to the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
three.At(1, 2) = 8;
std::cout << three.At(1, 2); // 8
}
Finally lets implement >>
operator:
#include <iostream>
std::istream& operator>>(std::istream& stream, Matrix &matrix) {
int row = 0, col = 0;
stream >> row >> col;
matrix.Reset(row, col);
for (int r = 0; r < row; ++r) {
for (int c = 0; c < col; ++c) {
stream >> matrix.At(r, c);
}
}
return stream;
}
And test it:
#include <iostream>
int main() {
Matrix four; // An empty matrix
MatrixInfo(four);
// Example output:
//
// { "rows": 0, "cols": 0 }
std::cin >> four;
// Example input
//
// 2 3
// 4 -1 10
// 8 7 13
MatrixInfo(four);
// Example output:
//
// { "rows": 2, "cols": 3 }
}
Feel free to add out of range check. I hope this example helps you :)
Solution 5
try this. m = row, n = col
vector<vector<int>> matrix(m, vector<int>(n));
for(i = 0;i < m; i++)
{
for(j = 0; j < n; j++)
{
cin >> matrix[i][j];
}
cout << endl;
}
cout << "::matrix::" << endl;
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
user1487000
Updated on December 03, 2020Comments
-
user1487000 over 3 years
I am trying to take in an input for the dimensions of a 2D matrix. And then use user input to fill in this matrix. The way I tried doing this is via vectors (vectors of vectors). But I have encountered some errors whenever I try to read in data and append it to the matrix.
//cin>>CC; cin>>RR; already done vector<vector<int> > matrix; for(int i = 0; i<RR; i++) { for(int j = 0; j<CC; j++) { cout<<"Enter the number for Matrix 1"; cin>>matrix[i][j]; } }
Whenever I try to do this, it gives me a subscript out of range error. Any advice?
-
Luchian Grigore over 11 yearsCorrect, but this suffers from performance penalties due to subsequent push-back.
-
juanchopanza over 11 yearsYou could create a size
RR
vector of sizeCC
vectors in one statement and avoid the resizes. -
Luchian Grigore over 11 years@juanchopanza are you talking about std::generate or just assignment?
-
stefan over 11 years@LuchianGrigore: Reading a matrix from std::cin kills your argument about performance
-
paddy over 11 years+1: That's what I do too. Surprised you're the only one who gave this answer. As an aside, I would never use a vector of vectors to represent a matrix. =)
-
juanchopanza over 11 years@paddy I wouldn't use it either. The idea of being able to arbitrarily resize any column or row at any time, or changing the dimensions of a matrix after creation, is too scary for me.
-
paddy over 11 yearsIt's normal to change dimensions of a matrix (in MatLab you do it all the time), but in real-world use, the matrix is a contiguous block, and all you are changing is the rows/cols (basically keeping track of stride-lengths) - to index an element in the matrix, you calculate the linear index from your multi-dimensional index.
-
juanchopanza over 11 years@paddy I know it is normal but more often than not it is a bad idea. My matrices have fixed sizes and that dramatically reduces the scope for errors.
-
paddy over 11 yearsI think you misunderstood my reply. I was agreeing with you, and providing insight into how real applications do this. You never change the dimension of one row. Most times I've used Matrices outside of MatLab it's been for 3D work, and yes in that case I have a fixed-sized array with no heap allocation. When I really need a 2D dynamic array, I usually grab a single block of memory and dish out my row pointers and data area within that block.
-
juanchopanza over 11 years@paddy what I meant to say is that my matrices' dimensions are in the type of the matrix, so they cannot be changed. Since I treat matrices as mathematical objects rather than storage space, it makes sense (to me) to use the compiler to enforce certain constraints, for example, you cannot assign a 2x4 matrix to a 5x1, or you cannot multiply to matrices together that do not have compatible dimensions. The storage itself is a single block, statically allocated in my case since I tend to deal with small matrices, but could be easily adapted to dynamic allocation without affecting the type safety.
-
Leonardo V. De Gasperin almost 8 yearsHello @juanchopanza yo necessito de ayuda (I nedd help), I have this
vector<vector<int>> mat1(L, std::vector<int>(C));
, and if I making a matrix calculator and I wanna the user write the number of lines and columns and the all elements I try make like thiscin >> L ; cin >> C;
and go on a size for loopfor (int i = 0; i < L; i++)\\ {\\ for (int j = 0; j < C; j++)\\ {\\ cin >> mat1[i][j];}}
-
Nadim Farhat almost 7 yearsI know it is a very old thread . I like your solution . please could you add std:: in front of vectors:)
-
juanchopanza almost 7 years@NadimFarhat Thanks! I added a comment specifying that it uses to
using std::vector
. -
Mohit about 5 yearsActually, its initialized but with length "zero", so it gives SIGSEGV error.
-
Xiaofeng Zheng about 2 yearsBut then there will be RR + 1 vectors created. First you create a vector
vector<int>(CC)
and then it will be copied RR times. I want to know how to avoid redundant construction