CATEGORII DOCUMENTE |
DOCUMENTE SIMILARE |
|
TERMENI importanti pentru acest document |
|
FUNCTIA MAIN . FUNCTIILE EXEC() , SPAWN FUNCTII CU LISTA VARIABILA DE ARGUMENTE
1. Functia Main()
Orice program C trebuie sa aiba o functie main(), care poate fi plasata oriunde in fisierul sursa. Rutina de startup transmite functiei main trei parametrii (argumente): argc, argv si env.
- argc este de tip int si reprezinta numarul argumentelor din liniei de comanda transmise functiei main (in linia de comanda sau direct din compilator Run | Arguments)
- argv este un tablou de pointeri pe siruri de caractere (char *[ ]). argv[0] este numele complet al programului in curs de executie (incepand cu Dos 3.0 ; la versiunile anterioare, argv[0] pointa pe sirul vid); argv[1] pointeaza pe primul sir de caractere tastat in linia de comanda DOS dupa numele programului; argv[argc-1] pointeaza pe ultimul argument transmis functiei main; argv[argc] este NULL.
Aceste argumente (ce sunt siruri de caractere separate de spatii) se pot da in doua moduri:
1. se trec in linia corespunzatoare meniului Run-Arguments
2. se specifica in linia de comanda sub forma: nume_program argum_1 argum_2 argum_n
- env este tot un tablou de pointeri pe siruri de caractere
Fiecare element din tablou contine un sir de forma ENVVAR = value, unde ENVVAR este numele unei variabile de mediul DOS (PATH, PROMPT , etc.) iar value este sirul de caractere asociat. Nu se poate sti in avans (ca la argv) numarul de caractere din tablou; se continua pana un element al tabloului de pointeri env este NULL.
Observatie:
Cu ajutorul comenzii DOS, SET se pot declara un set de variabile de mediu - environment variable accesibile pentru citire din orice program care ruleaza in respectivul mediu (sistem de operare). Sistemul de operare adauga automat parametrii PROMPT si PATH (dupa lansarea acestor comenzi) si COMSPEC (la incarcarea sistemului - indica unitatea si calea utilizata pentru reincarcarea interpretorului de comenzi). Cei trei parametri trebuie declarati exact in ordinea mentionata (chiar daca se pot folosi si alte nume); sunt deci posibile 4 forme ale functiei:
main();
main(int argc);
main(int argc, char *argv[ ]);
main(int argc, char *argv[ ], char *env[ ]);
Argumentul env este accesibil si prin variabila globala environ; argumentele argc si argv sunt accesibile si prin variabilele globale _argc si _argv (deci vor putea fi analizate direct si de catre celelalte functii din program, fara a trebui transmise lor de catre main). Aceste variabile globale sunt definite in dos.h , ca urmare in program trebuie inclus acest fisier header.
Se va rula urmatorul exemplu:
#include <stdio.h>
#include <conio.h>
int main(int argc, char *argv[ ], char *env[ ])
Observatie:
Argumentele pot contine blanc-uri daca sunt incadrate intre ghilimele (acestea vor disparea la prelucrarea argumentelor). Lungimea maxima a argumentelor liniei de comanda transmise functiei main (inclusiv numele programului si spatiile dintre argumente) este de 128 de caractere, limitare data de sistemul de operare DOS).
Argumentele continand caracterele wildcard (*, ?) pot fi expandate in toate numele de fisiere care se potrivesc cu specificatorul. Caracterul inlocuieste un sir de caractere din nume, iar caracterul ? inlocuieste un singur caracter. Pentru aceasta trebuie sa se linkediteze programul impreuna cu WILDARGS.OBJ (se va include in proiect; se gaseste in borlandclib). Argumentul respectiv va fi expandat in argv in toate fisierele corespunzand specificatorului. Marimea maxima a argv depinde de marimea memoriei disponibile. Daca nu se gaseste nici un fisier potrivit, argumentul este trimis neschimbat (nu se expandeaza) Argumentele incadrate intre ghilimele nu sunt expandate. Deci daca se vrea ca tabloul argv sa contina anumite fisiere, sa spunem toate fisierele cu extensia .cpp din directorul de lucru, vom completa in Run-Arguments:
c:labora~1pclucru*.cpp
In plus trebuie facut un proiect ce contine programul principal si fisierul wildargs.obj.
Se va rula proiectul respectiv pentru a observa efectul.
Amintim ca programul principal contine secventa de afisare a tabloului argv:
for (i=0; i<argc; i++)
printf('argv[%d] : %sn',i,argv[i]);
2. Functii pentru variabilele de mediu
char *getenv(const char *nume)
- are prototipul in STDLIB.H;
- nume reprezinta denumirea unei variabile de mediu
- returneaza valoarea variabilei de mediu DOS specificate prin nume, sub forma unui sir de caractere; intoarce NULL daca nu este definita;
Exemplu:
char *s;
s = getenv('PATH');
printf('Calea %sn:', s);
int putenv(const char *nume)
- modifica o variabila de mediu;
- are prototipul in STDLIB.H;
- functia modifica environment-ul numai pentru programul curent; dupa terminare, se va reface vechiul mediu;
- apelarea se face in forma putenv('nume_var=valoare');
- stergerea unei intrari se face prin putenv ('var=');
- sirul de caractere folosit trebuie sa fie static sau global altfel rezultatele sunt imprevizibile.
3. Functii de calcul
Au prototipul in <math.h> de forma:
double nume(double x), unde nume poate fi:
ceil - rotunjire prin adaos
floor - rotunjire prin lipsa
fabs, abs, labs - valori absolute
pow - puterea
exp - e la o putere
log - logaritm natural
log10 - logaritm in baza 10
sqrt - radical
pow10 -10 la o putere
acos, asin, atan - arccosinus, arcsinus, arctangenta
cos, sin - cosinus, sinus
Functiile exec()
Grupul de functii exec() incarca si lanseaza in executie alte programe; toate au prototipurile in PROCESS.H.
int execl(char *path, char *arg0, , NULL);
int execle(char *path, char *arg0, , NULL, char *env[]);
int execlp(char *path, char *arg0, );
int execlpe(char *path, char *arg0, , NULL, char *env[]);
int execv(char *path, char *argv[]);
int execve(char *path, char *argv[], char *env[]);
int execvp(char *path, char *argv[]);
int execvpe(char *path, char *argv[], char *env[]);
Functiile incarca si lanseaza alte programe (denumite child processes- procese fiu), fara posibilitatea de a se mai reveni in programul care le-a apelat (procesele fiu se vor suprapune in memorie peste procesul parinte daca este suficient spatiu de memorie).
- path este numele fisierului corespunzator procesului fiu apelat. Functiile exec() cauta fisierul respectiv dupa algoritmul de cautare DOS standard. Sufixele p, l, v, e diferentiaza functiile dupa cum urmeaza:
p - Functia cauta fisierul in directoarele specificate de variabila de mediu DOS PATH (fara p s-ar cauta numai in directorul curent) daca parametru path nu contine un director explicit;
l - Argumentele de tip pointer (arg0,, argn) sunt transmise separat (atunci cand se cunoaste dinainte numarul argumentelor ce vor fi transmise);
v - Argumentele (argv[0], , argv[n] ) sunt transmise ca un tablou de pointeri atunci cand se transmite un numar variabil de caractere);
e - Argumentul env poate fi transmis procesului fiu, putand modifica mediul pentru acesta (altfel, procesul fiu mosteneste mediul procesului parinte).
Fiecare functie exec() trebuie sa aiba unul din sufixele l sau v, p si e sunt optionale.
Observatii:
- La apelarea cu sufixul l, uzual este ca arg0 sa pointeze pe path iar arg1, , argn sa pointeze pe siruri de caractere reprezentand noua lista de argumente (incheiata cu NULL dupa argn pentru a a marca sfarsitul listei);
- La apelarea cu sufixul e, se transmite o lista cu noile variabile de mediu prin env - un tablou de pointeri pe siruri de caractere de forma envar = value (ultimul element din env fiind NULL) daca env este NULL, procesul fiu mosteneste variabilele de mediu ale procesului parinte;
- Lungimea totala a arg0 + arg1 + + argn nu poate depasi 128 de caractere;
- Toate fisierele deschise de procesul parinte raman deschise in procesul fiu.
In caz de succes nu se mai revine din functiile exec; in caz de eroare se returneaza -1, errno luand una din valorile:
E2BIG Arg list too long (lista de argumente prea lunga)
EACCES Permission denied (nu este permis accesul la fisier)
EMFILE Too many open files (prea multe fisiere deschise)
ENOENT Path or file name not found (calea sau fisierul nu au fost gasite)
ENOEXEC Exec format error (fisierul corespunzator procesului fiu apelat nu contine cod executabil sau contine cod executabil eronat)
ENOMEM Not enough core (nu exista memorie suficienta pentru lansarea in executie a procesului fiu)
5. Functiile spawn()
Grupul de functii spawn() incarca si lanseaza in executie procese fiu (daca este suficienta memorie disponibila), putandu-se eventual reveni dupa terminarea acestora in procesul parinte; toate au prototipurile in PROCESS.H
int spawnl(int mode, char *path, char *arg0, , NULL);
int spawnle(int mode, char *path, char *arg0, , NULL, char *env[]);
int spawnlp(int mode, char *path, char *arg0, NULL);
int spawnlpe(int mode, char *path, char *arg0, , NULL, char *env[]);
int spawnv (int mode, char *path, char *argv[]);
int spawnve (int mode, char *path, char *argv[], char *env[]);
int spawnvp (int mode, char *path, char *argv[]);
int spawnvpe(int mode, char *path, char *argv[], char *env[]);
Valoarea argumentului mode determina comportarea procesului fiu dupa apelarea spawn():
-P_WAIT procesul parinte asteapta (on hold) terminarea procesului fiu (dupa care isi reia executia);
-P_NOWAIT procesul parinte isi continua executia in paralel cu procesul fiu (neimplementata);
-P_OVERLAY procesul fiu va fi incarcat in memoria anterior ocupata de procesul parinte (are acelasi efect cu exec ..()).
Modul de cautare a fisierului cat si semnificatia sufixelor p, l, v, e sunt aceleasi ca la grupul exec(). Observatiile de la grupul exec() raman valabile. In caz de esec se returneaza -1, errno luand una din valorile:
E2BIG Arg list too long
EINVAL Invalid argument (argument invalid)
ENOENT Path or file name not found
ENOEXEC Exec format error
ENOMEM Not enough core
In caz de succes returneaza codul de iesire al procesului fiu (pentru P_WAIT).
6. Functii cu lista variabila de argumente
Pot fi implementate folosind macrodefinitiile declarate in STDARG.H. Acestea pun la dispozitia unei functii o posibilitate portabila de acces la argumente, cand functia preia un numar variabil de parametri. Lista de argumente (parametri) a unei astfel de functii incepe cu un numar fix de argumente optionale. Functia care are un numar variabil de argumente este declarata folosind constructia '' imediat dupa ultimul argument fix. Argumentele fixe sunt accesate ca orice argument, iar cele optionale, folosind macrodefinitiile. In fisierul <stdarg.h> este declarat tipul va_list si macrodefinitiile va_start, va_arg si va _end.
Tipul de data va_list se declara astfel: typedef void *va_list;
Prin urmare:
va_list : este un pointer la informatiile necesare pentru va_arg si va_end; deci pointer la o lista variabila de argumente cand o functie apelata primeste o lista variabila de argumente, se declara o variabila: ptr_arg de tip va_list astfel: va_list ptr_arg;
va_start : initializeaza variabila ptr_arg de tipul va_list cu adresa primului parametru din sublista variabila; trebuie folosita inainte de a apela va_arg sau va_end;
Prototipul este :
void va_start(va_list ptr_arg, ultim_fix)
unde ultim_fix este numele ultimului parametru din sublista fixa.
va_arg : intoarce valoarea parametrului urmator din sublista variabila.
Prototipul este:
tip_par va_arg(va_list ptr_arg, tip_par);
unde tip_par este tipul parametrului urmator; la fiecare apelare va_arg() intoarce valoarea parametrului indicat de ptr_arg si modifica variabila ptr_arg asa incat sa indice parametrul urmator. In acest scop foloseste tipul specificat al parametrului tip_ par pentru a stabili dimensiunea zonei de memorie alocate. Datorita conversiilor implicite la transferul valorilor din sublista variabila, tipurile char, unsigned char si float nu se folosesc cu va_arg.
va_end : incheie operatia de extragere a valorilor parametrilor si trebuie apelata neaparat inainte de revenirea din functie. Prototipul este
void va_end(va_list ptr_arg);
Dupa ce se executa va_end(), pentru a relua extragerea parametrilor, este necesar sa se apeleze din nou va_start.
Exemplu 1
#include <stdio.h>
#include <stdarg.h>
/*calculeaza produsul numerelor nenule care fac parte dintr-o lista variabila */
void produs(char *msg, )
int main(void)
O aplicatie utila a listelor variabile de parametri o constituie crearea de functii de intrare / iesire dedicate, care sa fie folosite in locul functiilor scanf si printf.. In acest scop se pot utiliza noi functii:
int vprintf(const char * format, va_list arglist)
- scrie iesirea formatata la stdout (fisierul standard de iesire), ca si printf();
- are prototipul in stdio.h;
- lucreaza exact ca printf () dar accepta un pointer la lista de argumente in locul listei
propriu zise (si aici trebuie sa fie acelasi numar de specificatori cu numarul argumentelor);
- returneaza numarul de octeti inscrisi, astfel EOF pentru eroare;
- nu se apeleaza direct, ci doar prin intermediul unei functii intermediare (pentru a obtine un argument de tip va_list).
Exemplu 2
#include <stdio.h>
#include <stdarg.h>
int vpf(char *fmt, )
int main(void)
int vscanf(const char * format, va_list arglist)
- scaneaza si formateaza intrarea de la stdin (fisier standard de intrare)
- are prototipul in stdio.h;
- lucreaza exact ca scanf() numai ca accepta un pointer de la lista de argumente in locul unei liste;
- returneaza numarul de elemente ce au fost parcurse, convertite si memorate cu succes altfel EOF daca s-a detectat sfarsit de fisier;
- se apeleaza (ca si vsprintf() ) tot prin intermediul unei functii cu lista variabila de argumente
Exemplu 3
#include <stdio.h>
#include <stdarg.h>
#include <conio.h>
int vscnf(char * fmt, )
int main(void)
int vsprinf(char *buffer, const char *format, va_list arglist);
int vsscanf(const char *buffer, const char *format, va_list arglist);
- functiile scriu sau citesc in /dintr-un sir de caractere
- modul de lucru este asemanator; maniera de apelare este cea prezentata deja la vprintf() sau vscanf();
- au prototipurile in stdio.h;
int vfprintf(FILE *stream, const char *format, va_list arglist);
int vfscanf(FILE *stream, const char *format, va_list arglist);
- aceste doua functii sunt variantele cu lista variabila de argumente pentru fprintf() (scriere formatata intr-un fisier deschis) respectiv fscanf() (citire formatata dintr-un fisier deschis);
-au prototipurile in stdio.h;
Problema 1
Sa se faca un program care calculeaza suma a doua numere, numere ce nu sunt citite de la tastatura ci sunt transmise ca argumente programului. Sa se generalizeze si pentru mai multe numere.
Problema 2
Sa se faca un proiect compus din doua module (fisiere):
- unul ce contine functia main si care afiseaza argumentele liniei de comanda
- altul ce contine o functie ce face acelasi lucru , functie numita 'afisare' , ce va fi apelata in functia main() din primul modul (se folosesc _argc si _argv)
Problema 3
Scrieti un program care afiseaza variabilele de mediu DOS, modifica calea de cautare a fisierelor (variabila PATH) si reafiseaza variabilele de mediu. Faceti o alta varianta a programului care completeaza valoarea lui PATH cu o cale dorita de dvs (de exemplu calea existenta: c:winntsystem32;c:winnt se completeaza cu c:labora~1pc)
Problema 4
Scrieti un program numit tail care tipareste un set de linii specificate intr-o gama data ca argument in linia de comanda. Liniile se citesc de la tastatura si se depun intr-un tablou de siruri
Exemplu:
tail 5- /* tipareste toate liniile, incepand cu linia 5 */
tail -10 /* tipareste primele 10 linii */
tail 2-8 /* tipareste 7 linii (inclusiv liniile 2 si 8) */
tail /* tipareste toate liniile */
Problema nr. 5
Scrieti doua functii de afisare si citire a unui text intr-o anumita pozitie de pe ecran (mod text). Functiile vor avea urmatoarele prototipuri:
int readxy(int x, int y, char *format, );
int printxy(int x, int y, char *format,);
unde x, y reprezinta coordonatele ecran, iar variabila format reprezinta formatul de afisare.
Sa se testeze cele doua functii prin scrierea unui program in care coordonatele ecran se introduc de la tastatura.
Problema nr. 6
Sa se testeze expandarea argumentelor liniei de comanda ce contin wildcards
Problema nr. 7
Testati transmiterea argumentelor liniei de comanda ale procesului parinte la un proces fiu lansat prin exec() sau spawn().
Problema nr. 8
Testati transmiterea variabilelor de mediu DOS (env) la exec() sau spawn() Urmariti modificarea unei variabile in procesul fiu (getenv() / putenv()) si refacerea ei automata la revenirea in procesul parinte.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1481
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved