Vector of Vectors to create matrix

C++VectorMatrix

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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 2 - C++

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 3 - C++

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 - C++

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 - C++

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;
}

Solution 6 - C++

Vector needs to be initialized before using it as cin>>v[i][j]. Even if it was 1D vector, it still needs an initialization, see this link

After initialization there will be no errors, see this link

Solution 7 - C++

What you have initialized is a vector of vectors, so you definitely have to include a vector to be inserted("Pushed" in the terminology of vectors) in the original vector you have named matrix in your example.

One more thing, you cannot directly insert values in the vector using the operator "cin". Use a variable which takes input and then insert the same in the vector.

Please try this out :

int num;
for(int i=0; i<RR; i++){
      
      vector<int>inter_mat;       //Intermediate matrix to help insert(push) contents of whole row at a time
      
      for(int j=0; j<CC; j++){
           cin>>num;             //Extra variable in helping push our number to vector
           vin.push_back(num);   //Inserting numbers in a row, one by one 
          }
      
      v.push_back(vin);          //Inserting the whole row at once to original 2D matrix 
}

Solution 8 - C++

I did this class for that purpose. it produces a variable size matrix ( expandable) when more items are added

'''

#pragma once
#include<vector>
#include<iostream>
#include<iomanip>
using namespace std;
template <class T>class Matrix
{
public:
	Matrix() = default;
	bool AddItem(unsigned r, unsigned c, T value)
	{
		if (r >= Rows_count)
		{
			Rows.resize(r + 1);
			Rows_count = r + 1;
		}
		else
		{
			Rows.resize(Rows_count);
		}
		if (c >= Columns_Count )
		{
			for (std::vector<T>& row : Rows)
			{
				row.resize(c + 1);
			}
			Columns_Count = c + 1;
		}
		else
		{
			for (std::vector<T>& row : Rows)
			{
				row.resize(Columns_Count);
			}
		}
		if (r < Rows.size())
			if (c < static_cast<std::vector<T>>(Rows.at(r)).size())
			{
				(Rows.at(r)).at(c) = value;
			}
			else
			{
				cout << Rows.at(r).size() << " greater than " << c << endl;
			}
		else
			cout << "ERROR" << endl;
  		return true;
	}
	void Show()
	{
		std::cout << "*****************"<<std::endl;
		for (std::vector<T> r : Rows)
		{
			for (auto& c : r)
				std::cout << " " <<setw(5)<< c;
			std::cout << std::endl;
		}
		std::cout << "*****************" << std::endl;
	}
	void Show(size_t n)
	{
		std::cout << "*****************" << std::endl;
		for (std::vector<T> r : Rows)
		{
			for (auto& c : r)
				std::cout << " " << setw(n) << c;
			std::cout << std::endl;
		}
		std::cout << "*****************" << std::endl;
	}
//	~Matrix();
public:
	std::vector<std::vector<T>> Rows;
	unsigned Rows_count;
	unsigned Columns_Count;
};

'''

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1487000View Question on Stackoverflow
Solution 1 - C++juanchopanzaView Answer on Stackoverflow
Solution 2 - C++Luchian GrigoreView Answer on Stackoverflow
Solution 3 - C++ShmiddtyView Answer on Stackoverflow
Solution 4 - C++sergheiView Answer on Stackoverflow
Solution 5 - C++SubhaBhowmikView Answer on Stackoverflow
Solution 6 - C++MohitView Answer on Stackoverflow
Solution 7 - C++Shantanu GargView Answer on Stackoverflow
Solution 8 - C++Amr1318View Answer on Stackoverflow