简体   繁体   English

C程序设计:创建和写入二维文件数组作为函数

[英]C programming: Create and write 2D array of files as function

I have a very long program, which I am trying to shorten. 我有一个很长的程序,我想缩短它。 I frequently write 2d file arrays, but I repeat this process dozens of times throughout my program, so I am trying to write as a function to reduce mistakes on my part and make the code shorter and easier to read. 我经常编写2d文件数组,但是我在整个程序中重复了数十次此过程,因此我试图将其编写为一种函数,以减少我自己的错误,并使代码更短,更易于阅读。

I am modifying an example I got from Allocate memory 2d array in function C but doing so with a FILE array instead. 我正在修改从函数C中分配内存2d数组获得的示例但使用FILE数组代替。

I can already allocate 2D file arrays easily in main, but again, I want to do this as a function: 我已经可以很容易地在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;
}

I have tried almost every conceivable (to me, anyway) way of doing this, but I keep getting mistakes like this from valgrind: 我已经尝试了几乎所有可能的方法(无论如何对我而言),但是我不断从valgrind中得到这样的错误:

==16192== HEAP SUMMARY:
==16192==     in use at exit: 4,440 bytes in 3 blocks
==16192==   total heap usage: 3 allocs, 0 frees, 4,440 bytes allocated
==16192== 
==16192== Searching for pointers to 3 not-freed blocks
==16192== Checked 70,808 bytes
==16192== 
==16192== 552 bytes in 1 blocks are still reachable in loss record 1 of 3
==16192==    at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192==    by 0x4EA711C: __fopen_internal (iofopen.c:69)
==16192==    by 0x40080C: allocate_mem (create_file_array.c:11)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192== 
==16192== 648 bytes in 1 blocks are still reachable in loss record 2 of 3
==16192==    at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192==    by 0x4007AC: allocate_mem (create_file_array.c:7)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192== 
==16192== 3,240 bytes in 1 blocks are still reachable in loss record 3 of 3
==16192==    at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192==    by 0x400761: allocate_mem (create_file_array.c:5)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192== 
==16192== LEAK SUMMARY:
==16192==    definitely lost: 0 bytes in 0 blocks
==16192==    indirectly lost: 0 bytes in 0 blocks
==16192==      possibly lost: 0 bytes in 0 blocks
==16192==    still reachable: 4,440 bytes in 3 blocks
==16192==         suppressed: 0 bytes in 0 blocks
==16192== 
==16192== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==16192== 
==16192== 1 errors in context 1 of 2:
==16192== Invalid write of size 8
==16192==    at 0x40080D: allocate_mem (create_file_array.c:11)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==16192== 
==16192== 
==16192== 1 errors in context 2 of 2:
==16192== Use of uninitialised value of size 8
==16192==    at 0x40080D: allocate_mem (create_file_array.c:11)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192==  Uninitialised value was created by a heap allocation
==16192==    at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192==    by 0x4007AC: allocate_mem (create_file_array.c:7)
==16192==    by 0x400951: main (create_file_array.c:29)
==16192== 
==16192== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
create_file_array.c

How can I get allocate_mem and deallocate_mem to work? 我怎样才能使allocate_mem和deallocate_mem工作?

You should forget you ever heard about three stars or four stars. 您应该忘了听说过三颗星或四颗星。 C programming uses an inverse system compared with hotels: the more stars, the worse quality of the code. 与酒店相比,C编程使用的是逆系统:星星越多,代码的质量越差。

You don't even want a pointer-to-pointer-to... You want a 2D array. 您甚至都不想要指向……的指针。您想要一个2D数组。

That being said, note that this isn't all that trivial, since the type you want to have an array of is FILE* . 话虽如此,请注意,这并不是那么简单,因为您要拥有数组的类型是FILE* Most would-be veteran programmers will fail and suggest some nonsense with multiple for loops and multiple malloc calls, to launch a full-scaled attack on the poor innocent heap. 大多数想当老手的程序员都会失败,并提出一些废话,建议使用多个for循环和多个malloc调用,以对可怜的无辜堆发起全面的攻击。

Instead of that, start with main(). 而是从main()开始。 To save your sanity, you would probably want your main to look something like this: 为了节省理智,您可能希望主管道看起来像这样:

int main (void) 
{
  file_arr_t* array;    // pointer to a 2D array
  array = allocate_mem(5,3);
  deallocate_mem(array);
  return 0;
}

In which case the allocate_mem function needs to return a pointer to an allocated array. 在这种情况下, allocate_mem函数需要返回一个指向已分配数组的指针。 The C syntax for declaring array pointers is completely awful, so you'll need to create a typedef to save your sanity. 声明数组指针的C语法非常糟糕,因此您需要创建一个typedef来节省理智。 It is also bad practice to typedef away pointers, so preferably typedef an array type which you want to point at: typedef离开指针也是一种不好的做法,因此最好typedef一个要指向的数组类型:

typedef FILE* file_arr_t[3][5];   // type is an array of 3x5 FILE*

Where file_arr_t* will be a pointer to an array of 3x5 FILE pointers . 其中file_arr_t*指向3x5 FILE指针数组的指针 Phew. ew

Then you can write your functions as: 然后,您可以将函数编写为:

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);
}

EDIT 编辑

If you truly need to dimensions to be completely dynamical in run-time, I'm afraid you are stuck with one case of icky syntax or another, because then you can't use a typedef. 如果您真正需要在运行时实现完全动态化的尺寸标注,恐怕您会陷入一种棘手的语法或另一种情况,因为那样便无法使用typedef。 You'd end up with something unreadable like this: 您最终会得到这样的不可读内容:

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

In that case I would recommend to just go with void* instead: 在这种情况下,我建议只使用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);
}

First problem... 第一个问题...

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!

When i == 0 your initial pointer returned by arr = malloc(n*m*sizeof(FILE)); i == 0您的初始指针由arr = malloc(n*m*sizeof(FILE)); is overwritten and you leak (lose visibility to) this memory. 被覆盖,您会泄漏(丢失可见性)该内存。 This has to be fixed. 这是必须解决的。

My original thought was... Wow! 我最初的想法是……哇! You are working with ( FILE**** arr ) a pointer to a pointer to a pointer to a pointer. 您正在使用( FILE**** arr )指向指针的指针。 You really need to simplify this. 您确实需要简化此过程。

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

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