C编程:创建并编写2D文件数组作为函数

C编程:创建并编写2D文件数组作为函数,c,file,multidimensional-array,writefile,C,File,Multidimensional Array,Writefile,我有一个很长的程序,我正试图缩短它。我经常编写2d文件数组,但我在整个程序中重复了几十次这个过程,因此我尝试将其作为一个函数来编写,以减少我的错误,并使代码更短、更易于阅读 我正在修改我从中得到的一个示例,但改为使用文件数组 我已经可以在main中轻松地分配2D文件数组,但我想再次将其作为一个函数: #include <stdio.h> #include <stdlib.h> void allocate_mem(FILE**** arr, const int n, co

我有一个很长的程序,我正试图缩短它。我经常编写2d文件数组,但我在整个程序中重复了几十次这个过程,因此我尝试将其作为一个函数来编写,以减少我的错误,并使代码更短、更易于阅读

我正在修改我从中得到的一个示例,但改为使用文件数组

我已经可以在main中轻松地分配2D文件数组,但我想再次将其作为一个函数:

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

void allocate_mem(FILE**** arr, const int n, const int m) {
    arr = malloc(n*m*sizeof(FILE));
    for(int i=0; i<n; i++) {
        arr[i] = malloc(m*sizeof(FILE));
        for (unsigned int j = 0; j < m; j++) {
            char filename[64];
            sprintf(filename,"tmp_%d_%d.txt",i,j);
            *arr[i][j] = fopen(filename,"w");
            fprintf(*arr[i][j],"blah %d %d\n",i,j);
        }
    }
}

void deallocate_mem(FILE**** arr, const int n, const int m){
    for (int i = 0; i < n; i++) {
        for (unsigned int j = 0; j < m; j++) {
            fclose(*arr[i][j]);
        }
        free((*arr)[i]);
    }
    free(*arr); 
}

int main() {
    FILE ***array;
    allocate_mem(&array,5,3);
    deallocate_mem(&array,5,3);
    return 0;
}
如何让allocate\u mem和deallocate\u mem正常工作?

第一个问题

void allocate_mem(FILE**** arr, const int n, const int m) {
    arr = malloc(n*m*sizeof(FILE));      // probably not what you want!
    for(int i=0; i<n; i++) {
       arr[i] = malloc(m*sizeof(FILE));  //overwrites initial value of arr when i==0!
void allocate_mem(文件****arr,const int n,const int m){
arr=malloc(n*m*sizeof(FILE));//可能不是您想要的!

对于(int i=0;i你应该忘记你曾经听说过三星或四星。与酒店相比,C编程使用的是一个逆系统:星级越多,代码质量越差

话虽如此,请注意,这并不是那么简单,因为您想要的数组类型是
FILE*
。大多数有经验的程序员都会失败,并建议使用多个for循环和多个malloc调用来对可怜的无辜堆发起全面攻击

而不是从main()开始。 为了保持头脑清醒,您可能希望主屏幕的外观如下所示:

int main (void) 
{
  file_arr_t* array;    // pointer to a 2D array
  array = allocate_mem(5,3);
  deallocate_mem(array);
  return 0;
}
// turning messy, avoid writing code like this.
void allocate_mem (size_t x, size_t y, FILE* (**arr_ptr)[x][y])
{
  *arr_ptr = malloc(sizeof(FILE*[x][y]));
  (**arr_ptr)[i][j] = something;
}

int main (void)
{
  FILE* (*array)[5][3];
  allocate_mem(5, 3, &array);
}
在这种情况下,
allocate\u mem
函数需要返回一个指向已分配数组的指针。声明数组指针的C语法非常糟糕,因此您需要创建一个typedef来保存您的理智。另外,typedef远离指针也是一种不好的做法,因此最好是typedef一个您想要指向的数组类型:

typedef FILE* file_arr_t[3][5];   // type is an array of 3x5 FILE*
其中
file\u arr\u t*
将是指向3x5文件指针数组的指针。Phew

然后,您可以将函数编写为:

file_arr_t* allocate_mem (size_t x, size_t y)
{
  file_arr_t* array = malloc(sizeof(FILE*[x][y]));

  (*array)[i][j] = ... // do things with the pointer to array

  return array;
}

void deallocate_mem(file_arr_t* array)
{
  free(array);
}

编辑

如果您真的需要在运行时完全动态地创建维度,恐怕您会遇到这样或那样令人讨厌的语法,因为这样您就不能使用typedef了。您最终会遇到如下无法读取的情况:

int main (void) 
{
  file_arr_t* array;    // pointer to a 2D array
  array = allocate_mem(5,3);
  deallocate_mem(array);
  return 0;
}
// turning messy, avoid writing code like this.
void allocate_mem (size_t x, size_t y, FILE* (**arr_ptr)[x][y])
{
  *arr_ptr = malloc(sizeof(FILE*[x][y]));
  (**arr_ptr)[i][j] = something;
}

int main (void)
{
  FILE* (*array)[5][3];
  allocate_mem(5, 3, &array);
}
在这种情况下,我建议只使用
void*

void* allocate_mem (size_t x, size_t y)
{
  // omit inner-most dimension on purpose to get clearer access syntax later
  FILE* (*array)[y] = malloc(sizeof(FILE*[x][y]));

  // now this pointer can be used with intuitive syntax:
  array[i][j] = something;
  ...

  return array;
}

int main (void)
{
  FILE* (*array)[5][3];
  array = allocate_mem(5, 3);
}

“我总是犯错误。”这不是一个有人可以帮助您解决的问题。OldProgrammer-我已经从valgrindIt添加了错误。自从我看到一个4星变量
文件****
!指向指向指针的指针仍然不是数组。不。如果您添加更多的星,它将不会变成一个。@Lundin,刚刚看到这个。我很困惑。什么你的评论是什么意思?我在回答中没有提到数组?问题是关于如何动态创建文件指针的2D数组。最后一个问题是“如何让allocate_mem和deallocate_mem工作?”。我同意标题很差。+1表示“星星越多,代码越差”.可读性/可维护性在99%的情况下胜过指针功夫,不会留下任何粘性残留物。@Lundin我如何修改此代码,以便在main中确定typedef大小?@con编辑的答案涵盖了运行时需要真正动态的维度的情况。