繁体   English   中英

如何制作用户指定值的二维数组?

[英]How do you make a two dimensional array of user specified value?

我如何声明用户给出的大小为n的二维数组?
例如,为什么这会起作用:

int n;
cin >> n;
int *array = new int[n];
//no errors

但这不会:

int n;
cin >> n;
int *array = new int[n][n];
// these errors:
//error: array size in new-expression must be constant
//error: the value of 'n' is not usable in a constant expression
//note: 'int n' is not const

是否可以使用行和列大小为n的二维数组,或者您是否必须使用向量?
谢谢!

用矢量做,像这样:

int n;
cin >> n;
auto matrix = std::vector<std::vector<int>>(n, std::vector<int>(n));

https://wandbox.org/permlink/zsOiUTvCbxAGmK6d


还有一个std::valarray模板 ,其功能与std::vector类似,但具有有趣的额外功能,在矩阵的情况下可能很有用。

https://wandbox.org/permlink/9Vq141QpEWcWoUxM

要创建多维数组,您必须编写以下内容:

int n;
cin >> n;
int **array = new int*[n];
for (int i = 0; i < n; i++) {
    array[i] = new int[n];
}

别忘了删除它:

for (int i = 0; i < n; i++) {
    delete[] array[i];
}
delete[] array;

但是当前的c ++最佳实践是永远不要在应用程序代码中分配或释放内存,这意味着你应该使用std::vector或其他一些容器类。

这个答案与大多数其他答案的不同点有两点:

  • 没有原始指针或内存分配
  • 使用单个连续(线性)内存块

一种常见的方法是使用单个线性内存块并在列之后的行或列之后逐行存储元素(行或列主要顺序 )。 让我们概括一下,并说你想要一个具有范围N0N1的类型T的2D数量。 然后你可以通过获得所需的内存

std::vector<T> my_memory(N0*N1, T{});

使用向量而不是原始指针有几个优点。 例如,您不能忘记释放内存,因为解构器会自动关注内存( RAII惯用法 )。 另一个优点是上面调用的构造函数使用默认构造的T副本填充向量(而不是使内存保持未初始化)。

接下来,您可以使用vector成员operator[] (或者如果您想要绑定检查at则使用成员函数)来访问线性内存。 您可能希望在区间[ 0N0 ]和[ 0N1 )中使用两个索引n0n1 ,但内存是线性的并且需要单个索引。 因此,您可以引入辅助函数index以访问您的2D数量,例如,

my_memory[index(n0, n1)] = T(42);

想象一下这是如何工作的,考虑一个3乘2的矩阵。 在给定的线性内存块中,您可以像这样排列元素:

0           1           2           3           4           5
index(0, 0) index(0, 1) index(1, 0) index(1, 1) index(2, 0) index(2, 1)

在这种情况下你会写

int index(int n0, int n1) {
  return n0 * N1 + n1;// (note that `n0` is multiplied by `N1`).
}

通常对于d维度你会有(伪代码)

int index(int(&n)[d]) {
  return n[0] * (N[1]*N[2]*...*N[d-1])
    + n[1] * (N[2]*N[3]*...*N[d-1])
    + ...
    + n[d-2] * (N[d-1])
    + n[d-1] * (1);
}

括号中的表达式也称为音高

如果将所有逻辑放在一个类中,则变得非常简单易用。 这是一个灵感的例子( N = 4在线演示 ):

#include <cassert>

#include <iostream>
#include <vector>

template<class T>
class Quantity2d {
 private:
  std::size_t Ns_[2];
  std::vector<T> data_;
 public:
  Quantity2d(int N0, int N1)
  : Ns_{std::size_t(N0), std::size_t(N1)}
  , data_()
  {
    assert(N0 > 0);
    assert(N1 > 0);
    data_.resize(size(), T{});
  }

  constexpr size_t size() const { return Ns_[0] * Ns_[1]; }

  constexpr int N0() const { return int(Ns_[0]); }
  constexpr int N1() const { return int(Ns_[1]); }

  constexpr size_t pitch0() const { return Ns_[1]; }
  constexpr size_t pitch1() const { return std::size_t(1); }

  constexpr size_t ind(int n0, int n1) const {
    assert(n0 >= 0 && n0 < N0());
    assert(n1 >= 0 && n1 < N1());
    return std::size_t(n0) * pitch0() + std::size_t(n1) * pitch1();
  }

  T& operator()(int n1, int n2) {
    return data_[ind(n1, n2)];
  }

  constexpr const T& operator()(int n1, int n2) const {
    return data_[ind(n1, n2)];
  }
};

template<class T>
std::ostream& operator<<(std::ostream& os, const Quantity2d<T>& q) {
  int N0 = q.N0();
  int N1 = q.N1();
  for(int i=0; i<N0; ++i) {
    for(int j=0; j<N1; ++j) {
      os << i << "\t" << j << "\t" << q(i, j) << "\n";
    }
  }
  return os;
}

int main() {
  int N = 0;
  std::cout << "please enter size per dimension "
    << "(WARNING: matrix will be printed on screen): "
    << std::flush;
  std::cin >> N;

  if(N >= 1) {
    std::cout << "I understood. So let's do " << N << "x" << N << std::endl;
  }
  else {
    std::cerr << "You failed. Next time try with N >= 1." << std::endl;
    return 1;
  }

  Quantity2d<double> matrix(N, N);

  for(int i=0; i<matrix.N0(); ++i) {
    for(int j=0; j<matrix.N1(); ++j) {
      matrix(i, j) = double(i) * double(j);
    }
  }

  std::cout << matrix << std::flush;

  return 0;
}

可以在不使用如下矢量的情况下创建二维阵列。 这适用于所有类型。

template <typename T> 
T **Alloc2D( int nRows, int nCols)
{
      T **array2D;    
      array2D = new T*[nRows];
      for( int i = 0 ; i < nRows ; i++ )
          array2D[i] = new T [nCols];

      return array2D;
}

template <typename T>
void Free2D(T** dArray)
{
      delete [] *dArray;
      delete [] dArray;
}

但是,问题在于内存管理,因为它是一种原始方法。

相反,我们可以使用可管理的向量

typedef vector<vector<int>> ARRAY2D;

有可能的:

int **marray = new int[n][n];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM