Почти всем сложным программам для работы требуется входные параметры (опции, аргументы - называйте как хотите), от значения которых строится последовательность работы алгоритма заложенного в программе или используются различные источники данных.
Вы наверняка знаете, что передача параметров в программу на C/C++ осуществляется через массив функции main(). Так повелось, что он называется argv (от arguments values - значения аргументов), но в принципе его можно назвать и по другому. Количество этих параметров передается через переменную argc (от arguments counter - счетчик аргументов).
Программа, для работы которой требуется набор входных параметров задается при помощи специального определения функции main():
int main(int argc, char *argv[]{}; int main(int argc, char **argv){};
Давайте напишем маленькую программку, которая выводит значения переданных параметров:
// программа test.c #include <stdio.h>int main(int argc, char *argv[]){ int i=0; for (i=0;i<argc;i++){ printf("Argument %d: %s\n",i,argv[i]); };};
В качестве первого параметра программе всегда передается ее имя и таким образом программа может узнать свое название, т.е. имя файла, в котором она содержится.
Но моя цель не говорить о том, как передаются параметры, а как с ними работать. Для начала надо вспомнить, что в системе Linux существует два вида параметров: короткие и длинные. Короткие параметры начинаются с одного дефиса и имеют длину в один символ, их просто и быстро набирать в командной строке. Длинные параметры начинаются с двух дефисов и могут иметь длинное имя, которое целесообразно использовать в скриптах (чтобы потом можно было вспомнить, что и как происходит). Кроме этого любой параметр может иметь значение, а может и не иметь. Приведу для примера несколько параметров:
-h - короткий параметр--help - длинный параметр -s 10 - параметры со значениями--size 10--size=10
Так вот, существует несколько специальных функций предназначенных для разбора списка переданных параметров:
· int getopt(...) - Обрабатывает короткие параметры
· int getopt_long(...) - Обрабатывает короткие и длинные параметры
· int getopt_long_only(...) - Обрабатывает параметры только как длинные
Давайте разберемся с работой первой функции - getopt(...). Ее определение выглядит следующим образом:
#include <unistd.h> int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg;extern int optind, opterr, optopt;
Эта функция последовательно перебирает переданные параметры в программу. Для работы в функцию передается количество параметров argc, массив параметров argv[] и специальная строка optstring, в которой перечисляются названия коротких параметров и признаки того, что параметры должны иметь значение. Например, если программа должна воспринимать три параметра a, b, F , то такая строка бы выглядела как "abF". Если параметр должен иметь значение, то после буквы параметра ставится двоеточие, например параметр F и d имеют значения, а параметры e, a и b не имеют, тогда эта строка могла бы выглядеть как "eF:ad:b". Если параметр может иметь (т.е. может и не иметь) значение, то тогда ставится два знака двоеточия, например "a::" (это специальное расширение GNU). Если optstring содержит "W:", то тогда параметр -W opt переданный в программу, будет восприниматься как длинный параметр --opt. Это связано с тем, что параметр W зарезервирован в POSIX.2 для расширения возможностей.
Для перебора параметров функцию getopt() надо вызывать в цикле. В качестве результата возвращется буква названия параметра, если же параметры кончились, то функция возвращает -1. Индекс текущего параметра хранится в optind, а значение параметра помещается в optarg (указатель просто указывает на элемент массива argv[]). Если функция находит параметр не перечисленный в списке, то выводится сообщение об ошибке в stderr и код ошибки сохраняется в opterr, при этом в качестве значения возврящается "?". Вывод ошибки можно запретить, если установить opterr в 0.
#include <stdio.h>#include <unistd.h> int main(int argc, char *argv[]){ int rez=0; // opterr=0; while ( (rez = getopt(argc,argv,"ab:C::d")) != -1){ switch (rez){ case 'a': printf("found argument \"a\".\n"); break; case 'b': printf("found argument \"b = %s\".\n",optarg); break; case 'C': printf("found argument \"C = %s\".\n",optarg); break; case 'd': printf("found argument \"d\"\n"); break; case '?': printf("Error found !\n");break; }; }; };
Попробуем скомпилировать данную программку и запустить:
Давайте посмотрим, как функция getopt вылавливает ошибки. Попробуем задать параметр, которого нет в списке:
dron:~# ./test -h -a./test: invalid option -- hError found !found argument "a".
Как я и говорил, функция вывела сообщение об ошибке в stderr. Давайте выключим вывод сообщений, для этого надо где-то в программе перед вызовом функции вставить opterr=0;. Компилируем и запускаем:
dron:~# ./test -h -aError found !found argument "a".
Теперь, как видите, сообщение больше не выдается, зато как и раньше можно обработать ошибку самому.