2016-11-20 4 views
2

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

Во-первых, здесь моя первая нединамическая код:

char line[256]; 
file = fopen(inputFileName, "r"); 
// Here, of course I checked file is opened or not. 
while (fgets(line, sizeof(line), file)) { 
    // do some operations 
} 
// Closing operations 

Это работает для меня, когда я читал файлы. Но здесь строка должна быть равна или меньше 255 символов. Итак, я хочу прочитать, например, строку длиной 300 символов из файла.

Я попытался следующий код:

size_t maxl = 256; 
//char line[256]; 
char *line = malloc(maxl * sizeof(char)); 
if(!line){ 
    printf("Memory not allocated!!\n"); 
    return -2; 
} 
file = fopen(inputFileName, "r"); 

while (fgets(line, sizeof(line), file)) { 

    while(line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'){ 
     char *tmp = realloc (line, 2 * maxl); 
     //fgets(line, sizeof(line), file); 
     if (tmp) { 
      line = tmp; 
      maxl *= 2; 
     } 
     else{ 
      printf("Not enough memory for this line!!\n"); 
      return -3; 
     } 
    } 
    // do some operations 
} 

Я пытался реализовать ответы на этот вопрос на самом деле: Reading a line from file in C, dynamically

Но это всегда ввести «Недостаточно памяти» часть кода. Итак, что я делаю неправильно?

Благодарим вас за ответы и рекомендации.


Редактировать: Код обновлен в соответствии с вашими последними комментариями.


Редактировать 2: Код всегда читается теми же 3 символами из файла.

Представьте, что файл как:

abcdabcdabcd... 

Переменной line всегда «а» даже после операции повторного распределения.

+1

Ваш цикл while будет только завершен, если вы прочитаете новый текст из файла внутри него, но вы этого не сделаете. – Ryan

+0

Возможный дубликат [Как найти «sizeof» (указатель, указывающий на массив)?] (Http://stackoverflow.com/questions/492384/how-to-find-the-sizeofa-pointer-pointingtoto -an-array) –

+0

'sizeof (char *)' Неверно. Вы выделяете массив 'char *'? № –

ответ

1

Вот некоторые исправления, которые нужно сделать: (! Только предложение)

  • Изменение char *tmp = realloc (line, 2 * maxl); в char *tmp = realloc (line, 2 * maxl * sizeof(char);.
  • После перераспределения памяти вам нужно искать в файле, чтобы прочитать полную строку. Например, fseek(file,0,SEEK_SET); будет искать начало файла inputFileName.
  • sizeof(line) всегда будет постоянным значением, поскольку вы вычисляете размер указателя на символ, а не длину строки. Итак, измените while (fgets(line, sizeof(line), file)) { на while (fgets(line, maxl, file)) {.
  • Переместите прокомментированную строку //fgets(line, sizeof(line), file); внутри блока if (tmp), потому что вы захотите снова прочитать строку из файла после перераспределения.
  • Выражение line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r' не соответствует логике. Вы можете ввести петлю только в том случае, если последний символ line не является ни '\n', ни '\r'. Поэтому вы должны использовать && вместо ||.

Вот измененный код:

size_t maxl = 256; 
//char line[256]; 
char *line = malloc(maxl * sizeof(char)); 
if(!line){ 
    printf("Memory not allocated!!\n"); 
    return -2; 
} 
file = fopen(inputFileName, "r"); 

while (fgets(line, maxl, file)) { 

    while(line[strlen(line) - 1] != '\n' && line[strlen(line) - 1] != '\r'){ 
     char *tmp = realloc (line, 2 * maxl * sizeof(char)); 

     fseek(file,0,SEEK_SET);   //or wherever you want to seek to 
     if (tmp) { 
      line = tmp; 
      maxl *= 2; 
      fgets(line, maxl, file); 
     } 
     else{ 
      printf("Not enough memory for this line!!\n"); 
      return -3; 
     } 
    } 
    printf("%s\n",line);  //just to check 
} 

Проблемы в коде были:

  • Вы читали лишь несколько символов из файла, потому что вы читаете sizeof(line) количество символов только и не maxl количество символов.
  • Возможно, вы захотите отыскать несколько байтов, чтобы снова прочитать всю строку, но это зависит от вас.
  • Снова перечитайте строку из файла после перераспределения, только если перераспределение выполнено успешно (if(tmp)).

Теперь, почему это Not enough memory.. было печать?

Это произошло потому, что ваш цикл был запущен несколько раз и перераспределена размером памяти (maxl значения) увеличивается, как 256, 512, 1024, 2048, ..., 65536, ...

Когда этот размер будет достаточно большой, чтобы компилятор отказался от перераспределения, у вас была напечатана эта строка ошибок. Если хотите, попробуйте отладить версию кода или распечатайте значение maxl на каждой итерации внутреннего цикла while.

+1

Эй, skrtbhtngr. Спасибо за ваше объяснение, это очень понятно и информативно. Но после исправления этих строк, я снова получаю сообщение «Недостаточно памяти» – pilkington

+1

Я опробовал модифицированный код, он работает нормально. Можете ли вы проверить значение 'maxl' на каждой итерации? – skrtbhtngr

+0

Начинается с 256 и увеличивается, как 512,1024, ... пока в вашем ответе нет памяти, как вы упомянули в своем ответе – pilkington

Смежные вопросы