【问题标题】:C: Using a 2D array created in a function during mainC:使用在 main 函数中创建的二维数组
【发布时间】:2021-01-28 20:09:15
【问题描述】:

我查看了措辞相似的问题,但没有解决我的问题。 我的目标是从 C 中的文本文件中读取矩阵,然后对其执行操作。目前,我正在编写一个函数来读取矩阵。文本文件始终具有格式

# Comment
# Comment
matrix NROWS NCOLS
DATA DATA DATA
DATA DATA DATA etc
end

所以对于 3x4 矩阵:

# Comment
# Comment
matrix 3 4
7.16669652013   8.21223145665   8.78374366033   5.87828106521   
7.32124040244   4.30552353817   1.67905652974   3.91825198378   
7.28717047595   3.83999063812   5.53693148121   6.03363152874
end

我目前的功能是:

void read_matrix(char *filename, int rows, int cols) {
    char *status;
    char line[MAX_FILE_LINE_SIZE];
    int line_no = 1;
    char *data_line;
    double matrix[rows][cols];

    printf("Reading Matrix...\n");
    FILE *inf = fopen(filename, "r");
    if (!inf) {
        fprintf(stderr, "Error, could not open file '%s'\n", filename);
        exit(1);
    }
    
    status = fgets(line, sizeof(line), inf);
    while (status) {
        status = fgets(line, sizeof(line), inf);
        ///printf("%i: %s", line_no, line);
        if (line_no >= 3 && line_no < 3+rows) {
            int i=0;
            data_line = strtok(line, " \t");
            while (data_line != NULL) {
                matrix[line_no-3][i] = atof(data_line);
                data_line = strtok(NULL, " \t");
                i++;
            }
        }
        line_no ++;
    }
    printf("PRINT MATRIX\n");
    for (int z=0; z<rows; z++) {
        for (int j=0; j<cols; j++) {
            printf("matrix[%i][%i] = %f\n",z, j, matrix[z][j]);
        }
    }
    fclose(inf);
}

效果很好,所以在函数结束时,我将所有数据保存到二维数组matrix[rows][cols] 中。 然而,我完全不知道如何在 main 中使用这个函数,因为在函数之外,变量不再在范围内。任何帮助将不胜感激。

【问题讨论】:

    标签: c function multidimensional-array


    【解决方案1】:

    “但是我完全不知道如何在 main 中使用这个函数,因为在函数之外,变量不再在范围内”

    您已正确地将问题确定为范围。它可以通过多种方式解决。我喜欢以下内容:

        double ** read_matrix(char *filename, int *rows, int *cols);//requires memory allocation
    

    在此,函数将返回array,并将filename作为参数传递,并且因为在读取文件之前不知道大小参数,所以传递指向rowscols 的指针。它将被称为:

    int main(void)
    {
         const char filename[] = {"c:\\somefile.txt"};
         double **array = NULL;
         int rows, cols;
         ... other variables
         array = read_matrix(filename, &rows, &cols);
         if(array)
         {
              // use array
              ...
              free(array);
         }
    

    read_matrix() 的内部结构包括:

    • 读取和解析文件以获取 rowscols 的值和数组的数据。
    • 使用rowscols,将内存分配给double **array。 (使用了 malloc())
    • 用数据值填充新的动态分配的array
    • *cols == 设置为内部确定的列值。
    • *rows == 设置为内部确定的行值。
    • 返回数组。

    然后,回到main()

    • 使用array 对象。
    • free(array);

    read_matrix() 函数内部,调用的内存分配可以(并且可能应该)实现为另一个函数,例如:

    double ** Create2D(int c, int r)
    {   
        double **arr;
        int    y;
        
        arr   = calloc(c, sizeof(double *));
        for(y=0;y<c;y++)
        {
            arr[y] = calloc(r, sizeof(double)); 
        }
        return arr;
    }
    

    称为:

    double ** read_matrix(char *filename, int *rows, int *cols)
    {
         int cols=0, rows=0, i, j;
         
         //variables, initializations
         //read and parse files
         //convert values read from file from text into `cols` and `rows`
         //allocate memory for double **array
         //place data values from file into array
         double **array = Create2D(rows, cols
         if(array)
         {
             for(i=0;i<rows;i++)
             {
                 for(j=0;j<cols;j++)
                 {
                      array[i][j] = data[i][j];
                 }
             }
         }
         return array;  //must test that array is not null in caller
     }
    

    Create2D() 可以在哪里实现:

    double ** Create2D(int r, int c)
    {   
        double **arr;
        int    y;
        
        arr   = calloc(c, sizeof(double *));
        for(y=0;y<c;y++)
        {
            arr[y] = calloc(r, sizeof(double)); 
        }
        return arr;
    }                 
    

    【讨论】:

    • 我收到来自Create2D() 函数的错误,arr[y] = calloc(r, sizeof(double)); 行给了我错误:“从类型'void *' 分配给类型'double' 时类型不兼容”。编辑:这只是我的代码中的一个错字,我将arr 初始化为double *arr; 而不是double **arr;
    • @AceTorterra1 - 您是否在 C++ 编译器中进行编译?如果是这样,则要求您转换[m][c]alloc()的返回值,即arr[y] = (double)calloc(r, sizeof(double));,否则,如果C编译器转换is not recommended
    • 效果很好,谢谢!出于兴趣,您为什么建议在单独的函数中分配内存?
    • @AceTorterra1 - 欢迎您。 为什么[?] 这只是我的偏好。但总的来说,我相信许多程序员都会同意,通过将代码用于支持功能(例如分配多维数组的内存)其他地方。迁移到单独的函数可读性和可维护性的好处。
    【解决方案2】:

    不建议在 C 中使用 VLA(可变长度数组)。 添加一个“allocate_matrix”函数,该函数将返回一个用malloc分配的双**矩阵,并将其返回给main! 不要忘记在使用后释放所有东西;)

    【讨论】:

    • 不能将double matrix[rows][cols];等真正的二维数组作为双指针传递。
    • VLA 是为在C 中的C99 中使用而创建的,并且仍然包含在最新的标准中,它们是一种非常有用的方法,并且在C 编程中不鼓励使用它们
    • 在 C11 中它们是可选的,它们很容易被滥用。但取决于您的意图,它们可以是很好的补充是的
    【解决方案3】:

    您将需要使用 malloc 动态分配矩阵并从函数中返回它,这样您就可以从函数中返回它并访问您保存在范围之外的信息,没有办法做到这一点C 没有动态分配它。 这是另一个用户的回答,展示了如何动态分配矩阵:https://stackoverflow.com/a/2128754/6365408 直观的方法是分配一个指针指针指向两倍大小的列,并在每个索引中分配一个for循环中的一行:

    int **mat = (int **)malloc(rows * sizeof(int*));
    for(int i = 0; i < rows; i++) mat[i] = (int *)malloc(cols * sizeof(int));
    

    但是您会失去参考位置,这会影响性能。 第二个选项是:

    int *mat = (int *)malloc(rows * cols * sizeof(int));
    

    然后,您使用模拟矩阵

    int offset = i * cols + j;
    // now mat[offset] corresponds to m(i, j)
    

    用于行优先排序和

    int offset = i + rows * j;
    // not mat[offset] corresponds to m(i, j)
    

    最后,您将不得不释放您使用 malloc 进行的所有分配。

    【讨论】:

    • 进入我的矩阵的值为floats,我还能在malloc 命令中使用int吗?
    • @AceTorterra1 - 不,它们必须是 double
    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 2016-04-23
    • 1970-01-01
    相关资源
    最近更新 更多