Linux программирование в примерах | страница 38



равен NULL, >val обычно содержит некоторую символьную константу. Если длинная опция соответствует короткой, эта символьная константа должна быть той же самой, которая появляется в аргументе >optstring для этой опции. (Все это станет вскоре ясно, когда мы рассмотрим несколько примеров.)


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

МакроподстановкаЧисловое значениеСмысл
>no_argument0Опция не принимает аргумент
>required_argument1Опции требуется аргумент
>optional_argument2Аргумент опции является необязательным

У каждой длинной опции есть один такой элемент с соответствующими заполненными значениями. В последнем элементе массива все значения должны быть равны нулю. Нет необходимости сортировать массив: >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 из первого примера.