Capitolul 5.11. Argumentele liniei de comanda

Vezi subiectul anterior Vezi subiectul urmator In jos

Capitolul 5.11. Argumentele liniei de comanda

Mesaj  zooky la data de Mier Mar 18, 2009 1:50 pm

Printre facilitatile oferite de C exista modalitatea de a transmite argumentele liniei de comanda sau parametrii unui program atunci cind el incepe sa se execute. Pt inceperea executiei este apelat main prin doua argumente. Primul (numit convetional arge) este numarul argumentelor liniei de comanda prin care a fost apelat programul; al doilea (argv) este un pointer pe un tablou de lanturi de caractere care contine argumentele, unul pentru fiecare lant. Manipularea acestor lanturi de caractere este o utilizare comuna a nivelelor multiple de pointeri.

Cea mai simpla ilustrare a declaratiilor necesare si a celor de mai sus amintite este programul echo, care pune pur si simplu pe o singura linie argumentele liniei de comanda, separate prin blancuri. Astfel, daca este data comanda

echo hello, world

iesirea este

hello, world

Prin conventie, argv[0] este numele prin care se recunoaste programul, asa ca argc este 1. In exemplul de mai sus, argc este 3 si argv[0], argv[1] si argv[2] sint respectiv echo, hello si world. Aceasta este ilustrata in echo:

main(argc, argv) /* arg. echo; prima versiune */
int argc;
char *argv[];
{
int i;
for (i = 1; i < argc; i++)
printf("%s%c", argv[i], (i <argc-1) ? ' ' : '\n');

Arg fiind un pointer pe un tablou de pointeri, exista citeva modalitati de a scrie acest program care implica manipularea pointerului mai curind decit indexarea tabloului. Sa vedem doua variante:

main(argc, argv) /* arg echo; a doua versiune */
int argc;
char *argv[];
{
while (--argc > 0)
printf("%s%c", *++argv, (argc >1) ? ' ' : '\');
}

Daca argv este un pointer pe inceputul tabloului care contine siruri de argumente, a-l incrementa cu i(++argv) face ca el sa pointeze pe argv[1] in loc de argv[0]. Fiecare incrementare succesiva muta pe argv pe urmatorul argument; argv este deci pointerul pe acel argument. Simultan argc este decrementat; atunci cind el devine zero, nu mai exista argumente de imprimat.

main(argc, ragv) /* arg echo; a treia versiune */
int argc;
char *argv[];
{
while (--argc > 0)
printf((argc > 1) ? "%s " : "%s\n", *++argv);
}

Aceasta versiune arata ca formatul argumentului lui printf poate fi o expresie ca oricare alta. Aceasta utilizare nu este foarte frecventa dar este bine sa fie retinuta.

Ca un al doilea exemplu, sa facem unele modificari in configuratia programului de cautare din cap4. In cazul unui apel repetat, configuratia ce serveste de model va fi prelucrata ca atare, de fiecare data de catre program, ceea ce ar duce la un aranjament evident nesatisfacator. Urmind exemplul utilitarului grep-UNIX, sa schimbam programul in asa fel incit configuratia model sa fie specificata prin primul argument al liniei de comanda.

#define MAXLINE 1000
main(argc, argv)
/* cautarea model specificat prin primul 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);
}

Acum poate fi elaborat modelul de baza in asa fel incit sa ilustreze viitoarele constructii realizate cu ajutorul pointerilor.
Sa presupunem ca dorim ca doua argumente sa fie optionale. Unul dintre ele spune "tipareste toate liniile cu exceptia celor care contin modelul "; al doilea cere "fiecare linie tiparita sa fie precedata de numarul curent".

O conventie uzuala pt programele C este legata de argumentul care incepe cu un semn minus si care introduce un flag sau un paramentru optional. Daca se alege -x(pt "exceptie") pt semnalarea inversarii, si ("nr") pt a cere numararea liniilor, atunci comanda

find -x -n the

cu intrarea

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

va produce iesirea

2: for all good men

Argumentele optionale sint admise in orice ordine iar restul programului va fi insensibil la numarul argumentelor care au fost, de fapt, prezente. In particular, apelul la index nu va referi pe argv[2] atunci cind a fost un singur flag si nici la argv[1] daca n-a existat nici un argument flag. In plus, este convenabil pt utilizatori daca argumentele optionale pot fi adunate, ca in

find -nx the

Iata programul

#define MAXLINE 1000
main(argc, argv) /*gasirea configuratiei din primul arg*/
int argc;
char *arv[];
{
char lim[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("fiind: ilegal option%c\n", *s);
argc = 0;
break;
}
if (argc != 1)
printf("usage: find -x -n pattern\n");
else
while (getline(lim, MAXLINE) > 0)
{
lineno++;
if ((index(line,*argv)>=0) !=except)
{
if (number)
printf("%ld: ", lineno);
printf("%s", line);
}
}
}

argv este incrementat inaintea fiecarui argument optional si argc este decrementat. Daca nu exista erori, la sfirsitul buclei argc va fi 1 iar argv va pointa pe configuratia data. De notat ca *++argv este un pointer pe un lant de caractere; (*++argv)[0] este primul caracter. Parantezele sint necesare deoarece fara de expresia ar fi *++(argv[0]), ceea ce este cu totul altceva (si eronat). O forma corecta ar fi.

**++argv

Exercitiul 5.7. Scrieti programul add care evalueaza o expresie poloneza inversata din linia de comanda. De exemplu,

add 2 3 4 + *

calculeaza 2 x (3 + 4)

Exercitiul 5.8. Modificati programele entab si detab (scrise ca exercitii in cap 1) in asa fel incit sa accepte ca argumente o lista de tab-stop-uri utilizati tab-urile normale daca nu exista argumente.

Exercitiul 5.9. Extindeti entab si dentab in asa fel incit sa accepte prescurtarea.

entab m +n

care inseamna tab-stop dupa fiecare n coloane, incepind de la coloana m. Scrieti functia oarecare implicita convenabila pentru utilizator.

Exercitiul 5.10. Scrieti programul tail care tipareste rutinele n linii-input. Presupunem, implicit n=10, dar el poate fi schimbat un argument optional, astfel

tail -n

imprima ultimele n linii. In mod normal, programul va functiona indiferent de intrare (rationala sau nu), sau de valoare lui n. Scrieti progarmul in asa fel incit sa utilizeze in mod optim memoria: liniile vor fi pastrate ca in short, nu intr-un tablou bidimensional de lungime fixata.
avatar
zooky
Moderator
Moderator

Numarul mesajelor : 147
Data de inscriere : 15/03/2009
Varsta : 24
Localizare : Cernatesti City

Vezi profilul utilizatorului http://e-learning.forumhit.ro

Sus In jos

Vezi subiectul anterior Vezi subiectul urmator Sus


 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum