Результат, возвращаемый функцией
getopt
, — символ следующей опции, хранящийся в массиве
argv
(если он есть). Вызывайте
getopt
повторно для поочередного получения каждой опции. Функция ведет себя следующим образом.
□ Если опция принимает значение, на него указывает внешняя переменная
optarg
.
□ Функция
getopt
вернет -1, когда не останется опций для обработки. Специальный аргумент
--
заставит
getopt
прекратить перебор опций.
□ Функция
getopt
вернет
?
, если есть нераспознанная опция, которую она сохранит во внешней переменной
optopt
.
□ Если опции требуется значение (например, в нашем примере опции
-f
) и не задана никакая величина,
getopt
обычно возвращает
?
. Если поместить двоеточие как первый символ в строке опций, при отсутствии заданной величины функция
getopt
вернет
:
вместо
?
.
Во внешней переменной
optind
хранится номер следующего обрабатываемого аргумента. Функция
getopt
использует ее, чтобы знать, как далеко она продвинулась. Программы редко нуждаются в установке этой переменной. Когда все аргументы с опциями обработаны, переменная
optind
указывает, где в конце массива argv можно найти оставшиеся аргументы.
Некоторые версии функции
getopt
прекратят выполнение при обнаружении первого аргумента не опции, вернув значение -1 и установив переменную
optind
. Другие, например предлагаемые в ОС Linux, могут обрабатывать опции, где бы они ни встретились в аргументах программы. Учтите, что в данном случае
getopt
фактически перепишет массив
argv
так, что все аргументы не опции будут собраны вместе, начиная с элемента массива
argv[optind]
. В случае версии GNU функции
getopt
ее поведение определяется переменной окружения
POSIXLY_CORRECT
. Если переменная установлена,
getopt
остановится на первом аргументе не опции. Кроме того, некоторые реализации
getopt
выводят сообщения об ошибке для незнакомых опций. Имейте в виду, что в стандарте POSIX написано о том, что если переменная
opterr
не равна нулю, функция
getopt
выведет сообщение об ошибке в
stderr
.
Итак, выполните упражнение 4.2.
Упражнение 4.2. Функция
getopt
В этом упражнении вы используете функцию getopt; назовите новую программу argopt.c.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, ":if:lr")) != -1) {
switch(opt) {
case 'i':
case 'l':
case 'r':
printf("option: %c\n", opt);
break;
case 'f':
printf("filename: %s\n", optarg);
break;
case ':':
printf("option needs a value\n");
break;
case '?':
printf("unknown option: %c\n", optopt);
break;
}
}
for (; optind < argc; optind++)
printf("argument: %s\n", argv[optind]);
exit(0);
}
Теперь, когда вы выполните программу, то увидите, что все аргументы командной строки обрабатываются автоматически:
$ <b>./argopt -i -lr 'hi there' -f fred.с -q</b>
option: i
option: l
option: r
filename: fred.c
unknown option: q
argument: hi there
Как это работает
Программа многократно вызывает функцию
getopt
для обработки аргументов-опций до тех пор, пока не останется ни одного, в этот момент
getopt
вернет -1. Для каждой опции выбирается подходящее действие, включая обработку неизвестных опций и пропущенных значений. Если у вас другая версия
getopt
, то вы получите вывод, слегка отличающийся от показанного, — особенно сообщения об ошибках — но смысл будет понятен.
Когда все опции обработаны, программа просто выводит оставшиеся аргументы, как и раньше, но начиная с номера, хранящегося в переменной
optind
.
getopt_long
Многие приложения Linux принимают более информативные аргументы, чем использованные в предыдущем примере односимвольные опции. Библиотека С проекта GNU содержит версию функции
getopt
, названную
getopt_long
, которая принимает так называемые
длинные аргументы, которые вводятся с помощью двойного дефиса.
Рассмотрим упражнение 4.3.
Упражнение 4.3. Функция
getopt_long
Примените функцию
getopt_long
для создания новой версии примера программы, которая может вызываться с использованием длинных эквивалентов опций, например, следующих:
$ <b>./longopt --initialize --list 'hi there' --file fred.c -q</b>
option: i
option: l
filename: fred.c
./longopt: invalid option --q