realloc, для строкового массива в C - PullRequest
0 голосов
/ 05 ноября 2018

Есть ли правильный способ использовать realloc, когда вы хотите добавить слова переменного размера в массив строк? Я получаю ошибку сегментации. Пожалуйста, покажи мне, что не так

// This function puts every word found in a text file, to a String array, **words
char **concordance(char *textfilename, int *nwords){
    FILE * fp;
    char *fileName = strdup(textfilename);
    fp = fopen(fileName, "r");
    if(fp == NULL) {
        perror("fopen");
        exit(1);
    }
    char **words = malloc(sizeof(char));
    // char **words = NULL

    char line[BUFSIZ];
    while(fgets(line, sizeof(line), fp) != NULL){
        char *word = strdup(line);
        word = strtok(word, " ");
        do{
            words = realloc(words, (*nwords+1) * sizeof(char(*)));
            words[*nwords] = word;
        } while((word = strtok(NULL, " ")) != NULL);
    }
    return words;
}


int main(int argc, const char * argv[]) {
    int *nwords = malloc(sizeof(int));
    nwords = 0;
    concordance("test.txt", nwords);
}

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Вы, похоже, неправильно инициализировали nwords в 0. Поскольку вы объявили его как указатель, вы не можете получить к нему доступ напрямую. вместо этого вы должны использовать оператор де-ссылки *.

внести следующие изменения в функцию main

*nwords = 0; вместо nwords = 0;

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

ВНИМАНИЕ:

  1. Лучше не выполнять realloc для одного и того же указателя, это сделает расположение указателя NULL в случае сбоя realloc, что приведет к потере ранее существующих данных. Вместо этого, как предлагает @David, вы можете использовать временную переменную для realloc памяти, а затем проверить, не является ли она NULL, а затем присвоить ее содержимое указателю words.
    //your code
    char *tmp = realloc(words, /* new size*/);
    if(tmp != NULL)
        words = tmp;
    // your code
  1. при использовании realloc вы обычно используете его для выделения блока данных, а не для одного местоположения.
0 голосов
/ 05 ноября 2018

Когда вы инициировали значение nwords, вы перезаписывали его адрес указателя, а не его значение.

Кроме того, как говорит комментатор, строка char **words = malloc(sizeof(char)); неверна. Но вы всегда перераспределяете переменную words, поэтому код по-прежнему работает, как и ожидалось. Чтобы сделать его супер безопасным, вы должны изменить его на char **words = malloc(sizeof(char*));

Я использую строку *nwords = 0; и теперь она работает как положено.

#define BUFSIZ 1000
#include<stdio.h>
// This function puts every word found in a text file, to a String array, **words
char **concordance(char *textfilename, int *nwords){
  FILE * fp;
  char *fileName = strdup(textfilename);
  fp = fopen(fileName, "r");
  if(fp == NULL) {
    perror("fopen");
    exit(1);
  }
  char **words = malloc(sizeof(char));
  // char **words = NULL

  char line[BUFSIZ];
  while(fgets(line, sizeof(line), fp) != NULL){
    char *word = strdup(line);
    word = strtok(word, " ");
    printf("word='%s'\n",word);
    do{
      *nwords=*nwords+1;
      printf("nwords=%d\n",*nwords);
      words = realloc(words, (*nwords+1) * sizeof(char(*)));
      words[*nwords] = word;
    } while((word = strtok(NULL, " ")) != NULL);
  }
  return words;
}


int main(int argc, const char * argv[]) {
  int *nwords = malloc(sizeof(int));
  *nwords = 0;
  concordance("test.txt", nwords);
}
...