Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
ЗАМЕЧАНИЕ. Первоначально при написании своего приложения делайте это простым способом: непосредственно используйте
malloc()free()3.2.1.8. Пример: чтение строк произвольной длины
Поскольку это, в конце концов, Программирование на Linux в примерах, настало время для примера из реальной жизни. Следующий код является функцией
readline()ftp://ftp.gnu.org/gnu/make/make-3.80.tar.gzread.cСледуя принципу «никаких произвольных ограничений», строки в
MakefileВторичной задачей является распоряжение продлением строк. Как и в С, строки, заканчивающиеся обратным слешем, логически продолжаются со следующей строки. Используется стратегия поддержания буфера. В нем хранится столько строк, сколько помещается в буфер, причем указатели отслеживают начало буфера, текущую строку и следующую строку. Вот структура:
struct ebuffer { char *buffer; /* Начало текущей строки в буфере. */ char *bufnext; /* Начало следующей строки в буфере. */ char *bufstart; /* Начало всего буфера. */ unsigned int size; /* Размер буфера для malloc. */ FILE *fp; /* Файл или NULL, если это внутренний буфер. */ struct floc floc; /* Информация о файле в fp (если он есть). */};Поле
sizefpFILEФункция возвращает число строк в буфере. (Номера строк здесь даны относительно начала функции, а не исходного файла.)
1 static long2 readline(ebuf) /* static long readline(struct ebuffer *ebuf) */3 struct ebuffer *ebuf;4 {5 char *p;6 char *end;7 char *start;8 long nlines = 0;910 /* Использование строковых буферов и буферов потоков достаточно11 различается, чтобы использовать разные функции. */1213 if (!ebuf->fp)14 return readstring(ebuf);1516 /* При чтении из файла для каждой новой строки мы всегда17 начинаем с начала буфера. */1819 p = start = ebuf->bufstart;20 end = p + ebuf->size;21 *p = ' ';Для начала заметим, что GNU Make написан на С K&R для максимальной переносимости. В исходной части объявляются переменные, и если ввод осуществляется из строки (как в случае расширения макроса), код вызывает другую функцию,
readstring()!ebuf->fpebuf->fp==NULLСтроки 19-21 инициализируют указатели и вводят байт NUL, который является символом завершения строки С в конце буфера. Затем функция входит в цикл (строки 23–95), который продолжается до завершения всего ввода.
23 while (fgets(p, end - р, ebuf->fp) != 0)24 {25 char *p2;26 unsigned long len;27 int backslash;2829 len = strlen(p);30 if (len == 0)31 {32 /* Это случается лишь тогда, когда первый символ строки ' '.33 Это довольно безнадежный случай, но (верите или нет) ляп Афины34 бьет снова! (xmkmf помещает NUL в свои makefile.)35 Здесь на самом деле нечего делать; мы создаем новую строку, чтобы36 следующая строка не была частью данной строки. */37 error (&ebuf->floc,38 _("warning: NUL character seen; rest of line ignored"));39 p[0] = 'n';40 len = l;41 }Функция
fgets()FILE*