Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

/* flags2str --- делает значения флагов удобочитаемыми */

const char *flags2str(int flagval) {

 static const struct flagtab values[] = {

{ MALLOC, "MALLOC" },

{ TEMP, "TEMP" },

{ PERM, "PERM" },

{ STRING, "STRING" },

{ STRCUR, "STRCUR" },

{ NUMCUR, "NUMCUR" },

{ NUMBER, "NUMBER" },

{ MAYBE_NUM, "MAYBE_NUM" },

{ ARRAYMAXED, "ARRAYMAXED" },

{ FUNC, "FUNC" },

{ FIELD, "FIELD" },

{ INTLSTR, "INTLSTR" },

{ 0, NULL },

 };

 return genflags2str(flagval, values);

}

flags2str
определяет массив сопоставлений флагов со строками. По соглашению, значение флага 0 означает конец массива. Код вызывает для осуществления работы
genflags2str
(«общий флаг в строку»).
getflags2str
является процедурой общего назначения, которая преобразует значение флага в строку. Из
eval.c
:

1 /* genflags2str --- общая процедура для преобразования значения флага в строковое представление */

2

3 const char *

4 genflags2str(int flagval, const struct flagtab *tab)

5 {

6 static char buffer(BUFSIZ];

7 char *sp;

8 int i, space_left, space_needed;

9

10 sp = buffer;

11 space_left = BUFSIZ;

12 for (i = 0; tab[i].name != NULL; i++) {

13 if ((flagval & tab[i].val) != 0) {

14 /*

15 * обратите внимание на уловку, нам нужны 1 или 0, чтобы

16 * определить, нужен ли нам символ '|'.

17 */

18 space_needed = (strlen(tab[i].name) + (sp != buffer));

19 if (space_left < space_needed)

20 fatal(_("buffer overflow in genflags2str"));

21

22 if (sp >= buffer) {

23 *sp++ = '|';

24 space_left--;

25 }

26 strcpy(sp, tab[i].name);

27 /* обратите внимание на расположение! */

28 space_left -= strlen(sp);

29 sp += strlen(sp);

30 }

31 }

32

33 return buffer;

34 }

(Номера строк приведены относительно начала функции, а не файла.) Как и в предыдущей версии, идея заключалась в заполнении статического буфера строковыми значениями, такими, как "

MALLOC | PERM | STRING | MAYBE_NUM
", и возвращении адреса этого буфера. Мы вскоре обсудим причины использования статического буфера; сначала давайте исследуем код.

Указатель

sp
отслеживает положение следующего пустого слота в буфере, тогда как
space_left
отслеживает количество оставшегося места; это уберегает нас от переполнения буфера.

Основную часть функции составляет цикл (строка 12), проходящий через массив значений флагов. Когда флаг найден (строка 13), код вычисляет, сколько места требуется строке (строка 18) и проверяет, осталось ли столько места (строки 19–20).

Тест '

sp ! = buffer
' для первого значения флага завершается неудачей, возвращая 0. Для последующих флагов тест дает значение 1. Это говорит нам, что между значениями должен быть вставлен разделительный символ '
|
'. Добавляя результат (1 или 0) к длине строки, мы получаем правильное значение
space_needed
. Тот же тест с той же целью проводится в строке 22 для проверки строк 23 и 24, которые вставляют символ '
|
'.

В заключение строки 26–29 копируют значение строки, выверяют количество оставшегося места и обновляют указатель

sp
. Строка 33 возвращает адрес буфера, который содержит печатное представление строки.

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

  • Читать дальше
  • 1
  • ...
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • ...

Private-Bookers - русскоязычная библиотека для чтения онлайн. Здесь удобно открывать книги с телефона и ПК, возвращаться к сохраненной странице и держать любимые произведения под рукой. Материалы добавляются пользователями; если считаете, что ваши права нарушены, воспользуйтесь формой обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • help@private-bookers.win

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