динамическая память и фэгеты - PullRequest
1 голос
/ 23 ноября 2010

Привет всем пользователям stackoverflow.Я пытаюсь создать простой (в качестве упражнения) код, который будет читать из файла и сохранять слова из файла в динамически распределенном массиве.Я думаю, что я неправильно поступаю.Кто-нибудь видит, что я не так делаю?

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

#define ARRSIZE 10

int main(){
    char * myArray = malloc(ARRSIZE*sizeof(char*));
    FILE * p1File;
    char mystring1 [100];
    char word [100];
    int j = 0;
    p1File = fopen ("my1file.txt","r");
    if (p1File == NULL) perror ("Error opening file");
    else{
        while(fgets(mystring1, 100, p1File)){
            int nuRead = sscanf(mystring1, "%s", word);\
            printf("lepo ani magia\n\n");
            if (nuRead > 0){
                strncpy (*myArray[j], mystring1, 100);
                //*myArray[j] = mystring1;
            }
            j += 1;
        } 
    }
}

///////////////////////////////////////////////////////////

my text file is

this
will
probably
work
but
I
am

Ответы [ 4 ]

3 голосов
/ 23 ноября 2010

Для этой задачи я бы сначала определил структуру данных, содержащую слова, например:

struct wordlist {
    char **words; /* the actual words */
    size_t size; /* the number of words in the list */
    size_t capacity; /* the number of words that would fit in the list */
};
typedef struct wordlist wordlist;

Тогда я бы определил некоторые функции для работы с ними. Это должно сделать код в main коротким и читабельным. Функции:

void *
malloc_or_fail(size_t size)
{
  void *result = malloc(size);
  if (result == NULL) {
    perror("malloc");
    exit(EXIT_FAILURE);
  }
  return result;
}

/* Creates a newly allocated copy of the given string. Later changes
 * to the given string will not have any effect on the returned string.
 */
char *
str_new(const char *str) {
  size_t len = strlen(str);
  char *result = malloc_or_fail(len + 1);
  memcpy(result, str, len + 1);
  return result;
}

/* Adds a copy of the given string to the word list. Later changes
 * to the given string have no effect on the word in the word list.
 */
void
wordlist_add(wordlist *wl, const char *word)
{
  if (wl->size == wl->capacity) {
    /* TODO: resize the wordlist */
  }
  assert(wl->size < wl->capacity);
  wl->words[wl->size++] = str_new(word);
}

/* Creates a new word list that can hold 10 words before it will be
 * resized for the first time.
 */
wordlist *
wordlist_new(void)
{
  wordlist *result = malloc_or_fail(sizeof wordlist);
  result->size = 0;
  result->capacity = 10;
  result->words = malloc_or_fail(result->capacity * sizeof result->words[0]);
  return result;
}

Используя эти функции, не составит труда выполнить исходное задание.

1 голос
/ 23 ноября 2010

Вы не выделяете место для ваших строк, просто массив строк.myArray[j] это просто неинициализированный указатель.Вместо этого, выделите место для каждой строки в myArray следующим образом:

char *myArray[ARRSIZE]; // No reason for this to be dynamic.
// ...
if (nuRead > 0)
{
    myArray[j] = malloc((strnlen(mystring, 100) + 1) * sizeof(char));
    strncpy (myArray[j], mystring1, nuRead + 1);
}

Как указал user411313, sscanf не возвращает количество совпадающих символов, но совпадает количество входных элементов.Используйте strnlen (или strlen, если у вас нет strnlen), чтобы получить размер строки (и не забудьте добавить 1 для нулевого терминатора).

0 голосов
/ 23 ноября 2010

Если вам нужно обработать до 10 строк текста, я бы сделал это примерно так:

char *myArray[ARRSIZE];
...
if (nuRead > 0) {
  myArray[j++] = strdup(mystring1);
}
...

Что происходит, так это то, что этот код выделяется и копируется за один раз (используя strdup вместо malloc , за которым следует strcpy ).

0 голосов
/ 23 ноября 2010
char * myArray = malloc(ARRSIZE*sizeof(char*));

Вы выделили место для хранения десяти строковых указателей. Но вы не выделили места для копирования символов в постоянные строки.

Если вы хотите настроить это хранилище в начале, вы можете сделать

#define MAX_STR_SIZE 100

char * myArray = malloc(ARRSIZE*sizeof(char*));
if (!myArray) exit(1);
for (j=0; j<ARRSIZE; j++) {
    myArray[j] = malloc(MAX_STR_SIZE);
    if (!myArray[j]) exit(1);
}

Или, возможно, лучше, вы можете выделить каждую строку по мере необходимости. Вместо strncpy используйте strdup (что похоже на malloc, а затем strcpy):

    myArray[j] = strdup(mystring1);
...