【问题标题】:Problem when passing multidimensional array to a function in C将多维数组传递给C中的函数时出现问题
【发布时间】:2020-08-27 00:53:26
【问题描述】:

/*编写一个程序,使用函数计算方阵的对角线元素之和。这 函数应将总和返回给调用函数。 使用 gcc 版本 9.3.0 在 debain 测试中测试的程序 */

程序在不使用函数时运行良好,但存在问题,即传递的数组没有原始数组的所有元素,因此总和不正确。

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

int sum(int a[10][10],int d);

int main(){

    int r,c;
    puts("Enter the dimension of square matrix");
    scanf("%d %d",&r,&c);
    if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
    int a[r][c];
    puts("Enter the elements of the matrix");
    for(int i=0; i<r; ++i){
        for(int j=0; j<c; ++j){
            printf("Enter a[%d][%d] element = ",i+1,j+1);
            scanf("%d",&a[i][j]);
        }
    }

    int result = sum(a,r);

    printf("Sum of diagonal elements = %d \n",result);
    return 0;
}

int sum(int a[10][10],int d){
//for a square matrix no of diagonal element = row/col of matrix
    int result=0;
    for(int i=0; i<d; ++i){
        result=result+a[i][i];
    }

    return result;
}

【问题讨论】:

  • 您需要为r 输入10 并为c 输入10 才能有任何工作机会。
  • 将 r 和 c 设为全局会是不好的做法,即添加 int r,c;上面 sum 的函数原型? (如果不是那么它将解决问题)
  • 是的,这是不好的做法......而且它无论如何也解决不了你的问题。

标签: c


【解决方案1】:

你的代码有两个问题:

  1. sum 函数接收 10x10 数组。您的代码可以接收任何大小的矩阵。如果您要求 2x2 矩阵,然后 sum 将其视为 10x10 数组并尝试访问 [2][2],会发生什么?那是未定义的行为。您不应该在 sum 参数中声明数组的大小。

  2. 您不能接收数组大小作为输入,然后以这种方式声明数组。您应该分配动态内存。我鼓励您阅读有关动态内存分配的更多信息

看看下面的变化:

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

int sum(int a[][],int d);

int main(){

    int r,c;
    puts("Enter the dimension of square matrix");
    scanf("%d %d",&r,&c);
    if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix

    //allocate memory
    int* a = (int*)malloc(sizeof(*a)*r);
    for(int i=0;i<r;i++){
        a[i] = (int*)malloc(sizeof(int)*c)
    }
    puts("Enter the elements of the matrix");
    for(int i=0; i<r; ++i){
        for(int j=0; j<c; ++j){
            printf("Enter a[%d][%d] element = ",i+1,j+1);
            scanf("%d",&a[i][j]);
        }
    }

    int result = sum(a,r);

    printf("Sum of diagonal elements = %d \n",result);

    //Free memory
    for(int i=0;i<r;i++)
        free(a[i])
    free(a)
    return 0;
}

int sum(int a[][d],int d){
//for a square matrix no of diagonal element = row/col of matrix
    int result=0;
    for(int i=0; i<d; ++i){
        result=result+a[i][i];
    }

    return result;
}

【讨论】:

  • 函数没有接收到 junk,没有添加任何内容来创建一个 10x10 数组,但是从数组中读取的行为是未定义的。我鼓励你添加一个更正 OP 代码的提案
  • int sum(int a[][], int d) 不会编译。
  • @KamilCuk 我太习惯将它作为指针传递:( 我会改变它
【解决方案2】:

当您创建一个真正的二维数组时,除了第一个维度之外的所有维度都用于实际的索引计算。您有两种选择:

  1. 为矩阵使用静态最大尺寸(比如 10):

    int sum(int a[][10],int d);
    
    int main(){
    
        int r,c;
        puts("Enter the dimension of square matrix");
        scanf("%d %d",&r,&c);
        scanf("%d %d",&r,&c);
        if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
        if (r > 10) {puts("Size must be at most 10"); exit(0);} // check size
        int a[r][10];             // Force a well know row size
        ...
    int sum(int a[][10],int d){
    //for a square matrix no of diagonal element = row/col of matrix
        ...
    
  2. 在函数调用之前传递动态维度:

    int sum(int d, int a[][d]);
    
    int main(){
    
        int r,c;
        puts("Enter the dimension of square matrix");
        scanf("%d %d",&r,&c);
        if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
        int a[r][c];
        ...
        int result = sum(r, a);
        ...
    int sum(int d, int a[][d]){
    //for a square matrix no of diagonal element = row/col of matrix
    

【讨论】:

    【解决方案3】:

    如前所述,对于rc 的任何值(1010 除外),您在将数据输入大小错误的静态数组时会遇到问题。
    有几种方法可以重构来解决这个问题,一种是动态内存内存分配:

    改变这个:

    int sum(int a[10][10],int d);
    
    int main(){
    
        int r,c;
        puts("Enter the dimension of square matrix");
        scanf("%d %d",&r,&c);
        if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
        int a[r][c];  
    

    对此:

    int sum(int **a,int d);
    
    int main(){
    
        int r,c;
        puts("Enter the dimension of square matrix");
        scanf("%d %d",&r,&c);
        if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
        int **a = calloc(c, sizeof(int *));
        if(a)
        {
            for(int i = 0;i<c;i++)
            {
                a[i] = calloc(r, sizeof(int));
            }
        }
    

    然后改变下面的函数原型:

    int sum(int a[10][10],int d){
    

    收件人:

    int sum(int **a,int d){
    

    使用calloc 创建的每个元素在不再需要时都必须释放。

    例如:

            for(int i = 0;i<c;i++)
            {
                free(a[i]);
            }
            free(a);
    

    【讨论】:

      【解决方案4】:

      rc 输入的是什么?如果不是1010,那么不,这段代码没有工作的希望。

      另外,如果要求数组是方阵,为什么要问行数列?只需要求一个值并将其应用于两个维度:

      int r;
      ...
      scanf( "%d", &r );
      ...
      int a[r][r];
      

      由于您在 main 中将 a 创建为 VLA,因此您还需要在 sum 中将其声明为 VLA:

      int sum( int r, int a[r][r] ) // r must be declared first.
      {
        ...
      }
      

      然后适当地更改您的呼叫:

      int result = sum( r, a );
      

      【讨论】:

        【解决方案5】:
        #include <stdio.h>
        #include <stdlib.h>
        
        int sum(int *a,int r);
        
        int main(){
        
            int r,c;
            puts("Enter the dimension of square matrix");
            scanf("%d %d",&r,&c);
            if (r != c) {puts("Not a square matrix");exit(0);}//check if square matrix
            int a[r][c];
            puts("Enter the elements of the matrix");
            for(int i=0; i<r; ++i){
                for(int j=0; j<c; ++j){
                    printf("Enter a[%d][%d] element = ",i+1,j+1);
                    scanf("%d",&a[i][j]);
                }
            }
        
            int result = sum((int *)a,r);
        
            printf("Sum of diagonal elements = %d \n",result);
            return 0;
        }
        
        int sum(int *a,int r){
        //for a square matrix no of diagonal element = row/col of matrix
            int result=0;
            for(int i=0; i<r; i++){
                result=result+(*(a+ i*r) + i);
            }
        return result;
        }
        

        【讨论】:

        • 并非在所有情况下都有效。例如,让维度为 2*2,元素为 4 3 2 1,结果应为 5,但它给出 7,如果输入值为 1 2 3 4,则它给出 5。
        【解决方案6】:

        基本思想是展平二维数组。例如,一个 3 行 5 列的 2D 数组的元素顺序与 15 个元素的 1D 数组的顺序相同。

        int a2[3][5] = {{0, 1, 2, 3, 4}, {1, 2, 3, 4, 5}, {4, 5, 6, 7, 8}};
        

        有完全相同的序列
        int a1[15] = {0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8};
        

        虽然a1a2 的类型不兼容。

        那么...如何展平数组?

        您可以简单地使用a[0][0]int* 类型)的地址并假设所有元素都按顺序排列。同时传递维度信息,以便您可以计算函数内部的索引。

        #include <stdio.h>
        
        void foo(int *flattened, int rows, int cols) {
            printf("original[2][3] is %d\n", flattened[2*cols + 3]);
        }
        
        int main(void) {
            int one[14][14]; one[2][3] = 42;
            foo(&one[0][0], 14, 14);
        
            int two[4][100]; two[2][3] = 42;
            foo(&two[0][0], 4, 100);
        
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2019-04-20
          • 2015-09-10
          • 2014-01-15
          • 1970-01-01
          • 2014-11-19
          • 2014-03-16
          • 2011-09-27
          • 1970-01-01
          相关资源
          最近更新 更多