如何在C++中选择多维数组中的一个范围

how to select a range in multidimensional array in C++?

本文关键字:范围 一个 C++ 选择 数组      更新时间:2023-10-16

假设我有:

int array[9][9]= {
        {1 , 2 , 3 , 4, 5, 6, 7, 8, 9},
        {10, 11, 12, 13, 14, 15, 16, 17, 18},
        {19, 20, 21, 22, 23, 24, 25, 26, 27},
        {28, 29, 30, 31, 32, 33, 34, 35, 36},
        {37, 38, 39, 40, 41, 42, 43, 44, 45},
        {46, 47, 48, 49, 50, 51, 52, 53, 54},
        {55, 56, 57, 58, 59, 60, 61, 62, 63},
        {64, 65, 66, 67, 68, 69, 70, 71, 72},
        {73, 74, 75, 76, 77, 78, 79, 80, 81}
    };

我怎么能只对第一行(值1到9)或第一列(像值1到73)应用一些函数呢。比方说,我想说索引0到9都应该具有值0。

可以将这个范围保存在变量中吗?

试着这样做:

for (int i = 0; i<10; i++) 
        array[0][i] = 0;

C.中没有真正的多维数组

在一个真正的多维数组中,所有维度都是平等的。无论你能对行做什么,你也能对列做什么。

C++的情况并非如此。阵列的第三行只是

array[3]

它在各个方面都是一个独立的阵列。与任何其他范围一样,行的范围可以表示为(开始、结束)对,例如make_pair(array[3], array[7])

没有什么可以用列来完成的。与第三行不同,第三列不是数组,它只是一个不在任何标准数据结构保护伞下的元素的虚拟集合。

最接近多维数组切片的是自定义迭代器,因此++i移动到右边的下一个元素或下面的下一元素。当你在做的时候,考虑从C风格的数组转移到STL风格的容器。

要隔离数组的行,可以引用数组的一行:

int (&row)[9] = array[2];

例如,上面的行引用了数组的第三行。

实时演示

对于列,则更为复杂。

或者,您可以执行以下构造,将引用包装器的向量返回到2D数组的列或行。

// if flg == true you get row at idx else if flg == false you get column at idx
template<typename T, int N, int M>
std::vector<std::reference_wrapper<T>>
getRange(T (&arr)[N][M], std::size_t const idx, bool const flg = true) {
  if(flg) {
    return typename std::vector<std::reference_wrapper<T>>(std::begin(arr[idx]), std::end(arr[idx]));
  } else {
    typename std::vector<std::reference_wrapper<T>> out;
    out.reserve(N);
    for(int i(0); i < N; ++i) out.push_back(arr[i][idx]);
    return out;
  }
}

实时演示

对于行,这很容易,因为您可以像一样传递它们

void foo(int * row, int cols) {
    for (int col = 0; col < cols; ++col) {
        int * x = row + col;
    }
}
...
foo(array[3], 9);
...

对于列来说,这更困难,但您可以将每一列视为数组中具有特定偏移量的列:

void boo(int * col, int rows, int cols) {
    for (int row = 0; row < rows; ++row) {
        int * x = col + row * cols;
    }
}
....
// process fourth column:
boo(array[0]+4, 9, 9);

当然,使用sizeof而不是"9",使用C++矢量/数组而不是C样式的int[][]将使生活更加轻松,代码也更加可读和可支持。

另一种方法是使用boost::矩阵,例如:

using namespace boost::numeric::ublas;
matrix<double> m(9, 9);
matrix_row<matrix <double> > row(m, 5);
matrix_column<matrix <double> > col(m, 4);

您可以通过在函数中指定索引(起始和结束范围)并说明它应该应用于行还是列来实现。由于您使用的是纯C风格的数组,因此处理指针更为棘手。我建议您使用vector s和pair s(用于范围)。

C型阵列的一个例子

void some_function(int array[][9], bool row_or_column, size_t major, size_t start, size_t end){
    if (row_or_column = true) {
        for (int i = start; i < end; i++) {
            cout << array[major][i]; //perform your operation on row
        }
    }
    else {
        for (int i = start; i < end; i++) {
            cout << array[i][major]; //perform your operation on column
        }
    }
}

row_or_column设置为行的true或列的falsemajor应指定列号或行号以及startend中的范围。注:end为专属

用于处理范围为start = 0end = 5的第二行,即10到14some_function(array, true, 1, 0, 5)

用于处理范围为start = 0end = 5的第二列,即2到38some_function(array, false, 1, 0, 5)