使用向量的向量创建矩阵

78

我试图获取一个二维矩阵的尺寸输入,然后使用用户输入来填充这个矩阵。我尝试用向量(向量的向量)来实现这一点,但是每当我尝试读取数据并将其附加到矩阵时都会遇到一些错误。

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

每当我尝试这样做时,它会给我一个下标超出范围的错误。 有什么建议吗?


3
你没有初始化matrix - elyashiv
@elyashiv 实际上,matrix 已经被初始化了。 - Luchian Grigore
3
向量最初是空的,因此出现了超出范围的错误。 - Samy Arous
1
正确。作为一个长度为零的向量,它包含了一个长度为零的向量 =) - WhozCraig
1
@lcfseth 那又怎样?这并不意味着它没有被初始化。它是一个大小为0的已初始化向量对象。在C++中,初始化具有精确的含义。 - Luchian Grigore
既然问题已经解决,我建议您使用矩阵库,例如eigen或boost blas,并使用atlas等后端,而不是使用向量的向量并手动执行所有操作。 - user6094307
8个回答

211

在访问任何元素之前,您必须将向量的向量初始化为适当的大小。 您可以这样做:

// assumes using std::vector for brevity
vector<vector<int>> matrix(RR, vector<int>(CC));

这会创建一个大小为RR,元素为大小为CC的向量,其中每个元素都填充为0


5
我也是这样做的。惊讶你是唯一给出这个答案的人。顺便说一下,我从不使用矢量的向量来表示矩阵。 =) - paddy
1
@paddy 我也不会使用它。随意调整任何列或行的大小,或在创建后更改矩阵的尺寸的想法对我来说太可怕了。 - juanchopanza
2
@paddy 我知道这是正常的,但往往这是一个不好的想法。我的矩阵具有固定的大小,这大大减少了错误的可能性。 - juanchopanza
1
我觉得你误解了我的回复。我是在赞同你的同时,提供了一些关于实际应用程序如何处理这个问题的见解。你从来没有改变过一行的维度。我在MatLab之外使用矩阵的大多数情况下都是用于3D工作,是的,在这种情况下,我有一个固定大小的数组,没有堆分配。当我真正需要一个2D动态数组时,我通常会获取一个单独的内存块,并在该块内分配我的行指针和数据区域。 - paddy
3
@paddy,我的意思是我的矩阵尺寸的类型已经确定,所以无法更改。因为我把矩阵视为数学对象而不是存储空间,所以使用编译器来强制执行一些限制是有道理的(至少对我而言),例如你不能将一个2x4的矩阵赋值给一个5x1的矩阵,或者你不能将不兼容尺寸的两个矩阵相乘。存储本身是单个块,在我的情况下是静态分配的,因为我倾向于处理小矩阵,但可以轻松适应动态分配而不会影响类型安全性。 - juanchopanza
显示剩余5条评论

86

你的向量目前两个维度都是0。

相反,将向量初始化为:

vector<vector<int> > matrix(RR);
for ( int i = 0 ; i < RR ; i++ )
   matrix[i].resize(CC);

这将给你一个尺寸为 RR * CC 的矩阵,其中所有元素都被设置为 0


2
你可以用一条语句创建一个大小为 CC 的向量,其中包含 RR 个大小相同的子向量,并避免重新调整大小。 - juanchopanza
1
@juanchopanza,你是在谈论std::generate还是仅仅是赋值? - Luchian Grigore

13

我不熟悉C++,但是快速查看文档表明这应该能够工作:

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

4
正确,但由于随后的推回而遭受性能惩罚。 - Luchian Grigore
14
从std::cin中读取矩阵会削弱你有关性能的论点。 - stefan

4
假设我们有以下类:
#include <vector>

class Matrix {
 private:
  std::vector<std::vector<int>> data;
};

首先,我建议您实现一个默认构造函数:

#include <vector>

class Matrix {
 public:
  Matrix(): data({}) {}

 private:
  std::vector<std::vector<int>> data;
};

此时我们可以按照以下方式创建Matrix实例:

Matrix one;

下一个战略步骤是实现一个 `Reset` 方法,它接受两个整数参数,分别指定矩阵的新行数和列数:
#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;
};

此时,Reset方法会更改2D矩阵的尺寸为给定的尺寸并重置其所有元素。稍后我将向您展示为什么我们可能需要这样做。

我们可以创建并初始化我们的矩阵:

Matrix two(3, 5);

让我们为矩阵添加信息方法:
#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;
};

此时我们可以获取一些琐碎的矩阵调试信息:

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

此时我们需要的第二个类方法是 At。它是用于获取私有数据的一种getter方法:
#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;
};

常量At方法接受行号和列号,返回对应矩阵单元格中的值:

#include <iostream>

int main() {
  Matrix three(3, 4);
  std::cout << three.At(1, 2); // 0 at this time
}

第二个与第一个相同参数的非常量 At 方法返回对应矩阵单元格中值的引用。请注意,这里的返回值是引用而不是原始值。
#include <iostream>

int main() {
  Matrix three(3, 4);
  three.At(1, 2) = 8;
  std::cout << three.At(1, 2); // 8
}

最后,让我们实现 >> 运算符:

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

然后进行测试:

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

可以随意添加超出范围的检查。希望这个例子能够帮助您 :)


2

试试这个。m = 行数,n = 列数

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

1

在使用cin>>v[i][j]之前,需要初始化向量Vector。即使它是一维向量,仍然需要初始化,请查看此链接

初始化后将不会出现错误,请查看此链接


实际上,它被初始化为长度为“零”,因此会导致SIGSEGV错误。 - Mohit

0

你所初始化的是一个向量的向量,因此你一定要包含一个向量来插入(在向量术语中称为“推入”)到你在示例中命名为矩阵的原始向量中

还有一件事,你不能直接使用运算符“cin”在向量中插入值。使用一个变量来输入,然后将其插入向量中。

请尝试这个:

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 
}

0
我为此编写了这个类。当添加更多项目时,它会生成一个可变大小的矩阵(可扩展)。

'''

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

'''


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接