Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

78 /* Это была комбинация обратный слеш/новая строка. Если есть

79 место, прочесть еще одну строку. */

80 if (end - p >= 80)

81 continue;

82

83 /* В конце буфера нужно больше места, поэтому выделить еще.

84 Позаботиться о сохранении текущего смещения в p. */

85 more_buffer:

86 {

87 unsigned long off = p - start;

88 ebuf->size *= 2;

89 start = ebuf->buffer=ebuf->bufstart=(char*)xrealloc(start,

90 ebuf->size);

91 p = start + off;

92 end = start + ebuf->size;

93 *p = '\0';

94 }

95 }

До

сих пор мы имели дело с механизмом получения в буфер по крайней мере одной полной строки. Следующий участок обрабатывает случай строки с продолжением. Хотя он должен гарантировать, что конечный символ обратного слеша не является частью нескольких обратных слешей в конце строки. Код проверяет, является ли общее число таких символов четным или нечетным путем простого переключения переменной
backslash
из 0 в 1 и обратно. (Строки 64–70.)

Если число четное, условие '

!backshlash
' (строка 72) будет истинным. В этом случае конечный символ конца строки замещается байтом NUL, и код выходит из цикла.

С другой стороны, если число нечетно, строка содержит четное число пар обратных слешей (представляющих символы \\, как в С), и конечную комбинацию символов обратного слеша и конца строки. [43] В этом случае, если в буфере остались по крайней мере 80 свободных байтов, программа продолжает чтение в цикле следующей строки (строки 78–81). (Использование магического числа 80 не очень здорово; было бы лучше определить и использовать макроподстановку.)

43

Этот код несет с собой аромат практического опыта, не удивительно было узнать, что более ранние версии просто проверяли наличие обратного слеша перед символом конца строки, пока кто-то не пожаловался, что он не работает, когда в конце строки есть несколько обратных слешей — Примеч. автора.

По достижении строки 83 программе нужно больше места в буфере. Именно здесь вступает в игру динамическое управление памятью. Обратите внимание на комментарий относительно сохранения значения

p
(строки 83-84); мы обсуждали это ранее в терминах повторной инициализации указателей для динамической памяти. Значение end также устанавливается повторно. Строка 89 изменяет размер памяти.

Обратите внимание, что здесь вызывается функция

xrealloc
. Многие программы GNU используют вместо
malloc
и
realloc
функции-оболочки, которые автоматически выводят сообщение об ошибке и завершают программу, когда стандартные процедуры возвращают
NULL
. Такая функция-оболочка может выглядеть таким образом:

extern const char *myname; /* установлено в main */

void *xrealloc(void *ptr, size_t amount) {

 void *p = realloc(ptr, amount);

 if (p == NULL) {

fprintf(stderr, "%s: out of memory!\n", myname);

exit(1);

 }

 return p;

}

Таким образом, если функция

xrealloc
возвращается, она гарантированно возвращает действительный указатель. (Эта стратегия соответствует принципу «проверки каждого вызова на ошибки», избегая в то же время беспорядка в коде, который происходит при таких проверках с непосредственным использованием стандартных процедур.) Вдобавок, это позволяет эффективно использовать конструкцию '
ptr = xrealloc(ptr, new_size)
', против которой мы предостерегали ранее.

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

97 if (ferror(ebuf->fp))

98 pfatal_with_name(ebuf->floc.filenm);

99

100 /* Если обнаружено несколько строк, возвратить их число.

101 Если не несколько, но _что-то_ нашли, значит, прочитана

102 последняя строка файла без завершающего символа конца

103 строки; вернуть 1. Если ничего не прочитано, это EOF;

104 возвратить -1. */

105 return nlines ? nlines : p == ebuf->bufstart ?
– 1 : 1;

106 }

В заключение, функция

readline
проверяет ошибки ввода/вывода, а затем возвращает описательное значение. Функция
pfatal_with_name
(строка 98) не возвращается. [44]

44

Эта функция завершает выполнение программы — Примеч. науч. ред.

3.2.1.9. Только GLIBC: чтение целых строк:

getline
и
getdelim

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

#define _GNU_SOURCE 1 /* GLIBC */

#include <stdio.h>

#include <sys/types.h> /* для ssize_t */

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);

Определение константы

_GNU_SOURCE
вводит объявления функций
getline
и
getdelim
. В противном случае они неявно объявлены как возвращающие
int
. Для объявления возвращаемого типа
ssize_t
нужен файл
<sys/types.h>
. (
ssize_t
является «знаковым
size_t
». Он предназначен для такого же использования, что и
size_t
, но в местах, где может понадобиться использование также и отрицательных значений.)

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

getline
читает до символа конца строки, a
getdelim
использует в качестве разделителя символ, предоставленный пользователем. Общие аргументы следующие:

char **lineptr

Указатель на

char*
указатель для адреса динамически выделенного буфера. Чтобы
getline
сделала всю работу, он должен быть инициализирован
NULL
. В противном случае, он должен указывать на область памяти, выделенную с помощью
malloc
.

Поделиться:
Популярные книги

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд

Путь Шедара

Кораблев Родион
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Путь Шедара

Идущий в тени 5

Амврелий Марк
5. Идущий в тени
Фантастика:
фэнтези
рпг
5.50
рейтинг книги
Идущий в тени 5

Кровь Василиска

Тайниковский
1. Кровь Василиска
Фантастика:
фэнтези
попаданцы
аниме
4.25
рейтинг книги
Кровь Василиска

Вернуть невесту. Ловушка для попаданки

Ардова Алиса
1. Вернуть невесту
Любовные романы:
любовно-фантастические романы
8.49
рейтинг книги
Вернуть невесту. Ловушка для попаданки

Не грози Дубровскому!

Панарин Антон
1. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому!

Мастер Разума III

Кронос Александр
3. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.25
рейтинг книги
Мастер Разума III

Мимик нового Мира 8

Северный Лис
7. Мимик!
Фантастика:
юмористическая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Мимик нового Мира 8

На границе империй. Том 9. Часть 5

INDIGO
18. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 5

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Дядя самых честных правил 7

Горбов Александр Михайлович
7. Дядя самых честных правил
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Дядя самых честных правил 7

С Д. Том 16

Клеванский Кирилл Сергеевич
16. Сердце дракона
Фантастика:
боевая фантастика
6.94
рейтинг книги
С Д. Том 16

Авиатор: назад в СССР 14

Дорин Михаил
14. Покоряя небо
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 14

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота