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:

之前重置 linelen
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;
}