Linux программирование в примерах - страница 23
', 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
>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
определена в >
; она выглядит следующим образом:
>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;