getline into char ** возвращает только последнюю строку - PullRequest
1 голос
/ 20 марта 2020

Я пытаюсь сохранить строку из getline (..., line, ...) в массив char **. Но когда я перебираю массив для печати строк, он печатает только последнюю строку. Я думаю, что в человеке есть что-то, что я пропустил.

входной файл

стандартный вывод

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;
}

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Ваш текущий код повторно использует буфер line для чтения, а getline перераспределяет его только в том случае, если его размер слишком мал, чтобы поместиться в следующую строку для чтения (и, в этом случае, free s в предыдущем буфере !). Как следствие, последовательные строки будут храниться в том же буфере, по тому же адресу, который назначен maze[i].

. Чтобы избежать этого, вы можете сбросить line и len перед каждым вызовом на getline:

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!

Обратите внимание, что нам нужно free(line) после последнего вызова getline, даже если этот вызов не удался.

Кроме того, я бы опротестовал это злоупотребление for l oop, хотя это, безусловно, вопрос стиля: поскольку вы на самом деле не выполняете итерацию по той же переменной, которую объявляете и обновляете, я бы разделил чтение файла и цикл по 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;
}
0 голосов
/ 20 марта 2020

Вам также необходимо выделить память для каждой строки. Затем вам нужно скопировать строку.

    args->maze = realloc(args->maze, sizeof(char *) * (i + 1));
    args -> maze[i] = malloc(strlen(line) + 1);
    strcpy(args->maze[i], line);
...