【问题标题】:Return a 2D array of user-given size返回用户给定大小的二维数组
【发布时间】:2021-09-24 03:05:09
【问题描述】:

我想创建一个函数

  1. 将行和列作为参数。

  2. 根据给定的大小接受输入并

  3. 返回二维矩阵/数组。

我在网上浏览了很多解决方案,但我尝试的每件事都会给我一些新的错误。

int* input_taker(int row, int col)
{
    int mat[row][col];
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            scanf("%d", &mat[i][j]);
        }
    }
    return mat;
}

【问题讨论】:

  • 为什么不是 std::vector?
  • 您遇到了什么错误?我只收到警告,程序编译成功。
  • C 还是 C++?无论如何,您的代码在两者中都是非法的
  • @4386427 为什么非法?
  • @WeatherVane 我们不反对......

标签: c function pointers multidimensional-array


【解决方案1】:
  1. 函数返回类型是int*,但您试图返回具有不同类型(即int* (*)[col])的mat,所以这是一个错误。

  2. mat 是一个函数局部变量,所以一旦函数返回它就不存在了。换句话说 - 返回mat 完全没有意义。您正在返回对“死”对象的引用。

相反,您需要在函数中使用动态分配,以便函数返回后返回的对象仍然存在。

为此,您可以将mat 定义为指向col 整数数组的指针。此外,该函数应返回一个指向整数数组的指针。

喜欢:

#include <stdio.h>
#include <stdlib.h>

int (* input_taker(int row, int col))[]
{
    int (*mat)[col] = malloc(row * sizeof *mat);
    if (mat == NULL) exit(1);
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            mat[i][j] = i*col + j;  // Here you can read user input
        }
    }
    return mat;
}

int main ()
{
    int col = 8;
    int row = 5;
    int (* p)[col] = input_taker(row, col);
    for (int i=0; i<row; ++i)
    {
        for (int j=0; j<col; ++j)
        {
            printf("%5d ", p[i][j]);
        }
        puts("");
    }
    free(p);
    return 0;
}

输出

    0     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 

【讨论】:

  • @PaulOgilvie 随意发布“更简单、等效的解决方案”作为答案。它将帮助 OP 和其他人。在处理恒定列数时,我不知道比使用“指向数组的指针”更好的方法。
  • @PaulOgilvie:这个答案没有什么比这更重要的了。它提供了一种简单且定义明确的方式来创建二维数组。
  • 好的。我已撤回我的评论。
  • @4386427 像我这样的初学者有点难以理解。但它解决了我的问题。谢谢你。
  • @SheikhAbdullah 研究int *p[]int (*p)[] 之间的区别参见例如cdecl.org
【解决方案2】:

其他答案与您的原始问题一样使用 VLA。关键是我不认为 VLA 是矩阵的方法,因为它在执行期间不太可能具有相同的变量更改大小,这需要 VLA 的模糊设计。

如果您放弃使用双方括号语法,则使用简单的指针非常简单(我正在为此调整 4386427 代码):

#include <stdio.h>
#include <stdlib.h>

int *input_taker(int row, int col)
{
    int *mat = malloc(row * col * sizeof *mat);
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            mat[i * col + j] = i * col + j;  // Here you can read user input
        }
    }
    return mat;
}

int main ()
{
    int col = 8;
    int row = 5;
    int *p = input_taker(row, col);
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < col; ++j) {
            printf("%5d ", p[i * col + j]);
        }
        puts("");
    }
    free(p);
    return 0;
}

更好地将所有内容打包在一个结构中:

struct mat {
    int rows, cols;
    int *data;
};

并提供使用它的功能。

【讨论】:

  • 这不是二维数组,而是一维数组,导致索引容易出错
  • “这需要带有 VLA 的模糊设计。”不,更改行数很简单。使用您的解决方案更改列数同样困难
  • @4386427 通过结构访问应该可以解决这个问题。
  • 为什么要把简单的事情复杂化?
  • @4386427 一个好问题。我想 Paul Ogilvie 对您的回答的评论表明并不总是同意“复杂”。
【解决方案3】:

用户给定大小的二维数组

指向col 整数数组的指针。

两者似乎都避免使用 VLA 一词。 4386 的答案使用-Wvla 给出“C90 禁止 VLA”警告。

这个

int mat[row][col];

不工作,因为它是自动存储。

但是

int (*mat)[col];

只是一个指向 VLA 的指针;它可以被分配和返回。

为了(过度)简化 4386 的函数类型并拆分 mat 的定义,可以这样做:

void *array_maker(int row, int col)   // just a pointer; no dimensions, no type
{
    int (*mat)[col];                  // declare runtime inner dim.: ptr to VLA  
    mat = malloc(row * sizeof *mat);  // mallocate both dims

    for (int i = 0; i < row; i++)
    for (int j = 0; j < col; j++)
            mat[i][j] = i*col + j;    // fill the array[][] 
    return mat;
}

来自 main 的调用是:

int col, row;

int (*p)[col=8];                  // ptr. to VLA  
p = array_maker(row=5, col);      // implicit cast from void-ptr 

由于无论如何都涉及到 VLA,因此可以将其转过来并将数组指针放入参数中。这会将函数从 array-maker 转换为 array-filler:

void array_filler(int row, int col, int mat[][col])
{
    for (int i = 0; i < row; i++)
    for (int j = 0; j < col; j++)
            mat[i][j] = i*col + j;    // fill the array[][] 
}

现在数组必须由调用者分配 - 作为自动 VLA 或分配的 VLA 指针或固定大小的数组:

col=row=9;
int mat[row][col];  
//int (*mat)[col] = malloc(row * sizeof*mat); 
//int mat[9][9];
array_filler(row, col, mat);

int mat[row][col];错误的存储时间

int* input_taker(int row, int col) -> 不兼容类型警告

【讨论】:

    【解决方案4】:

    您的问题似乎是一个悬空指针。您必须在调用 input_taker 之前分配内存。

    #include <cstdio>
    #include <cstdlib>
    
    int* input_taker(int *ptr, int row, int col)
    {
        for (int i = 0; i < row; i++)
        {
            int *arr = &ptr[i*col];
            for (int j = 0; j < col; j++)
            {
                scanf("%d", &arr[j]);
            }
        }
        return ptr;
    }
    
    int main() {
        int n_rows, n_cols;
        n_rows = 2;
        n_cols = 3;
    //    int *matrix = (int*)malloc(n_rows*n_cols*sizeof(int));
        int matrix [n_rows][n_cols];
        input_taker(&matrix[0][0], n_rows, n_cols);
    
        for (int i = 0; i < n_rows; i++)
        {
            printf("[");
            for (int j = 0; j < n_cols; j++)
            {
                j==n_cols-1?printf("%d]\n", matrix[i][j]):printf("%d, ", matrix[i][j]);
            }
        }
        return 0;
    }
    

    我更改了函数参数但保留了返回值。但是,您可以返回 void

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多