如何在C中的函数中使用2D数组作为输出参数

时间:2016-10-19 16:27:04

标签: c arrays file-io

我正在编写一个程序,使用Floyd算法计算图形上两点之间的最短路径。我需要写入二进制文件,然后从中读取并打印图形。我的问题在于此,因为我的函数签名必须是以下形式:void read_graph(char *filename, int *n, int ***A)

我写了以下内容:

void read_graph(char *filename, int *n, int ***A)
{
    FILE *fin;
    size_t i;
    int x;
    int **arr;

    fin  = fopen(filename, "rb");
    if (fin == 0) {
        printf("Error opening file\n");
        exit(1);
    } else {
        fread(&x, sizeof(int), 1, fin);
        printf("Read size of matrix %d\n",x);
        *n = x;
        fseek(fin, sizeof(int)+1, SEEK_SET);
        arr = malloc(x*sizeof(int *));
        if (arr == NULL) {
            printf("Not enough space.\n");
        }
        for (i = 0; i < x; ++i) {
            arr = malloc(x*sizeof(int));
        }
        for (i = 0;  i < x; ++i) {
            fread(arr,sizeof(int), x, fin);
        }

        //  ***A = **arr;    
    }
    fclose(fin);
    free2darray(*A, x);
}

free2darray是用于释放内存的实用程序功能。我的问题是,如果我在调用它之前分配一个2d数组,这个函数是有效的。但是,要求此函数将2d数组返回***A而不是相反。如果你能告诉我我做错了什么,那将会非常有帮助。对代码风格的批评也很受欢迎。

编辑:这是我当前正在调用该函数的方式:

int **arr;
   int x;
   size_t i;
   arr = malloc(5*sizeof(int*));
   if (arr == NULL) {
     printf("Cannot allocated memory for array\n");
     exit(1);
   }
   for (i = 0; i < 5; i++) {
     arr[i] = malloc(5*sizeof(int));
   }
   read_graph("test.dat", &x, &arr); 

5只是一个测试尺寸。先前通过使用随机值填充5 * 5数组来编写test.dat

由于

1 个答案:

答案 0 :(得分:2)

你很亲密。如果您在几分钟前阅读了我的答案,您可能已经注意到我的解决方案返回了指向动态数组的指针。然后我在你的问题的评论中看到函数原型是给定的,所以我修改了我的答案。

您需要在main()中执行的操作是声明指向int的指针以存储矩阵的大小,以及指向int的指针,该指针将传递给read_graph()函数arr。虽然这不是绝对必要的,但作为一个好的风格,我继续将这个指针(read_graph())初始化为NULL。我在这里包含几行来显示新数组的内容。

您需要在退出前释放已分配的内存。这是您在原始代码中遇到的主要问题之一:在调用arr时,您正在释放内存。在释放这些分配之前,您需要等到不再需要阵列内容。

我发现的另一个问题是,当您为动态数组的各个行分配内存时,您忘记索引malloc,因此您x编辑内存并将地址分配给它指针arr次。这是你的循环,它反复将内存重新分配给for (i = 0; i < x; ++i) { arr = malloc(x*sizeof(int)); } (并且因为对先前分配的引用丢失而导致内存泄漏):

A

传递给函数的指针malloc()用于接收对read_graph()的调用结果,以便从调用函数中看到分配的内存。这会稍微改变您的一些分配,因为您最初为此目的在x内声明了一个指针。我还改变了将值读入数组的循环,以便它一次读入一个值 - 看起来你一次尝试读取fseek()

你真的不需要size_t,因为文件指针已经在位,所以我删除了那一行。我还添加了一个检查,以确保数据文件正确关闭。我编写了一个测试数据文件,一切似乎都有效。我还将您的int变量更改为int s。我这样做是因为在生成编译器警告的循环中对size_t值与size_t值进行了比较。代码仍然可以正常工作,但没有意义忽略警告。我会将所有内容更改为int,但您从文件中读取矩阵的大小,这是代码中的size_t。如果您可以稍微更改文件格式,则矩阵的大小可以存储为#include <stdio.h> #include <stdlib.h> void read_graph(char *filename, int *n, int ***A); void free2darray(int ***A, int n); int main(void) { int x; int **arr = NULL; int i, j; read_graph("test.dat", &x, &arr); for (i = 0; i < x; i++) { for (j = 0; j < x; j++) printf("%d ", arr[i][j]); putchar('\n'); } /* Free allocated memory */ free2darray(&arr, x); return 0; } void read_graph(char *filename, int *n, int ***A) { FILE *fin; int i; int x; fin = fopen(filename, "rb"); if (fin == 0) { printf("Error opening file\n"); exit(1); } else { fread(&x, sizeof(int), 1, fin); printf("Read size of matrix %d\n",x); *n = x; *A = malloc(x*sizeof(int *)); if (*A == NULL) { printf("Not enough space.\n"); } for (i = 0; i < x; ++i) { (*A)[i] = malloc(x*sizeof(int)); } for (i = 0; i < x; ++i) for (int j = 0; j < x; ++j) fread(&(*A)[i][j], sizeof(int), 1, fin); } if (fclose(fin) != 0) fprintf(stderr, "Unable to close file\n"); } void free2darray(int ***A, int n) { for (int i = 0; i < n; i++) free((*A)[i]); free(*A); } 值。以下是修订后的代码:

int

修改

我必须创建一个测试文件,所以我为此添加了一些代码,但上面没有显示。它读取文本文件并创建程序可以使用的二进制文件。生成的二进制文件只是main() s的序列。我只是将代码放在5 1 2 3 4 5 .... 的开头,并在与“a.out”相同的目录中创建了一个名为“testdat.txt”的文件。我的文本文件在第一行包含5,然后是25个整数,每行一个:

/* Code to create a datafile from a text file */

FILE *fpin, *fpout;
char nstr[100];
int num_out;

fpin = fopen("testdat.txt", "r");
fpout = fopen("test.dat", "wb");
while (fgets(nstr, 100, fpin) != NULL) {
    num_out = atoi(nstr);
    fwrite(&num_out, sizeof(int), 1, fpout);
}
fclose(fpin);
fclose(fpout);

以下是代码:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()