初始化二维字符串动态数组并按引用传递
Initializing two dimensional string dynamic array and passing by reference
我正在尝试学习 C 指针传递。所以请原谅我的无知
我想在函数中分配一个动态分配的二维字符串数组。
函数签名无效,所以参数是引用。
测试文件包含这两行。
I am testing.
This is not an empty file.
这是我到目前为止所做的。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void read_lines(FILE *fp, char** lines, int *num_lines) {
ssize_t read;
char * line = NULL;
size_t len = 0;
*num_lines = 0;
while ((read = getline(&line, &len, fp)) != -1) {
if (*num_lines == 0) {
// For the first time it holds only one char pointer
*lines = malloc(sizeof(char *));
} else {
// Every time a line is read, space for next pointer is allocated
*lines = realloc(*lines, (*num_lines) * sizeof(char *));
}
// allocate space where the current line can be stored
*(lines + (*num_lines)) = malloc(len * sizeof(char));
// Copy data
strcpy(*(lines + (*num_lines)), line);
printf("Retrieved line of length %zu:\n", read);
printf("%s\n", line);
(*num_lines)++;
// After first line subsequent lines get truncated if I free
// the storage here, then subsequent lines are not read completely
//if (line) {
// free(line);
//}
}
if (line) {
free(line);
}
}
int main(void)
{
FILE * fp;
char *array;
int num_lines;
fp = fopen("file.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
read_lines(fp, &array, &num_lines);
printf("After returning\n");
// Intend to access as array[0], array[1] etc
// That's not working
// If I access this way then I get seg violation after first line
printf("%s\n", &array[0]);
fclose(fp);
}
我的问题与代码内联:
- 为什么我不能在 while 循环内为
line
释放存储空间?
- 如何访问
main
中返回的二维数组? array[0]
array[1]
好像不行?我想做类似的事情。
- 为什么我现在这样会产生seg fault?
更正后的代码将帮助我理解。此外,任何人都可以提供任何好的参考来澄清 C 的这些概念,我们将不胜感激。
如果您在 while 循环中 free(line)
,则必须在下一次调用之前将 line
重置为 NULL
并将 len
重置为 0
getline
。否则,getline
会认为 line
是大小为 len
的有效缓冲区,并可能会尝试写入它,这实际上是现在所谓的“悬挂指针”。
在realloc
行中,大小应该是(*num_lines + 1) * sizeof(char *)
,需要多分配一个元素来容纳刚刚读取的行。
而array
变量为char*
,取其地址赋给read_lines
的参数lines
。所以 lines
是 array
的地址,而 *lines
只是 array
本身。
但是
// allocate `char*[1]`
*lines = malloc(sizeof(char *));
和
// allocate `char*[N]` with N=`*num_lines`
*lines = realloc(*lines, (*num_lines) * sizeof(char *));
您将 char*[]
分配给 array
,实际上是 char*
。
所以,如果你想让你的函数 return 一个字符串数组(即 char*[]
或 char**
),你必须使参数成为一个指向数组的指针字符串(即 char***
)。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void read_lines(FILE * fp, char*** lines, int* num_lines) {
ssize_t read;
char* buffer = NULL;
size_t buffer_len = 0;
*num_lines = 0;
while ((read = getline(&buffer, &buffer_len, fp)) != -1) {
// `*lines` is actually `array`,
// modify `*lines` will effectively modify `array`
if (*num_lines == 0) {
// `array` now is `char*[1]`
*lines = (char**)malloc(sizeof(char*)); // A
}
else {
// `array` now is `char*[(*num_lines) + 1]`
*lines = (char**)realloc(*lines, (*num_lines + 1) * sizeof(char*)); // B
}
// *(x+n) is the same as x[n], this line is actually doing:
// `array[*num_lines] = malloc...
*(*lines + (*num_lines)) = (char*)malloc((read + 1) * sizeof(char)); // C
strcpy(*(*lines + (*num_lines)), buffer);
(*num_lines)++;
printf("Retrieved line of length %zu:\n", read);
printf("%s\n", buffer);
}
if (buffer) {
// `line` is `malloc`ed or `realloc`ed by `getline`,
// have to be `free`ed
free(buffer);
}
}
int main(void)
{
FILE* fp;
char** array;
int num_lines;
fp = fopen("file.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
read_lines(fp, &array, &num_lines);
printf("After returning\n");
for (int i = 0; i < *num_lines; i++) {
printf("%s\n", array[i]);
free(array[i]); // corresponding to C
}
free(array); // corresponding to A or B
fclose(fp);
}
我正在尝试学习 C 指针传递。所以请原谅我的无知
我想在函数中分配一个动态分配的二维字符串数组。 函数签名无效,所以参数是引用。
测试文件包含这两行。
I am testing.
This is not an empty file.
这是我到目前为止所做的。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void read_lines(FILE *fp, char** lines, int *num_lines) {
ssize_t read;
char * line = NULL;
size_t len = 0;
*num_lines = 0;
while ((read = getline(&line, &len, fp)) != -1) {
if (*num_lines == 0) {
// For the first time it holds only one char pointer
*lines = malloc(sizeof(char *));
} else {
// Every time a line is read, space for next pointer is allocated
*lines = realloc(*lines, (*num_lines) * sizeof(char *));
}
// allocate space where the current line can be stored
*(lines + (*num_lines)) = malloc(len * sizeof(char));
// Copy data
strcpy(*(lines + (*num_lines)), line);
printf("Retrieved line of length %zu:\n", read);
printf("%s\n", line);
(*num_lines)++;
// After first line subsequent lines get truncated if I free
// the storage here, then subsequent lines are not read completely
//if (line) {
// free(line);
//}
}
if (line) {
free(line);
}
}
int main(void)
{
FILE * fp;
char *array;
int num_lines;
fp = fopen("file.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
read_lines(fp, &array, &num_lines);
printf("After returning\n");
// Intend to access as array[0], array[1] etc
// That's not working
// If I access this way then I get seg violation after first line
printf("%s\n", &array[0]);
fclose(fp);
}
我的问题与代码内联:
- 为什么我不能在 while 循环内为
line
释放存储空间? - 如何访问
main
中返回的二维数组?array[0]
array[1]
好像不行?我想做类似的事情。 - 为什么我现在这样会产生seg fault?
更正后的代码将帮助我理解。此外,任何人都可以提供任何好的参考来澄清 C 的这些概念,我们将不胜感激。
如果您在 while 循环中 free(line)
,则必须在下一次调用之前将 line
重置为 NULL
并将 len
重置为 0
getline
。否则,getline
会认为 line
是大小为 len
的有效缓冲区,并可能会尝试写入它,这实际上是现在所谓的“悬挂指针”。
在realloc
行中,大小应该是(*num_lines + 1) * sizeof(char *)
,需要多分配一个元素来容纳刚刚读取的行。
而array
变量为char*
,取其地址赋给read_lines
的参数lines
。所以 lines
是 array
的地址,而 *lines
只是 array
本身。
但是
// allocate `char*[1]`
*lines = malloc(sizeof(char *));
和
// allocate `char*[N]` with N=`*num_lines`
*lines = realloc(*lines, (*num_lines) * sizeof(char *));
您将 char*[]
分配给 array
,实际上是 char*
。
所以,如果你想让你的函数 return 一个字符串数组(即 char*[]
或 char**
),你必须使参数成为一个指向数组的指针字符串(即 char***
)。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void read_lines(FILE * fp, char*** lines, int* num_lines) {
ssize_t read;
char* buffer = NULL;
size_t buffer_len = 0;
*num_lines = 0;
while ((read = getline(&buffer, &buffer_len, fp)) != -1) {
// `*lines` is actually `array`,
// modify `*lines` will effectively modify `array`
if (*num_lines == 0) {
// `array` now is `char*[1]`
*lines = (char**)malloc(sizeof(char*)); // A
}
else {
// `array` now is `char*[(*num_lines) + 1]`
*lines = (char**)realloc(*lines, (*num_lines + 1) * sizeof(char*)); // B
}
// *(x+n) is the same as x[n], this line is actually doing:
// `array[*num_lines] = malloc...
*(*lines + (*num_lines)) = (char*)malloc((read + 1) * sizeof(char)); // C
strcpy(*(*lines + (*num_lines)), buffer);
(*num_lines)++;
printf("Retrieved line of length %zu:\n", read);
printf("%s\n", buffer);
}
if (buffer) {
// `line` is `malloc`ed or `realloc`ed by `getline`,
// have to be `free`ed
free(buffer);
}
}
int main(void)
{
FILE* fp;
char** array;
int num_lines;
fp = fopen("file.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
read_lines(fp, &array, &num_lines);
printf("After returning\n");
for (int i = 0; i < *num_lines; i++) {
printf("%s\n", array[i]);
free(array[i]); // corresponding to C
}
free(array); // corresponding to A or B
fclose(fp);
}