Книга: Linux программирование в примерах

2.3.3.1. Таблица длинных опций

2.3.3.1. Таблица длинных опций

Длинные опции описываются с помощью массива структур struct option. Структура struct option определена в <getopt.h>; она выглядит следующим образом:

struct option {
 const char *name;
 int has_arg;
 int *flag;
 int val;
};

Элементы структуры следующие:

const char *name

Это имя опции без предшествующих черточек, например, «help» или «verbose».

int has_arg

Переменная описывает, имеет ли длинная опция аргумент, и если да, какого вида этот аргумент. Значение должно быть одно из представленных в табл. 2.1. Макроподстановки являются некоторыми символическими именами для числовых значений, приведенных в таблице. Хотя числовые значения тоже работают, макроподстановки гораздо легче читать, и вы должны их использовать вместо соответствующих чисел в любом коде, который пишете.

int *flag

Если этот указатель равен NULL, getopt_long() возвращает значение поля val структуры. Если он не равен NULL, переменная, на которую он указывает, заполняется значением val, a getopt_long() возвращает 0. Если flag не равен NULL, но длинная опция отсутствует, указанная переменная не изменяется.

int val

Если длинная опция обнаружена, это возвращаемое значение или значение для загрузки в *flag, если flag не равен NULL. Обычно, если flag не равен NULL, val является значением true/false, вроде 1 или 0. С другой стороны, если flag равен NULL, val обычно содержит некоторую символьную константу. Если длинная опция соответствует короткой, эта символьная константа должна быть той же самой, которая появляется в аргументе optstring для этой опции. (Все это станет вскоре ясно, когда мы рассмотрим несколько примеров.)

Таблица 2.1. Значения для has_arg

Макроподстановка Числовое значение Смысл
no_argument 0 Опция не принимает аргумент
required_argument 1 Опции требуется аргумент
optional_argument 2 Аргумент опции является необязательным

У каждой длинной опции есть один такой элемент с соответствующими заполненными значениями. В последнем элементе массива все значения должны быть равны нулю. Нет необходимости сортировать массив: getopt_long() осуществляет линейный поиск. Однако, сортировка его по длинным именам может упростить его чтение для программиста.

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

while ((с = getopt(argc, argv, ":af:hv")) != -1) {
 switch (с) {
 case 'a':
  do_all = 1;
  break;
 case 'f':
  myfile = optarg;
  break;
 case 'h':
  do_help = 1;
  break;
 case 'v':
  do_verbose = 1;
  break;
 ... /* Здесь обработка ошибок */
 }
}

Когда flag не равен NULL, getopt_long() устанавливает значения переменных за вас. Это снижает число операторов case в предыдущем switch с трех до одного. Вот пример таблицы длинных опций и код для работы с ней:

int do_all, do_help, do_verbose; /* флаговые переменные */
char *my_file;
struct option longopts[] = {
 { "all", no_argument, &do_all, 1 },
 { "file", required_argument, NULL, 'f' },
 { "help", no_argument, &do_help, 1 },
 { "verbose", no_argument, &do_verbose, 1 },
 { 0, 0, 0, 0 }
};
while ((с =
 getopt_long(argc, argv, ":f:", longopts, NULL)) != -1) {
 switch (c) {
 case 'f':
  myfile = optarg;
  break;
 case 0:
  /* getopt_long() устанавливает значение переменной,
     просто продолжить выполнение */
  break;
 ... /* Здесь обработка ошибок */
 }
}

Обратите внимание, что значение, переданное аргументу optstring, не содержит больше 'a', 'h' или 'v'. Это означает, что соответствующие короткие опции неприемлемы. Чтобы разрешить как длинные, так и короткие опции, вам придется восстановить в switch соответствующие case из первого примера.

На практике следует писать свои программы так, чтобы у каждой короткой опции была также соответствующая длинная опция. В этом случае проще всего установить в flag NULL, а в val соответствующий единичный символ.

Оглавление книги


Генерация: 0.070. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз