Книга: 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
соответствующий единичный символ.
- 2.3. Разбор опций: getopt() и getopt_long()
- Безопасная работа с внешними таблицами
- Урок 5.6. Работа с таблицами
- Общее понятие об электронных таблицах
- Итоговые вычисления в таблицах
- Практическая работа 52. Итоговые вычисления в таблицах
- Режимы работы с таблицами
- Урок 7.4. Проектирование базы данных. Создание связей между таблицами
- Связи между таблицами
- Практическая работа 56. Создание связей между таблицами
- Таблица 14.1. Примеры имен файлов в результате задания правил форматирования
- 2.3.2. GNU getopt() и порядок опций