【问题标题】:Print 2D Array as a Method in C++将二维数组打印为 C++ 中的方法
【发布时间】:2021-12-25 23:16:18
【问题描述】:

我想用 C++ 编写一个打印二维数组的方法。此方法是无效的,它具有以下参数作为输入:二维数组、行数、列数。我想使用二维矩阵作为双指针来调用函数。我想以 2D 形状打印元素。我收到以下错误:

error: cannot convert ‘int (*)[2]’ to ‘int**’

编辑:将 int** list 更改为 int (*list)[2] 有效,但有没有一种方法我不必手动编写列号,因为我希望此方法适用于不同大小的数组.

#include <iostream>

using namespace std;

void printArray2D(int** list, int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            cout << list[i][j] << " ";
        }
        cout << endl;
    }
}

int main()
{
    int list1[2][2] = { {1,2},{3,4} };

    int row1 = sizeof(list1) / sizeof(list1[0]);
    
    int col1 = sizeof(list1[0]) / sizeof(list1[0][0]);

    printArray2D(list1, row1, col1);

    return 0;
}
 

【问题讨论】:

    标签: c++ arrays pointers multidimensional-array methods


    【解决方案1】:

    您的数组实际上是扁平的,这意味着您必须将其类型转换为int*,而不是int**int** 指的是指向 int 数组的指针数组,但数组内没有指针。

    换句话说,您实际上有整数的一维数组(平面)。任何 C 多维数组,如 int a[3][5]int a[3][5][7] 都是平面数组,本质上是一维的。 [3][5] 数组指向内存中包含3 * 5 = 15 整数的连续区域,[3][5][7] 数组指向内存中连续区域中的3 * 5 * 7 = 105 整数。

    同样在转换为int* 之后,有关维度的信息会丢失,因此您必须通过使用[i * col + j] 手动进行索引运算:

    Try it online!

    #include <iostream>
    
    using namespace std;
    
    void printArray2D(int* list, int row, int col) {
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                cout << list[i * col + j] << " ";
            }
            cout << endl;
        }
    }
    
    int main()
    {
        int list1[2][2] = { {1,2},{3,4} };
    
        int row1 = sizeof(list1) / sizeof(list1[0]);
        
        int col1 = sizeof(list1[0]) / sizeof(list1[0][0]);
    
        printArray2D((int*)list1, row1, col1);
    
        return 0;
    }
    

    输出:

    1 2 
    3 4 
    

    实际上有一个使用模板的 C++ 特定解决方案,可用于保存有关维度的信息并将此信息转发给函数,然后您不必使用手动索引算法:

    Try it online!

    #include <iostream>
    
    using namespace std;
    
    template <int Rows, int Cols>
    void printArray2D(int const (&list)[Rows][Cols]) {
        for (int i = 0; i < Rows; i++) {
            for (int j = 0; j < Cols; j++) {
                cout << list[i][j] << " ";
            }
            cout << endl;
        }
    }
    
    int main()
    {
        int list1[2][2] = { {1,2},{3,4} };
    
        int row1 = sizeof(list1) / sizeof(list1[0]);
        
        int col1 = sizeof(list1[0]) / sizeof(list1[0][0]);
    
        printArray2D(list1);
    
        return 0;
    }
    

    输出:

    1 2 
    3 4 
    

    如果您有固定的多维数组,另一个不错的解决方案是使用std::array。那么就不需要转发任何维度信息了,使用std::array.size()方法即可:

    Try it online!

    #include <iostream>
    #include <array>
    
    template <typename ArrT>
    void printArray2D(ArrT const & list) {
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list[i].size(); j++) {
                std::cout << list[i][j] << " ";
            }
            std::cout << std::endl;
        }
    }
    
    int main()
    {
        std::array<std::array<int, 2>, 2> list1 =
            { std::array{1,2}, std::array{3,4} };
        printArray2D(list1);
        return 0;
    }
    

    输出:

    1 2 
    3 4 
    

    【讨论】:

    • 我使用列表作为指针,因此我可以通过使用一个索引来调用所有元素,因为所有数组值在内存中彼此相邻。对吗?
    • @user6210457 是的,正确。如果在多维 C 数组的所有情况下都有 int a[3][5]int a[3][5][7],它们实际上都是一维的,这意味着数组变量只是指向包含所有数组数据的单个内存区域的指针,在这个意义上它是平坦的.如果您有维度[3][5][7],那么您在一个内存区域中只有一个包含3 * 5 * 7 = 105 int 的连续内存区域。
    • @user6210457 我刚刚使用模板添加了我的答案的第二部分与 C++ 特定解决方案,请看一下。这是一个很好的解决方法,可以避免将行/列等维度大小传递给函数。此外,它有助于不进行任何手动索引算法,您可以使用[i][j]
    • @user6210457 再次,刚刚用std::array 解决方案添加了我的答案的第三部分,请看一下。这个std::array 解决方案非常类似于C++,因为使用C 数组int a[3][5] 更接近C 风格,而std::array 是与C 数组相同数组的现代C++ 变体。
    • @Arty 我刚刚阅读了答案 n。链接到,以及从那里链接到的标准讨论。这很有启发性。最初甚至应该禁止 struct A{int i;} a; A *pa = (A*)&amp;a.i;(在指向类的第一个成员的指针和指向类的指针之间转换),但这会使太多现有的 C 代码(例如 struct sockaddr address hacks)无效。显然,基于排除数据访问路径(从而避免昂贵的内存同步)来启用编译器优化很受关注。
    猜你喜欢
    • 2018-12-02
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 2012-05-07
    相关资源
    最近更新 更多