繁体   English   中英

如何在C函数中将2D数组用作输出参数

[英]How to use a 2D array as an output parameter in a function in C

我正在编写一个程序,使用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

谢谢

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

main()您需要做的就是声明一个指向int的指针以存储矩阵的大小,以及一个指向int的指针的指针,该指针将传递给函数read_graph() 尽管不是严格必需的,但出于良好的风格,我继续将指针( arr )初始化为NULL。 我在此处添加了几行内容来显示新数组的内容。

您需要在退出之前释放分配的内存。 这是原始代码中的主要问题之一:在对read_graph()的调用结束时释放了内存。 您需要等到不再需要数组内容后再释放这些分配。

我发现的另一个问题是,当你的动态数组的各行分配的内存,你忘了指数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值与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()的开头,并在与“ a.out”相同的目录中创建了一个名为“ testdat.txt”的文件。 我的文本文件的第一行包含5,然后是25个整数,每行包含一个:

5
1
2
3
4
5
....

这是代码:

/* 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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM