17 if (i < argc-1)
18 putchar(' ');
19 }
20 if (nflg == 0)
21 putchar('\n');
22 exit(0);
23 }
Всего 23 строки! Здесь есть два интересных момента. Во-первых, уменьшение argc
argv
(строки 12 и 13) являются обычным способом пропуска начальных аргументов. Во-вторых, проверка наличия -n
(строка 10) является упрощением. -no-newline-at-the-end
также работает. (Откомпилируйте и проверьте это!)Ручной разбор опций обычен для кода V7, поскольку функция getopt()
Наконец, здесь и в других местах по всей книге, мы видим использование ключевого слова register. Одно время это ключевое слово давало компилятору подсказку, что данная переменная должна по возможности размещаться в регистре процессора. Теперь это ключевое слово устарело; современные компиляторы все основывают размещение переменных в регистрах на анализе исходного кода, игнорируя ключевое слово register
2.3. Разбор опций: getopt()
getopt_long()
Примерно в 1980-х группа поддержки Unix для System III в AT&T заметила, что каждая программа Unix использовала для разбора аргументов свои собственные методики. Чтобы облегчить работу пользователей и программистов, они разработали большинство из перечисленных ранее соглашений. (Хотя изложение в System III справки для
Группа поддержки Unix разработала также функцию getopt()
getopt_long()
предоставляет совместимую с getopt()
версию, а также упрощает разбор длинных опций в описанной ранее форме.2.3.1. Опции с одним символом
Функция getopt()
#include
int getopt(int argc, char *const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
Аргументы argc
argv
обычно передаются непосредственно от main()
. optstring
является строкой символов опций. Если за какой-либо буквой в строке следует двоеточие, эта опция ожидает наличия аргумента.Для использования getopt()
while
до тех пор, пока она не вернет -1
. Каждый раз, обнаружив действительный символ опции, функция возвращает этот символ. Если опция принимает аргумент, указатель на него помещается в переменную optarg
. Рассмотрим программу, принимающую опцию -а
без аргумента и опцию -b
с аргументом:int ос; /* символ опции */
char *b_opt_arg;
while ((ос = getopt(argc, argv, "ab:")) != -1) {
switch (oc) {
case 'a':
/* обработка -а, установить соответствующий флаг */
break;
case 'b':
/* обработка -b, получить значение аргумента из optarg */
b_opt_arg = optarg;
break;
case ':':
... /* обработка ошибок, см. текст */
case '?':
default:
... /* обработка ошибок, см. текст */
}
}
В ходе работы getopt()
char *optarg
Аргумент для опции, если она принимает аргумент.
int optind
Текущий индекс в argv
loop
завершается, оставшиеся операнды находятся с argv[optind]
по argv[argc-1]
. (Помните, что 'argv [argc] ==NULL
'.)int opterr
Когда эта переменная не равна нулю (значение по умолчанию), getopt()
int optopt
Когда находится недействительный символ опции, getopt()
?
', либо ':
' (см ниже), a optopt
содержит обнаруженный недействительный символ.Люди есть люди, программы неизбежно будут иногда вызываться неправильно либо с недействительной опцией, либо с отсутствующим аргументом опции. Обычно в таких случаях getopt()
?
'. Однако, вы можете изменить такое поведение двумя способами.Во-первых, записав 0 в opterr
getopt()
, можно заставить getopt()
не предпринимать при обнаружении проблем никаких действий.