2014-02-08 3 views
0

У меня возникают проблемы при чтении файла в массив строк в C. Вот мой код:Чтение файла в массив строк C

char mylittleBuffer[BUFFER_SIZE];  //BUFFER_SIZE is 4096 
    char *a; 
    char **c; 

    fprintf(stderr, "LOL\n"); 
    for(int i = 0; (a = fgets(mylittleBuffer, sizeof(mylittleBuffer), myInput)) != NULL; i++) 
    { 
     fprintf(stderr, "a: %s\n", a); 
     c[i] = malloc(sizeof(a)); 
     if (c[i] == NULL) 
     printf("c[i] is NULL"); 
     c[i] = strdup(a); 
     //  fprintf(stderr, "mylittleBuffer: %s\n", mylittleBuffer);                                     
     fprintf(stderr, "c[i] %s\n", c[i]); 
    } 

Это кажется, что только одна строка файла считывается так как программа будет распечатывать a один раз. Что случилось с другими линиями? Я не получаю сообщений об ошибках ...

  1. В чем проблема?
  2. Как исправить эту проблему?
+0

извините, я просто редактируется. Это то, что я написал достаточно? – CodeKingPlusPlus

+0

Вы читаете файл, а не записываете файл. Вы не инициализировали 'c' указывать на что-либо (вам нужно выделить место для него), поэтому, когда вы используете' c [i] ', вы используете неопределенные ячейки памяти, вызывая неопределенное поведение. Это чудо, что оно не падает. Вам нужно будет выделить место для массива указателей символов. –

+0

ага! Благодаря! Я изменил 'char ** c' на' char * c [NUM_LINES] ', поэтому, я думаю, мне нужно будет подсчитать количество строк в файле. Любые предложения для этого? – CodeKingPlusPlus

ответ

3

Вы не инициализирован c, чтобы указать на что-либо (вам нужно выделить место для него), поэтому при использовании c[i], вы используете места неопределенные памяти, вызывая неопределенное поведение. Это чудо, что оно не падает. Вам нужно будет выделить место для массива указателей символов.

enum { INITIAL_SIZE = 2 };   // Set to a larger number when not debugging 
char mylittleBuffer[BUFFER_SIZE];  //BUFFER_SIZE is 4096 
char *a; 
size_t c_size = INITIAL_SIZE; 
char **c = malloc(c_size * sizeof(*c)); 

if (c == NULL) 
{ 
    fprintf(stderr, "out of memory (for c)\n"); 
    return; 
} 

fprintf(stderr, "LOL\n"); 
for (int i = 0; (a = fgets(mylittleBuffer, sizeof(mylittleBuffer), myInput)) != NULL; i++) 
{ 
    fprintf(stderr, "a: %s\n", a); 
    if (i >= c_size) 
    { 
     // Reallocate c to get more space 
     size_t new_size = c_size * 2; 
     void *new_space = realloc(c, new_size * sizeof(*c)); 
     if (new_space == 0) 
     { 
      // Release the already allocated c[i] 
      // Release c 
      fprintf(stderr, "Out of memory (for more c)\n"); 
      return; 
     } 
     c_size = new_size; 
     c = new_space; 
    } 
    // c[i] = malloc(sizeof(a)); // Leak - you use strdup() too 
    c[i] = strdup(a); 
    if (c[i] == NULL) 
    { 
     fprintf(stderr, "c[i] is NULL\n"); 
     // Release the already allocated c[i] strings 
     // Release c 
     return; 
    } 
    //  fprintf(stderr, "mylittleBuffer: %s\n", mylittleBuffer); 
    fprintf(stderr, "c[%d] <<%s>>\n", i, c[i]); // <<>> show where the string ends 
} 

Я сохранил ваш код в основном. Если бы он был моим, a не существовало бы, mylittleBuffer было бы всего buffer, и это то, что я использовал бы в теле цикла вместо a. Вероятно, я бы использовал более длинное имя для c, хотя обычно я использую более короткие имена, чем другие люди.

Обратите внимание, что код с использованием realloc() позволяет избежать потери указателя на ранее выделенную память, если вызов завершился с ошибкой. Если он назначен непосредственно на c, вы потеряете единственную ссылку на предыдущее выделение памяти - возможно, большую утечку.

Учитывая, что код очистки требуется в два раза, я бы написать функцию, чтобы сделать это:

static void release_memory(size_t num, char **strings) 
{ 
    for (size_t i = 0; i < num; i++) 
     free(strings[i]); 
    free(strings); 
} 

Это будет называться:

release_memory(i, c); 
Смежные вопросы