getline into char** 只产生最后一行
getline into char** yields only the last line
我正在尝试将 getline(..., line, ...) 中的行存储到 char** 数组中。
但是当我遍历数组以打印行时,它只打印最后一行。
我想我错过了这个人的某些东西。
the input file
standard output
int fill_map(t_args *args)
{
char *line = NULL;
args->maze = NULL;
int i = 0;
size_t len = 0;
ssize_t nread;
args->maze = malloc(sizeof(char *));
for (size_t j = 0; (nread = getline(&line, &len, args->stream)) != -1; i++)
{
if (i == 1)
args->width = (int)nread;
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args->maze[i] = line;
}
args->height = i;
for (size_t i = 0; i < (size_t)args->height; i++)
{
printf("%ld %s", i, args->maze[i]);
}
return nread;
}
你还需要为每一行分配内存。然后你需要复制这行。
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args -> maze[i] = malloc(strlen(line) + 1);
strcpy(args->maze[i], line);
您当前的代码正在重用缓冲区 line
进行读取,并且 getline
仅在其大小太小无法容纳下一行读取时才重新分配它(并且,在这种情况下,free
是前一个缓冲区!)。因此,连续的行将存储在同一缓冲区中的同一地址,该地址分配给 maze[i]
.
为避免这种情况,您可以在每次调用 getline
:
之前重置 line
和 len
for (size_t j = 0; (nread = getline(&line, &len, args->stream)) != -1; i++)
{
if (i == 1)
args->width = (int)nread;
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args->maze[i] = line;
line = NULL;
len = 0;
}
free(line); // Important!
请注意,我们需要在最后一次 getline
调用之后 free(line)
,即使该调用失败了。
此外,我会抗议这种对 for
循环的滥用,尽管这当然是一种风格问题:因为您并不是真正迭代声明和更新的同一个变量,我将文件读取和循环 i
分开(无论如何 j
有什么意义?),并使用 while
循环;这也使 i
的使用更简单(不需要 i + 1
):
while ((nread = getline(&line, &len, args->stream)) != -1) {
++i;
args->width = (int) nread;
args->maze = realloc(args->maze, sizeof(char *) * i);
args->maze[i] = line;
line = NULL;
len = 0;
}
我正在尝试将 getline(..., line, ...) 中的行存储到 char** 数组中。 但是当我遍历数组以打印行时,它只打印最后一行。 我想我错过了这个人的某些东西。
the input file
standard output
int fill_map(t_args *args)
{
char *line = NULL;
args->maze = NULL;
int i = 0;
size_t len = 0;
ssize_t nread;
args->maze = malloc(sizeof(char *));
for (size_t j = 0; (nread = getline(&line, &len, args->stream)) != -1; i++)
{
if (i == 1)
args->width = (int)nread;
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args->maze[i] = line;
}
args->height = i;
for (size_t i = 0; i < (size_t)args->height; i++)
{
printf("%ld %s", i, args->maze[i]);
}
return nread;
}
你还需要为每一行分配内存。然后你需要复制这行。
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args -> maze[i] = malloc(strlen(line) + 1);
strcpy(args->maze[i], line);
您当前的代码正在重用缓冲区 line
进行读取,并且 getline
仅在其大小太小无法容纳下一行读取时才重新分配它(并且,在这种情况下,free
是前一个缓冲区!)。因此,连续的行将存储在同一缓冲区中的同一地址,该地址分配给 maze[i]
.
为避免这种情况,您可以在每次调用 getline
:
line
和 len
for (size_t j = 0; (nread = getline(&line, &len, args->stream)) != -1; i++)
{
if (i == 1)
args->width = (int)nread;
args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
args->maze[i] = line;
line = NULL;
len = 0;
}
free(line); // Important!
请注意,我们需要在最后一次 getline
调用之后 free(line)
,即使该调用失败了。
此外,我会抗议这种对 for
循环的滥用,尽管这当然是一种风格问题:因为您并不是真正迭代声明和更新的同一个变量,我将文件读取和循环 i
分开(无论如何 j
有什么意义?),并使用 while
循环;这也使 i
的使用更简单(不需要 i + 1
):
while ((nread = getline(&line, &len, args->stream)) != -1) {
++i;
args->width = (int) nread;
args->maze = realloc(args->maze, sizeof(char *) * i);
args->maze[i] = line;
line = NULL;
len = 0;
}