Как загрузить TXT на указатели массива в C - PullRequest
0 голосов
/ 19 марта 2019

Эй, я хотел бы получить помощь по этому вопросу. Я пытаюсь загрузить словарь в моей программе на c, но я получаю ошибку сегмента.Я хотел бы помочь.при отладке с помощью gdb он говорит, что произошел сбой в строке 63, в которой команда говорит: lines[i]=string_coppied

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

const int step=200;
char **loadfile();


int main()
{   
  char **words=loadfile();
  if (words==NULL) printf ("cant build structure");
  for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );
}

char **loadfile()
{
  //We load our text file at the stack
  FILE * fpointer;
  fpointer = fopen ("word.txt" , "r");
  if (fpointer==NULL) printf ("file not loaded \n");
  else printf ("File loaded \n");

  int array_size=step;
  char ** lines=(char **)malloc(array_size*sizeof(char*));
  if (lines=NULL) printf ("cant allocate memory \n");

  char temp[100];
  int i=0;

  while (fgets(temp,100,fpointer))
  {
    //we check if the already allocated memory is full , if so we realloc
    if (i==array_size)
    { 
      array_size +=step;

      char **newlines= (char**)realloc(lines , array_size * sizeof(char*));
      if (newlines==NULL) //check if the memory was allocated
      {
         printf ("Cant reallocate memory , please try again \n ");
         return 0 ;
      }

      lines=newlines;
    }
    //now that we made sure that the memory was allocated we continue by copying the temp //
    temp[strlen(temp)-1]="\0" ;
    int length =strlen(temp);
    char * string_coppied=malloc((length+1) * sizeof(char));
    strcpy(string_coppied ,temp);
    lines[i]=string_coppied;
    i++;
  }
  return lines;

  free(lines);
  fclose(fpointer);
}

1 Ответ

0 голосов
/ 19 марта 2019

GDB говорит, что произошел сбой в строке 63, в которой команда говорит: lines[i]=string_coppied

это потому, что после

char **newlines= (char**)realloc(lines , array_size * sizeof(char*));

вы не можете использовать строки после realloc , потому что если потенциально освобожден realloc , и, очевидно, это то, что произошло, потому что GDB сигнализирует о проблеме


Но у вас больше проблем с вашим кодом

1) компилятор сообщает об ошибке в строке temp[strlen(temp)-1]="\0" ;, потому что temp - это массив char , а не массив char *, вы, безусловно, хотели temp[strlen(temp)-1] = 0 ;

2) в main :

 if (words==NULL) printf ("cant build structure");
 for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );

и иначе отсутствует, если миров равно NULL вы делаете для и (пытаетесь) получить доступ к words[i] снеопределенное поведение

3) в main

for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );

вы получаете доступ к 100 первым записям слов длянапечатать их, не зная его размера / сколько записей у него есть, если в нем меньше 100 записей, у вас другое неопределенное поведение, если его больше, вы не распечатываете все из них

loadfile должно возвращать количество записей, например, черезвыходная переменная char **loadfile(size_t * n), позволяющая вам for (int i=0 ; i<n ; i++) ...

4) в loadfile

 fpointer = fopen ("word.txt" , "r");
 if (fpointer==NULL) printf ("file not loaded \n");
 else printf ("File loaded \n");

, если вы не можете открыть файл файлавы печатаете сообщение и продолжаете выполнение , вам нужно return NULL;

Обратите внимание, что вы также настроены оптимистично, потому что вы уже печатаете File loaded, пока просто открываете файл

5) в загрузочный файл

 char ** lines=(char **)malloc(array_size*sizeof(char*));
 if (lines=NULL) printf ("cant allocate memory \n");

если malloc возвращает NULL вы печатаете сообщение и вы продолжаете выполнение , так что вы можете сделать позже lines[i]=string_coppied;, в то время как строк равно NULL с неопределенным поведением

6) в loadfile

Как я уже сказал

 char **newlines= (char**)realloc(lines , array_size * sizeof(char*));
 if (newlines==NULL) //check if the memory was allocated
 {
     printf ("Cant reallocate memory , please try again \n ");
     return 0 ;
 }

 lines=newlines;

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

  lines= (char**)realloc(lines , array_size * sizeof(char*));
  if (lines==NULL) //check if the memory was allocated
  {
      printf ("Cant reallocate memory , please try again \n ");
      return NULL;
  }

7) в loadfile

при выполнении (я изменил "\ 0" на 0):

temp[strlen(temp)-1]=0;
int length =strlen(temp);

вы вычисляете в 2 раза длину строки, пока вы знаете вторую strlen значения первый минус 1, сделайте

int length = strlen(temp) - 1;

temp[length] = 0;

но есть другая проблема, вы делаете это для удаления новой строки, но

  • последняя строка файла может несодержат новую строку, и в этом случае вы потеряли последний символ.
  • когда строка длиннее 100 символов, она обрезается на несколько, а первые подстроки не содержат символа новой строки, и вы удаляете их последний символ

Чтобы не разрезать строки и не дублировать их, вы можете использовать getline

8) в loadfile

В

return lines;

free(lines);
fclose(fpointer);

последние две строки не могут быть выполнены, поэтому вы не освобождаете строк (но это лучше, потому что вы его возвращаете) и файл не закрыт


Предложение:

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

const int step=200;
char **loadfile(ssize_t * n);

int main()
{   
  ssize_t n;
  char **words=loadfile(&n);

  if (words == NULL)
    puts("error when reading file");
  else {
    for (ssize_t i = 0 ; i < n ; i++) {
      puts(words[i]);
      free(words[i]);
    }
  }
}

char **loadfile(ssize_t * n)
{
  *n = 0;

  //We load our text file at the stack
  FILE * fpointer = fopen ("word.txt" , "r");

  if (fpointer==NULL) {
    printf ("file not loaded \n");
    return NULL;
  }
  puts ("load file");

  int array_size = 0;
  char ** lines = NULL;

  for (;;) {
    char * lineptr = NULL;
    size_t zero = 0;
    ssize_t sz = getline(&lineptr, &zero, fpointer);

    if (sz <= 0) {
      fclose(fpointer);
      return lines;
    }

    if (lineptr[sz - 1] == '\n')
      lineptr[sz - 1] = 0;

    if (*n == array_size)
    { 
      array_size += step;
      lines = realloc(lines , array_size * sizeof(char*));

      if (lines == NULL) //check if the memory was allocated
      {
         printf ("Cant reallocate memory , please try again \n ");
         return NULL;
      }
    }

    lines[*n] = lineptr;
    *n += 1;
  }
}
...