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 /*POSIX*/


>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() выводит свои собственные сообщения и возвращает символ '>?'. Однако, вы можете изменить такое поведение двумя способами.