Linux программирование в примерах - страница 20

стр.

Как мы видели в разделе 1.4.2 «Поведение программ», программам GNU рекомендуется использовать длинные опции в форме >--help, >--verbose и т.д. Такие опции, поскольку они начинаются с '>--', не конфликтуют с соглашениями POSIX. Их также легче запомнить, и они предоставляют возможность последовательности среди всех утилит GNU. (Например, >--help является везде одним и тем же, в отличие от >-h для «help», >-i для «information» и т.д.) Длинные опции GNU имеют свои собственные соглашения, реализованные в функции >getopt_long():

1. У программ, реализующих инструменты POSIX, каждая короткая опция (один символ) должна иметь также свой вариант в виде длинной опции.

2. Дополнительные специфические для GNU опции не нуждаются в соответствующей короткой опции, но мы рекомендуем это сделать.

3. Длинную опцию можно сократить до кратчайшей строки, которая остается уникальной. Например, если есть две опции >--verbose и >--verbatim, самыми короткими сокращениями будут >--verbo и >--verba.

4. Аргументы опции отделяются от длинных опций либо разделителем, либо символом >=. Например, >--sourcefile=/some/file или >--sourcefile /some/file.

5. Опции и аргументы могут быть заинтересованы в операндах командной строки, >getopt_long() переставляет аргументы таким образом, что сначала обрабатываются все опции, а затем все операнды доступны последовательно. (Такое поведение можно запретить.)

6. Аргументы опций могут быть необязательными. Для таких опций считается, что аргумент присутствует, если он находится в одной строке с опцией. Это работает лишь для коротких опций. Например, если -х такая опция и дана строка '>foo -хYANKEES -y', аргументом >-х является '>YANKEES'. Для '>foo -х -y' у >-х нет аргументов.

7. Программы могут разрешить длинным опциям начинаться с одной черточки (Это типично для многих программ X Window.)

Многое из этого станет яснее, когда позже в этой главе мы рассмотрим >getopt_long().

GNU Coding Standards уделяет значительное место перечислению всех длинных и коротких опций, используемых программами GNU. Если вы пишете программу, использующую длинные опции, посмотрите, нет ли уже использующихся имен опций, которые имело бы смысл использовать и вам.

2.2. Базовая обработка командной строки

Программа на С получает доступ к своим аргументам командной строки через параметры >argc и >argv. Параметр >argc является целым, указывающим число имеющихся аргументов, включая имя команды. Есть два обычных способа определения >main(), отличающихся способом объявления >argc:

>int main(int argc, char *argv[])  int main(int argc, char **argv)

>{                                 {

>...                                ...

>}                                 }

Практически между двумя этими объявлениями нет разницы, хотя первое концептуально более понятно: >argc является массивом указателей на символы. А второе определение технически более корректно, это то, что мы используем. На рис. 2.2 изображена эта ситуация.

Рис. 2.2. Память для >argc

По соглашению, >argv[0] является именем программы. (Детали см. в разделе 9.1.4.3. «Имена программ и >argv[0]».) Последующие элементы являются аргументами командной строки. Последним элементом массива >argv является указатель >NULL.

>argc указывает, сколько имеется аргументов; поскольку в С индексы отсчитываются с нуля, выражение '>argv[argc] == NULL' всегда верно. Из-за этого, особенно в коде для Unix, вы увидите различные способы проверки окончания списка аргументов, такие, как цикл с проверкой, что счетчик превысил >argc, или '>argv[i] == 0', или '>*argv != NULL' и т.д. Они все эквивалентны.

2.2.1. Программа >echo V7

Возможно, простейшим примером обработки командной строки является программа V7 >echo, печатающая свои аргументы в стандартный вывод, разделяя их пробелами и завершая символом конца строки. Если первым аргументом является >-n, завершающий символ новой строки опускается. (Это используется для приглашений из сценариев оболочки.) Вот код[28]:

>1  #include

>2

>3  main(argc, argv) /*int main(int argc, char **argv)*/

>4  int argc;

>5  char *argv[];

>6  {

>7   register int i, nflg;

>8

>9   nflg = 0;