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

ЖАНРЫ

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

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

Шрифт:

Как и для стандартной

getopt
, если первым символом
optstring
является '
:
', GNU
getopt
различает «неверную опцию» и «отсутствующий аргумент опции», возвращая соответственно '
?
' или '
:
'. Символ '
:
' в
optstring
может быть вторым символом, если первым символом является '
+
' или '
'.

Наконец, если за символом опции в

optstring
следуют два двоеточия, эта опция может иметь необязательный аргумент. (Быстро повторите это три раза!) Такой аргумент считается присутствующим, если он находится в том же элементе
argv
,
что и сама опция, и отсутствующим в противном случае. В случае отсутствия аргумента GNU
getopt
возвращает символ опции, а в
optarg
записывает NULL. Например, пусть имеем:

while ((с = getopt(argc, argv, "ab::")) != -1)

...

для

– bYANKEES
, возвращаемое значение будет '
b
', a
optarg
указывает на «
YANKEES
», тогда как для
– b
или '
– b YANKEES
' возвращаемое значение будет все то же '
b
', но в
optarg
будет помещен NULL. В последнем случае «
YANKEES
» представляет отдельный аргумент командной строки.

2.3.3. Длинные опции

Функция

getopt_long
осуществляет разбор длинных опций в описанном ранее виде. Дополнительная процедура
getopt_long_only
работает идентичным образом, но она используется для программ, в которых все опции являются длинными и начинаются с единичного символа '
'. В остальных случаях обе функции работают точно так же, как более простая функция GNU
getopt
. (Для краткости, везде, где мы говорим «
getopt_long
», можно было бы сказать «
getopt_long
и
getopt_long_only
».) Вот объявления функций из справки getopt(3) GNU/Linux:

#include <getopt.h> /* GLIBC */

int getopt_long(int argc, char *const argv[],

 const char *optstring,

 const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char *const argv[],

 const char *optstring,

 const struct option *longopts, int *longindex);

Первые три аргумента те же, что и в

getopt
. Следующая опция является указателем на массив
struct option
, который мы назовем таблицей длинных опций и который вскоре опишем. Параметр
longindex
, если он не установлен в NULL, указывает на переменную, в которую помешается индекс обнаруженной длинной опции в
longopts
. Это полезно, например, при диагностике ошибок.

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 ((с =

Поделиться с друзьями: