Linux программирование в примерах - страница 21
>
>10 if (argc > 1 && argv[1][0] == && argv[1][1] == 'n') {
>11 nflg++;
>12 argc--;
>13 argv++;
>14 }
>15 for (i=1; i
>16 fputs(argv[i], stdout);
>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
. Мы решили оставить использующий это слово код, как есть, но вы должны знать, что оно больше не имеет реального применения.[29]
2.3. Разбор опций: >getopt()
и >getopt_long()
Примерно в 1980-х группа поддержки Unix для System III в AT&T заметила, что каждая программа Unix использовала для разбора аргументов свои собственные методики. Чтобы облегчить работу пользователей и программистов, они разработали большинство из перечисленных ранее соглашений. (Хотя изложение в System III справки для intro(1) значительно менее формально, чем в стандарте POSIX.)
Группа поддержки Unix разработала также функцию >getopt()
, вместе с несколькими внешними переменными, чтобы упростить написание кода, придерживающегося стандартных соглашений. Функция GNU >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()
выводит свои собственные сообщения и возвращает символ '>?
'. Однако, вы можете изменить такое поведение двумя способами.