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() не предпринимать при обнаружении проблем никаких действий.