Читаем Linux программирование в примерах полностью

/* для целей отладки */

struct flagtab {

 int val;          /* Целое значение флага */

 const char *name; /* Строковое имя */

};

Эту структуру можно использовать для представления любого набора флагов с соответствующими строковыми значениями. Каждая отдельная группа флагов имеет соответствующую функцию, которая возвращает печатное представление флагов, которые установлены в настоящее время. Из eval.c:

/* 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С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных