указатель указателя на char в c, сбой присваивания - PullRequest
0 голосов
/ 12 июля 2020

У меня есть указатель указателя для сохранения строк, которые я читал из файла;

char **lines;

И я назначаю их так:

line_no=0;
*(&lines[line_no++])=buffer;

Но почему происходит сбой?

Согласно моему logi c, & должен давать указатель нулевого индекса, затем *var=value, как сохранить значение в указателе. Не так ли?

Вот мой текущий полный код:


void read_file(char const *name,int len)
{
    int line_no=0;
    FILE* file;
    int buffer_length = 1024;
    char buffer[buffer_length];

    file = fopen(name, "r");

    while(fgets(buffer, buffer_length, file)) {
        printf("---%s", buffer);
        ++line_no;
        if(line_no==0)
        {
            lines = (char**)malloc(sizeof(*lines) * line_no);
        }
        else
        {
            lines = (char**)realloc(lines,sizeof(*lines) * line_no);
        }
        lines[line_no-1] = (char*)malloc(sizeof(buffer));
        lines[line_no-1]=buffer;
        printf("-------%s--------\n", *lines[line_no-1]);
    }

    fclose(file);
}

Ответы [ 2 ]

2 голосов
/ 12 июля 2020

У вас просто указатель, не более того. Вам нужно выделить память, используя malloc().

На самом деле вам нужно сначала выделить память для указателей, а затем выделить память для строк.

N строк, каждая M символов:

char** lines = malloc(sizeof(*lines) * N);
for (int i = 0; i < N; ++i) {
    lines[i] = malloc(sizeof(*(lines[i])) * M);
}

Вы также берете адрес и сразу же разыменовываете его - что-то вроде *(&foo) практически не имеет смысла.

Для обновленного кода

О, в этом коде столько неправильного ...

  1. Вам нужно включить stdlib.h, чтобы использовать malloc()
  2. lines не объявлено. char** lines отсутствует до того, как l oop
  3. if в l oop проверяет, соответствует ли line_no 0. Если да, то выделяется lines. Проблема в том, что переменная line_no равна 0 - sizeof(*lines) умноженное на 0, все равно равно нулю. Память не выделяется.
  4. Но! В начале l oop стоит ++line_no, поэтому line_no никогда не равно 0, поэтому malloc() вообще не вызывается.
  5. lines[line_no-1] = buffer; - он не копируется из buffer - lines[line_no-1], он просто назначает указатели. Чтобы скопировать строки в C, вам нужно использовать strcpy()
  6. fgets() добавляет новый символ строки в конец буфера - вы, вероятно, захотите удалить его: buffer[strcspn(buffer, "\n")] = '\0';
  7. Аргумент len никогда не используется.
  8. char buffer[buffer_length]; - не используйте VLA
  9. Лучше увеличить line_no в конце l oop вместо постоянного вычисления line_no-1
  10. В C результат приведения malloc() не является обязательным
  11. Нет проверки, если открытие файла не удалось
  12. Вы не освобождаете память

Учитывая все это, я быстро «поправил» его до такого состояния:

void read_file(char const* name)
{
    FILE* file = fopen(name, "r");
    if (file == NULL) {
        return;
    }

    int buffer_length = 1024;
    char buffer[1024];

    char** lines = malloc(0);

    int line_no = 0;
    while (fgets(buffer, buffer_length, file)) {
        buffer[strcspn(buffer, "\n")] = '\0';
        printf("---%s\n", buffer);
        lines = realloc(lines, sizeof (*lines) * (line_no+1));
        lines[line_no] = malloc(sizeof (*lines[line_no]) * buffer_length);
        strcpy(lines[line_no], buffer);
        printf("-------%s--------\n", lines[line_no]);
        ++line_no;
    }

    fclose(file);

    for (int i = 0; i < line_no; ++i) {
        free(lines[i]);
    }
    free(lines);
}
0 голосов
/ 12 июля 2020

Хорошо, у вас здесь пара ошибок:

  1. массив строк не объявлен

  2. Ваше распределение неверно

  3. Я не понимаю эту строку, бессмысленно выделять что-то умножая на ноль

    if (line_no == 0) {

    lines = (char **) mallo c (sizeof (* lines) * line_no);

    }

  4. Не следует выделять массив только одним элементом и постоянно перераспределять его . Это плохая практика, требует много времени и может привести к некоторым более серьезным проблемам позже.

  5. Я рекомендую вам проверить это Можно ли использовать результат mallo c ? для mallo c приведения.

Вы можете написать что-то вроде этого:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void read_file(char const *name)
{
    int line_no = 0, arr_size = 10;
    int buffer_length = 1024;
    char buffer[buffer_length];
    char **lines;
    
    FILE* file;
    
    lines = malloc(sizeof(char*) * 10);
    
    file = fopen(name, "r");

    while(fgets(buffer, buffer_length, file)) {
        buffer[strlen(buffer)-1] = '\0';
        printf("---%s", buffer);
        ++line_no;
        
        if(line_no == arr_size)
        {
            arr_size += 10;
            
            lines = realloc(lines, sizeof(char*) * arr_size);
        }
        
        lines[line_no-1] = malloc(sizeof(buffer));
        lines[line_no-1] = buffer;
        printf("-------%s--------\n", lines[line_no-1]);
    }

    fclose(file);
}

PS, fgets() также принимает '\n' char в конце, чтобы предотвратить это, вы можете написать следующую строку: buffer[strlen(buffer)-1] = '\0';

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...