使用 C 和指向指针的指针创建动态字符数组

Creating a dynamic array of characters using C with pointers to pointers

我正在尝试创建一个指向指针的指针数组,至少在我看来是这样。但是我使用 valgrind 运行 进行了无效的读写操作。

char **format_file(FILE *infile) {
     char **char_array = malloc(20 * sizeof(char*));
     int c;
     int cUsed = 0;

     while ((c = fgetc(infile)) != EOF) {
         char_array[cUsed] = c;
         cUsed += 1;
     }

     printf("%s", *char_array);
     return char_array;
}

代码通过读取已打开的文件来工作 "infile"。首先,我使用 malloc 分配了 20 个字符的内存,然后我尝试逐个字符地将文件读取到分配的内存数组中,直到达到 EOF。但是,我编写代码时valgrind的输出如下:

==7379== Invalid read of size 1
==7379==    at 0x4E7CB36: vfprintf (vfprintf.c:1597)
==7379==    by 0x4E85198: printf (printf.c:35)
==7379==    by 0x400755: format_file (formatter.c:27)
==7379==    by 0x4006C1: main (format265alt.c:21)
==7379==  Address 0x6f is not stack'd, malloc'd or (recently) free'd

第 27 行是 printf 命令,valgrind 将其称为大小为 1 的无效读取。

formatter.c是包含format_file函数的文件,而format265alt.c是调用了formatter.c函数的文件,打开要读取的文件。

我对 ** 的语法感到困惑,即如何访问和 read/write 分配的内存?

如果我没有提供足够的关于这个问题的信息,我深表歉意。

如果只是创建字符数组,一维字符数组就足够了。不需要 char** 业务。但是,如果您尝试将数组用作字符串,请确保以 null 终止该数组。

valgrind 抱怨是因为您存储的字符超出了分配对象的末尾。编译器应该抱怨您将字符存储到错误类型的对象中,使用 -Wall -W 启用有用的警告。

一个char **是一个指向char指针的指针,它可以指向一个char指针数组,也称为字符串数组。您必须为文件内容分配适当大小的数组和每个字符串。

这里有两种可能:

  • 该函数可以将整个文件加载到单个字符串中,但不需要 return 指向 char* 的指针,只需 returning 字符串 (char *) 就足够了。

  • 如果函数是 return 一个指向字符串数组的指针,每行一个,还有一个额外的 NULL,那么建议的 API 更合适最后,就像作为第二个参数传递给 main 函数的 argv 数组一样。

为此,您必须在从 FILE* 中读取更多行时重新分配字符串数组,并且每行都应随着其增长而重新分配。在字符串数组末尾添加一个NULL指针,表示结束。

这是一种非常低效的方法:

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

char **format_file(FILE *infile) {
      size_t lines = 0;
      char **array = malloc(1 * sizeof(char*));
      size_t pos = 0;
      char *line = malloc(1);
      int c;

      while ((c = getc(infile)) != EOF) {
          if (c == '\n') {
              line[pos] = '[=10=]';
              array = realloc(array, (lines + 2) * sizeof(char *));
              array[lines++] = line;
              line = malloc(1);
              pos = 0;
              continue;
          }
          line = realloc(line, pos + 2);
          line[pos++] = c;
    }
    if (pos > 0) {
        line[pos] = '[=10=]';
        array = realloc(array, (lines + 2) * sizeof(char *));
        array[lines++] = line;
    } else {
        free(line);
    }
    array[lines] = NULL;
    return array;
}