使用 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 个字符的内存,然后我尝试逐个字符地将文件读取到分配的内存数组中,直到达到 EO
F。但是,我编写代码时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;
}
我正在尝试创建一个指向指针的指针数组,至少在我看来是这样。但是我使用 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 个字符的内存,然后我尝试逐个字符地将文件读取到分配的内存数组中,直到达到 EO
F。但是,我编写代码时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;
}