Как открыть файл любой длины в C? - PullRequest
2 голосов
/ 13 сентября 2011

Как школьное задание мне поручено написать программу, которая открывает любой текстовый файл и выполняет ряд операций над текстом.Текст должен быть загружен с использованием связанного списка, то есть массива структур, содержащих указатель на символ и указатель на следующую структуру.Одна строка на структуру.

Но у меня проблемы с загрузкой файла.Кажется, что память, необходимая для загрузки текста в память, должна быть выделена до того, как я прочту текст.Следовательно, я должен открыть файл несколько раз.Один раз посчитать количество строк, затем дважды на строку;один раз, чтобы посчитать символы в строке, а затем один раз, чтобы прочитать их.Кажется абсурдом открывать файл сотни раз просто для чтения его в память.

Очевидно, что есть лучшие способы сделать это, я просто не знаю их: -)

Примеры

  • Может ли точка, из которой fgetc извлекает символ, перемещаться без повторного открытия файла?
  • Можетколичество строк или символов в файле, которое нужно проверить перед его «открытием»?
  • Можно ли как-то прочитать строку или строку из файла и сохранить их в памяти без выделения фиксированнойколичество байтов?
  • и т. д.

Ответы [ 3 ]

3 голосов
/ 13 сентября 2011

Нет необходимости открывать файл более одного раза или проходить через него более одного раза.

Посмотрите на функцию POSIX getline(). Он читает строки в выделенном пространстве. Вы можете использовать его для чтения строк, а затем скопировать результаты для связанного списка.

Нет необходимости в связанном списке, чтобы знать, сколько строк впереди; это преимущество списков.

Итак, код может быть выполнен за один проход. Даже если вы не можете использовать getline(), вы можете использовать fgets() и следить за тем, читает ли он каждый раз до конца строки, а если нет, вы можете выделить (и перераспределить) пространство для хранения строки по мере необходимости ( malloc(), realloc() и в конечном итоге free() из <stdlib.h>).

Ваши конкретные вопросы в значительной степени несущественны, если вы используете какой-либо подход, который я предлагаю, но:

  • Использование fseek() (и в крайнем случае rewind()) переместит указатель чтения (для fgetc() и всех других функций), если «файл» не поддерживает поиск (например, канал, предоставленный как стандартный ввод).

  • Символы могут быть определены с помощью stat() или fstat() или их вариантов. Строки не могут быть определены, кроме как путем чтения файла.

  • Поскольку размер файла может варьироваться от нуля до гигабайта, разумного способа распределения фиксированного размера не существует. Вы в значительной степени вынуждены динамически распределять память с помощью malloc() et al. (За кадром getline() использует malloc() и realloc().)

1 голос
/ 13 сентября 2011

Вы не можете посчитать количество строк в файле, фактически не пройдя его.Вы можете получить общий размер файла, но это не то, что здесь задумано.Идея использования связанного списка строк заключается в том, что вы работаете с файлом по одной строке за раз.Вам не нужно ничего читать заранее.Пока вы не прочитали весь файл, прочитайте строку, добавьте ее к собственному узлу в конце связанного списка и перейдите к следующей строке.

0 голосов
/ 13 сентября 2011

Относительно вашего первого вопроса: вы можете изменить позицию в файле, с которого вы читаете, с помощью функции fseek ().

Есть несколько способов сделать это.Например, вы можете иметь буфер фиксированного размера, заполнить его байтами из файла, скопировать строки из буфера в список, снова заполнить буфер и т. Д.

...