русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Аргументи командного рядка


Дата додавання: 2014-11-28; переглядів: 1797.


В середовищах, що підтримують C, існує спосіб передачі аргументів командного рядка, або параметрів, програмі, коли вона починає своє виконання. Головну функцію main викликано з двома аргументами. Перший (звично, названий argc, як скорочення від «argument count» — відлік аргументів) вказує на кількість аргументів командного рядка з яким було викликано програму; другий (argv, «argument vector» — вектор аргументів) являється покажчиком на масив символьних ланцюжків, що, власне, містить аргументи — кожний ланцюжок відповідає аргументові. Ми, звичайно, використаємо багаторівневі покажчиків для маніпуляції цих символьних ланцюжків. Найпростішою ілюстрацією є програма echo, яка відлунює аргументи командного рядка на одному рядкові, розділюючи їх пробілами. Тобто, команда

echo hello, world

виводить

hello, world

За домовленістю, argv[0] являється назвою за якою було викликано програму, тож argcдорівнює, щонайменше, 1. Якщо argc дорівнює 1, після назви програми на командному рядкові немає аргументів. У прикладі вище, argc дорівнює 3, тоді як argv[0], argv[1] і argv[2]відповідають "echo", "hello," та "world". Першим необов'язковим аргументом є argv[1], а останнім - argv[argc-1]; на додачу, стандарт вимагає, щоб argv[argc] був нульовим покажчиком.

argv:

+-----+ +-----+ +--------+

| *--|----->| *--|----->| echo\0 |

+-----+ | | +--------+

| | +----------+

| *--|----->| hello,\0 |

| | +----------+

| | +---------+

| *--|----->| world\0 |

| | +---------+

| 0 |

+-----+

Наша перша версія echo розглядає argv як масив символьних покажчиків:

#include <stdio.h>

 

/* відлунює аргументи командного рядка; 1-а версія */

main(int argc, char *argv[])

{

int i;

 

for (i = 1; i < argc; i++)

printf("%s%s", argv[i], (i < argc-1) ? " " : "");

printf("\n");

return 0;

 

}

Оскільки argv є покажчиком на масив, що складається з покажчиків, ми можемо маніпулювати покажчиками, замість індексами масиву. Наступний варіант основується на прирості argv, який є покажчиком на покажчик на char, одночасно здійснюється спад argc:

#include <stdio.h>

 

/* відлунює аргументи командного рядка; 2-а версія */

main(int argc, char *argv[])

{

while (--argc > 0)

printf("%s%s", *++argv, (argc > 1) ? " " : "");

printf("\n");

return 0;

}

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

Альтернативно, ми могли би написати вираз із printf як наступне:

printf((argc > 1) ? "%s " : "%s", *++argv);

Це демонструє, що формат аргументу printf може також бути виразом. Як ще один приклад, давайте покращимо програму знаходження за шаблоном із Розділу 4.1. Якщо ви пам'ятаєте, ми розмістили шаблон пошуку глибоко всередині програми — явно незадовільне розташування. Слідуючи прикладові UNIX-програми grep, давайте поліпшимо нашу, тож шаблон вказуватиметься як перший аргумент на командному рядкові.

#include <stdio.h>

#include <string.h>

#define MAXLINE 1000

 

int getline(char *line, int max);

 

/* find: виводить рядки, що збіглися із шаблоном, вказаним

* у 1-у аргументі */

main(int argc, char *argv[])

{

char line[MAXLINE];

int found = 0;

 

if (argc != 2)

printf("Usage: find pattern\n");

else

while (getline(line, MAXLINE) > 0)

if (strstr(line, argv[1]) != NULL) {

printf("%s", line);

found++;

}

return found;

}

Функція стандартної бібліотеки strstr(s,t) повертає покажчик на перший випадок ланцюжкаt всередині ланцюжка s, або NULL, якщо жодного не знайдено. Її оголошено в <string.h>. Цю модель можна розвинути далі, для подальшої ілюстрації конструкцій з покажчиками. Скажімо, ми хотіли би дозволити два необов'язкових аргументи. Один вказуватиме «вивести всі рядки за винятком тих, що збігаються з шаблоном», а другий — «додати попереду кожного виведеного рядка його порядковий номер».

Загальною умовністю C-програм на UNIX-системах є те, що аргумент, який починається зі знака «мінус» означає необов'язковий прапорець або параметр. Якщо ми оберемо -x (як скорочення для «except») для вказівки протилежного результату, та -n («number»), для нумерації рядків, тоді команда

find -x -n шаблон

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

find -nx шаблон

А ось і сама програма:

#include <stdio.h>

#include <string.h>

#define MAXLINE 1000

 

int getline(char *line, int max);

 

/* find: виводить рядки, що збігаються із шаблоном,

* вказаним у 1-му аргументові */

main(int argc, char *argv[])

{

char line[MAXLINE];

long lineno = 0;

int c, except = 0, number = 0, found = 0;

 

while (--argc > 0 && (*++argv)[0] == '-')

while (c = *++argv[0])

switch (c) {

case 'x':

except = 1;

break;

case 'n':

number = 1;

break;

default:

printf("find: illegal option %c\n", c);

argc = 0;

found = -1;

break;

}

if (argc != 1)

printf("Usage: find -x -n pattern\n");

else

while (getline(line, MAXLINE) > 0) {

lineno++;

if ((strstr(line, *argv) != NULL) != except) {

if (number)

printf("%ld:", lineno);

printf("%s", line);

found++;

}

}

return found;

}

argc зменшено, а argv збільшено перед кожним аргументом. В кінці циклу, якщо не було помилок, argc вкаже, скільки аргуметів залишилось необробленими і argv вказує на перший із них. Таким чином, argc повинен бути 1, а *argv повинен вказувати на шаблон. Зверніть увагу, що *++argv — це покажчик на ланцюжок аргументу, тож (*++argv)[0] — це перший його символ. (Альтернативною чинною формою є **++argv.) Через те, що [] зв'язуються тісніше за* із ++, дужки обов'язкові; без них, вираз розглядався би як *++(argv[0]). Фактично, це те, що ми використали у внутрішньому циклові, де завдання полягає в проходженні через певний ланцюжок аргументу. У внутрішньому циклі, вираз *++argv[0] здійснює приріст покажчикаargv[0]!

Рідко хто використовує вирази з покажчиками складніші за ці; в таких випадках, розбиття їй на два або три кроки буде інтуїтивнішим.

Вправа 5-10. Напишіть програму expr, яка обчислює зворотній польський запис на командному рядкові, де кожний оператор або операнд, це окремий аргумент. Наприклад,

expr 2 3 4 + *

обчислюється як 2 * (3+4).

Вправа 5-11. Змініть програму entab і detab (написані як вправи в Розділі 1), щоб вони могли взяти список табуляторних обмежувачів як аргумент. Використайте стандартні установлення табуляції, якщо аргументи відсутні.

Вправа 5-12. Розширте entab і detab, щоб вони дозволяти скорочення

entab -m +n

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

Вправа 5-13. Напишіть програму tail, яка виводить останні n рядків свого вводу. Без задання,n буде задано як 10, скажімо, але його можна змінити за допомогою аргументу на командному рядку, тож

tail -n

виведе останні n рядків вводу. Програма повинна поводитись розумно, незалежно від того якими непередбачуваними є ввід і значення n. Напишіть цю програму таким чином, щоб вона найкраще використовувала місце зберігання; рядки повинні зберігатися як у програмі сортування з Розділу 5.6, а не в двовимірному масиві сталого розміру.


<== попередня лекція | наступна лекція ==>
Покажчики в порівнянні з багатовимірними масивами | Покажчики на функції


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн