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

4
假设我有以下内容:
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。

是否可以将此范围保存在变量中?


可能是从由向量组成的向量获取矩阵的第一列的重复问题。 - Teivaz
请查看 std::slice 的文档,它恰好可以做到这一点。 - Richard Hodges
5个回答

1
为了隔离数组的行,您可以引用数组的一行:
int (&row)[9] = array[2];

例如,上面的行取一个数组的第三行的引用。 演示实况 对于列来说,更加复杂。
或者,您可以使用以下构造返回对二维数组的列或行的引用包装器向量。
// 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;
  }
}

实时演示


非常感谢。我想确保该行或列中只有一个5。你会怎么做? - Ali RJ

1
尝试像这样做:

试着这样做:

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

1
非常简单,解决了我的问题。谢谢。现在还有一个问题。我想测试这个范围,看看数字是否重复。例如,我想确保该行或列中只有一个5。你会怎么做? - Ali RJ
看看这篇帖子,类似的问题 https://dev59.com/SG865IYBdhLWcg3wEaUx - Sergiy Shvets

1
在C语言中没有真正的多维数组。
在真正的多维数组中,所有维度都处于同等地位。无论你对行做什么,你也可以对列做同样的事情。
但在C++中并非如此。你的数组的第三行只是...
array[3]

在所有方面,它都是一个独立的数组。行范围,就像任何其他范围一样,可以表示为(start, end)对,例如make_pair(array[3], array[7])

列没有类似的表示方式。第三列不像第三行那样是一个数组,它只是一个虚拟的元素集合,不属于任何标准数据结构。

多维数组切片最接近的东西是自定义迭代器,++i可以移动到右侧或下方的下一个元素。顺便说一下,考虑从C风格数组转向STL风格容器。


0

对于行,很容易处理,你可以像这样传递它们:

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++ 的 vectors/array 而不是 C 风格的 int[][] 将使生活更加轻松,代码更易读、更易维护。
另一种方法是使用 boost::matrix,例如:
using namespace boost::numeric::ublas;
matrix<double> m(9, 9);
matrix_row<matrix <double> > row(m, 5);
matrix_column<matrix <double> > col(m, 4);

0

您可以通过在函数中指定索引(起始和结束范围),并说明它应该应用于行还是列来完成此操作。由于您正在使用普通的C风格数组,因此处理指针会更加棘手。我建议您使用vectorpair(用于范围)。

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表示行或false表示列,major应指定列号或行号以及startend中的范围。注意:end是排除在外的。

要处理第二行范围为start = 0end = 5即10到14的数据,请使用以下代码:some_function(array, true, 1, 0, 5)

要处理第二列范围为start = 0end = 5即2到38的数据,请使用以下代码:some_function(array, false, 1, 0, 5)


你不能将int[9][9]转换为int**。 - Shangtong Zhang

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