Vector of Vectors to create matrix

283,904

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;
}
Share:
283,904
user1487000
Author by

user1487000

Updated on December 03, 2020

Comments

  • user1487000
    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
    Luchian Grigore over 11 years
    Correct, but this suffers from performance penalties due to subsequent push-back.
  • juanchopanza
    juanchopanza over 11 years
    You could create a size RR vector of size CC vectors in one statement and avoid the resizes.
  • Luchian Grigore
    Luchian Grigore over 11 years
    @juanchopanza are you talking about std::generate or just assignment?
  • stefan
    stefan over 11 years
    @LuchianGrigore: Reading a matrix from std::cin kills your argument about performance
  • paddy
    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
    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
    paddy over 11 years
    It'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
    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
    paddy over 11 years
    I 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
    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
    Leonardo V. De Gasperin almost 8 years
    Hello @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 this cin >> L ; cin >> C; and go on a size for loop for (int i = 0; i < L; i++)\\ {\\ for (int j = 0; j < C; j++)\\ {\\ cin >> mat1[i][j];}}
  • Nadim Farhat
    Nadim Farhat almost 7 years
    I know it is a very old thread . I like your solution . please could you add std:: in front of vectors:)
  • juanchopanza
    juanchopanza almost 7 years
    @NadimFarhat Thanks! I added a comment specifying that it uses to using std::vector.
  • Mohit
    Mohit about 5 years
    Actually, its initialized but with length "zero", so it gives SIGSEGV error.
  • Xiaofeng Zheng
    Xiaofeng Zheng about 2 years
    But 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