Загрузить текстовый файл в 2D массив, затем сравнить с литералом - PullRequest
0 голосов
/ 29 июня 2019

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

ниже приведен код сравнения, я пробую разные вещи безуспешно

char** list;

load(list);

if(strcmp(list[0], "aasdf"))
{
    printf("win\n");
}

вышеприведенные segfaults на strcmp

функция загрузки

void load(char **list)
{
int MAX_NUM_LINES = 1000;

FILE *fp;

list = malloc(MAX_NUM_LINES*sizeof(char*));
fp = fopen("list", "r");

line_ct = 0;
char line[256];
while ( fgets(line, 256, fp) != NULL )
{
   int len = strlen(line);
   list[line_ct] = malloc(len * sizeof(char));
   strcpy(list[line_ct], line);
   line_ct++;

   if(line_ct == MAX_NUM_LINES)
   {
        break;
   }
}

fclose(fp);
}

любые идеи о том, почему segfault?

также я пробую перед тем, как strcmp

printf("Line: %s\n", *list[0]);

это segfault до

1 Ответ

1 голос
/ 29 июня 2019

когда вы возвращаетесь из load var list не установлен, поэтому, когда вы делаете

 if(strcmp(list[0], "aasdf"))

у вас неопределенное поведение при использовании list (обычно сбой)


Первое решение - использовать выходную переменную

вам нужно изменить

load(list);

от

load(&list);

и вам нужно изменить тип списка и разыменовать его в load , так:

void load(char ***list)
{
  *list = malloc(MAX_NUM_LINES*sizeof(char*));
  ...
  (*list)[line_ct] = malloc((len + 1) * sizeof(char));
  strcpy((*list)[line_ct], line);

Я также добавил 1 к len , чтобы иметь место для завершающего нулевого символа.

(правка) Использование *** не очень распространено, как предлагает @ user3629249 в замечании, которое вы можете посмотреть на Тройные указатели в C: это вопрос стиля? внимательно читая ответы.


Второе решение - вернуть выделенный массив:

char** list = load();

с

char ** load()
{
   char **list;
   ...
   return list;

также добавляя 1 к len при выделении каждой строки


Кроме того, если вы читаете более MAX_NUM_LINES строк, вы снова записываете из массива неопределенное поведение, и вызывающий load не знает, сколько строк вы прочитали.

Чтобы избежать этого, вы можете сначала инициализировать список с помощью malloc(0), а затем использовать realloc , чтобы увеличить размер списка каждый раз, когда вы читаете строку, что позволяет выделить правильный размер. Чтобы указать размер для вызывающей стороны, вы можете использовать дополнительный выходной var или выделить еще одну запись, чтобы поместить NULL в последнюю запись (все зависит от того, как вы используете массив чтения в коде, вызывающем load )

...