Язык программирования C

       

Командная строка аргументов


Системные средства, на которые опирается реализация языка "с", позволяют передавать командную строку аргументов или параметров начинающей выполняться программе. Когда функция main вызывается к исполнению, она вызывается с двумя аргументами. Первый аргумент (условно называемый argc) указывает число аргументов в командной строке, с которыми происходит обращение к программе; второй аргумент (argv) является указателем на массив символьных строк, содержащих эти аргументы, по одному в строке. Работа с такими строками - это обычное использование многоуровневых указателей.

Самую простую иллюстрацию этой возможности и необходимых при этом описаний дает программа echo, которая просто печатает в одну строку аргументы командной строки, разделяя их пробелами. Таким образом, если дана команда

echo hello, world

то выходом будет

hello, world

по соглашению argv[0] является именем, по которому вызывается программа, так что argc по меньшей мере равен 1. В приведенном выше примере argc равен 3, а argv[0], argv[1] и argv[2] равны соответственно "echo", "hello," и "world". Первым фактическим аргументом является argv[1], а последним - argv[argc-1]. Если argc равен 1, то за именем программы не следует никакой командной строки аргументов. Все это показано в echo:

main(argc, argv) /* echo arguments; 1st version */ int argc; char *argv[]; { int i;

for (i = 1; i < argc; i++) printf("%s%c", argv[i], (i<argc-1) ? ' ' : '\n'); }

Поскольку argv является указателем на массив указателей, то существует несколько способов написания этой программы, использующих работу с указателем, а не с индексацией массива. Мы продемонстрируем два варианта.

main(argc, argv) /* echo arguments; 2nd version */ int argc; char *argv[]; { while (--argc > 0) printf("%s%c",*++argv, (argc > 1) ? ' ' : '\n'); }

Так как argv является указателем на начало массива строк- аргументов, то, увеличив его на 1 (++argv), мы вынуждаем его указывать на подлинный аргумент argv[1], а не на argv[0]. Каждое последующее увеличение передвигает его на следующий аргумент; при этом *argv становится указателем на этот аргумент. Одновременно величина argc уменьшается; когда она обратится в нуль, все аргументы будут уже напечатаны.

Другой вариант:


main(argc, argv) /* echo arguments; 3rd version */ int argc; char *argv[]; { while (--argc > 0) printf((argc > 1) ? "%s" : "%s\n", *++argv); }

Эта версия показывает, что аргумент формата функции printf может быть выражением, точно так же, как и любой другой. Такое использование встречается не очень часто, но его все же стоит запомнить.

Как второй пример, давайте внесем некоторые усовершенствования в программу отыскания заданной комбинации символов из лекции №4. Если вы помните, мы поместили искомую комбинацию глубоко внутрь программы, что очевидно является совершенно неудовлетворительным. Следуя утилите grep системы UNIX, давайте изменим программу так, чтобы эта комбинация указывалась в качестве первого аргумента строки.



#define maxline 1000

main(argc, argv) /* find pattern from first argument */ int argc; char *argv[]; { char line[maxline];

if (argc != 2) printf ("usage: find pattern\n"); else while (getline(line, maxline) > 0) if (index(line, argv[1] >= 0) printf("%s", line); }

Теперь может быть развита основная модель, иллюстрирующая дальнейшее использование указателей. Предположим, что нам надо предусмотреть два необязательных аргумента. Один утверждает: "напечатать все строки за исключением тех, которые содержат данную комбинацию", второй гласит: "перед каждой выводимой строкой должен печататься ее номер".

Общепринятым соглашением в "с"-программах является то, что аргумент, начинающийся со знака минус, вводит необязательный признак или параметр. Если мы, для того, чтобы сообщить об инверсии, выберем -x, а для указания о нумерации нужных строк выберем -n("номер"), то команда

find -x -n the

при входных данных

now is the time for all good men to come to the aid of their party.

Должна выдать

2:for all good men

Нужно, чтобы необязательные аргументы могли располагаться в произвольном порядке, и чтобы остальная часть программы не зависела от количества фактически присутствующих аргументов. В частности, вызов функции index не должен содержать ссылку на argv[2], когда присутствует один необязательный аргумент, и на argv[1], когда его нет. Более того, для пользователей удобно, чтобы необязательные аргументы можно было объединить в виде:



find -nx the

вот сама программа:

#define maxline 1000

main(argc, argv) /* find pattern from first argument */ int argc; char *argv[]; { char line[maxline], *s; long lineno = 0; int except = 0, number = 0; while (--argc > 0 && (*++argv)[0] == '-') for (s = argv[0]+1; *s != '\0'; s++) switch (*s) { case 'x': except = 1; break;

case 'n': number = 1; break; default: printf("find: illegal option %c\n", *s); argc = 0; break; } if (argc != 1) printf("usage: find -x -n pattern\n"); else while (getlinе(line, maxline) > 0) { lineno++; if ((index(line, *argv) >= 0) != except) \ if (number) printf("%ld: ", lineno); printf("%s", line); } } }

аргумент argv увеличивается перед каждым необязательным аргументом, в то время как аргумент argc уменьшается. Если нет ошибок, то в конце цикла величина argc должна равняться 1, а *argv должно указывать на заданную комбинацию. Обратите внимание на то, что *++argv является указателем аргументной строки; (*++argv)[0] - ее первый символ. Круглые скобки здесь необходимы, потому что без них выражение бы приняло совершенно отличный (и неправильный) вид *++(argv[0]). Другой правильной формой была бы **++argv.

Упражнение 5-7

Напишите программу add, вычисляющую обратное польское выражение из командной строки. Например,

add 2 3 4 + * вычисляет 2*(3+4).

Упражнение 5-8

Модифицируйте программы entab и detab (указанные в качестве упражнений в лекции №1) так, чтобы они получали список табуляционных остановок в качестве аргументов. Если аргументы отсутствуют, используйте стандартную установку табуляций.

Упражнение 5-9

Расширьте entab и detab таким образом, чтобы они воспринимали сокращенную нотацию

entab m +n

означающую табуляционные остановки через каждые n столбцов, начиная со столбца m. Выберите удобное (для пользователя) поведение функции по умолчанию.

Упражнение 5-10

Напишите программу для функции tail, печатающей последние n строк из своего файла ввода. Пусть по умолчанию n равно 10, но это число может быть изменено с помощью необязательного аргумента, так что


Содержание раздела