Linux программирование в примерах
7. Программы могут разрешить длинным опциям начинаться с одной черточки (Это типично для многих программ X Window.)
Многое из этого станет яснее, когда позже в этой главе мы рассмотрим
.getopt_long()GNU Coding Standards уделяет значительное место перечислению всех длинных и коротких опций, используемых программами GNU. Если вы пишете программу, использующую длинные опции, посмотрите, нет ли уже использующихся имен опций, которые имело бы смысл использовать и вам.
2.2. Базовая обработка командной строки
Программа на С получает доступ к своим аргументам командной строки через параметры
иargc. Параметрargvявляется целым, указывающим число имеющихся аргументов, включая имя команды. Есть два обычных способа определенияargc, отличающихся способом объявленияmain():argcint main(int argc, char *argv[]) int main(int argc, char **argv){ {... ...} }Практически между двумя этими объявлениями нет разницы, хотя первое концептуально более понятно:
является массивом указателей на символы. А второе определение технически более корректно, это то, что мы используем. На рис. 2.2 изображена эта ситуация.argcРис. 2.2. Память для
argcПо соглашению,
является именем программы. (Детали см. в разделе 9.1.4.3. «Имена программ иargv[0]».) Последующие элементы являются аргументами командной строки. Последним элементом массиваargv[0]является указательargv.NULLуказывает, сколько имеется аргументов; поскольку в С индексы отсчитываются с нуля, выражение 'argc' всегда верно. Из-за этого, особенно в коде для Unix, вы увидите различные способы проверки окончания списка аргументов, такие, как цикл с проверкой, что счетчик превысилargv[argc] == NULL, или 'argc', или 'argv[i] == 0' и т.д. Они все эквивалентны.*argv != NULL2.2.1. Программа
V7echoВозможно, простейшим примером обработки командной строки является программа V7
печатающая свои аргументы в стандартный вывод, разделяя их пробелами и завершая символом конца строки. Если первым аргументом являетсяecho,, завершающий символ новой строки опускается. (Это используется для приглашений из сценариев оболочки.) Вот код [28]:-n1 #include <stdio.h>23 main(argc, argv) /*int main(int argc, char **argv)*/4 int argc;5 char *argv[];6 {7 register int i, nflg;89 nflg = 0;10 if (argc > 1 && argv[1][0] == && argv[1][1] == 'n') {11 nflg++;12 argc--;13 argv++;14 }15 for (i=1; i<argc; 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(строки 12 и 13) являются обычным способом пропуска начальных аргументов. Во-вторых, проверка наличияargv(строка 10) является упрощением.-nтакже работает. (Откомпилируйте и проверьте это!)-no-newline-at-the-endРучной разбор опций обычен для кода V7, поскольку функция
не была еще придумана.getopt()Наконец, здесь и в других местах по всей книге, мы видим использование ключевого слова register. Одно время это ключевое слово давало компилятору подсказку, что данная переменная должна по возможности размещаться в регистре процессора. Теперь это ключевое слово устарело; современные компиляторы все основывают размещение переменных в регистрах на анализе исходного кода, игнорируя ключевое слово
. Мы решили оставить использующий это слово код, как есть, но вы должны знать, что оно больше не имеет реального применения. [29]register2.3. Разбор опций:
иgetopt()getopt_long()Примерно в 1980-х группа поддержки Unix для System III в AT&T заметила, что каждая программа Unix использовала для разбора аргументов свои собственные методики. Чтобы облегчить работу пользователей и программистов, они разработали большинство из перечисленных ранее соглашений. (Хотя изложение в System III справки для intro(1) значительно менее формально, чем в стандарте POSIX.)
Группа поддержки Unix разработала также функцию
, вместе с несколькими внешними переменными, чтобы упростить написание кода, придерживающегося стандартных соглашений. Функция GNUgetopt()предоставляет совместимую сgetopt_long()версию, а также упрощает разбор длинных опций в описанной ранее форме.getopt()2.3.1. Опции с одним символом
Функция
объявлена следующим образом:getopt()#include <unistd.h> /*POSIX*/int getopt(int argc, char *const argv[], const char *optstring);extern char *optarg;extern int optind, opterr, optopt;Аргументы
иargcобычно передаются непосредственно отargv.main()является строкой символов опций. Если за какой-либо буквой в строке следует двоеточие, эта опция ожидает наличия аргумента.optstring
