【问题标题】:how to select a range in multidimensional array in C++?如何在 C++ 中选择多维数组中的范围?
【发布时间】:2023-03-16 19:52:01
【问题描述】:

假设我有:

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。

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

【问题讨论】:

标签: c++ arrays for-loop matrix multidimensional-array


【解决方案1】:

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

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

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

Live Demo

对于列,比较复杂。

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

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

Live Demo

【讨论】:

  • 非常感谢。我想确保该行或列中只有一个 5。你会怎么做?
【解决方案2】:

尝试这样做:

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

【讨论】:

  • 非常简单,解决了我的问题。谢谢。现在还有一个问题。现在我想测试这个范围,看看一个数字是否重复。例如,我想确保该行或列中只有一个 5。你会怎么做?
  • 看这个帖子,类似问题stackoverflow.com/questions/4003584/…
【解决方案3】:

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

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::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);

【讨论】:

    【解决方案4】:

    您可以通过在函数中指定索引(开始和结束范围)并说明它是否应该应用于行或列来实现。由于您使用的是普通的 C 样式数组,因此处理指针比较棘手。我建议您使用vectors 和pairs(用于范围)。

    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**
    【解决方案5】:

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

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

    这不是 C++ 的情况。数组的第三行只是

    array[3]
    

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

    这样的事情不能用列来完成。第三列与第三行不同,它不是一个数组,它只是一个虚拟的元素集合,不属于任何标准数据结构的保护伞。

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

    【讨论】:

      猜你喜欢
      • 2020-12-18
      • 2010-10-28
      • 1970-01-01
      • 2015-01-17
      • 2017-08-21
      • 2011-02-03
      • 1970-01-01
      • 2019-06-29
      • 2014-08-10
      相关资源
      最近更新 更多