Documente Academic
Documente Profesional
Documente Cultură
5 ,6
Tema: Tehnicile prelucrrii tablourilor, utiliznd subprograme
Scopul lucrrii: nsuirea tehnicilor de algoritmizare i programare cu subprograme n prelucrarea
tablourilor uni- i bidimensionale n C.
Obiectivele temei
1. Aprofundarea cunotinelor n limbajul i mediul TurboC i perfecionarea tehnicii de programare cu
subprograme n prelucrarea tablourilor uni- i bidimensionale.
2. Dezvoltarea procedeelor de algoritmizare i progamare prin descompunerea problemei n module
autonome care, apoi, vor fi reprezentate prin module de program pentru prelucrarea tablourilor uni- i
bidimensionale n C dup principii comune cu apeluri multiple, analiznd soluiile stereotipe i cele
eficiente.
3. nsuirea tehnicilor eficiente de parcurgere, cutare, schimbare i ordonare a structurilor i calculul
conform cunotinelor obinute din matematic i n baza lucrrilor precedente ntr-un program complex,
alctuit dup principiile top-down.
4. Llab. 5 se analizeaz testele din Anexa 2. i se preia variantele problemelor din Llab. 3 i se transform n
programe cu funcii proprii dup stil vechi i nou.
5. Llab. 6 se preia variantele problemelor din Llab. 4 i se transform n programe cu func ii proprii definite
ca proceduri n C cu transmiterea argumentelor func iilor n cteva moduri. Totodat se aplic i la
soluionarea problemelor din Anexa 3.
unde lista-parametri:
declaraie-parametru
declaraie-parametru, lista-parametri
Corpul-funciei:
<declaraiile variabilelor locale>; < <instruciuni> <instruciune-compus>>; <return rezultatul final>;
Dintre specificatorii de clas de memorie numai extern i static sunt admii. Dac nici un specificator
de clas de memorie nu este prezent, atunci funcia este automat declarat extern, deoarece n C nu se admite
ca o funcie s fie definit n interiorul altei funcii.
Un declarator de funcie este similar cu un declarator pentru funcie care returneaz ... cu excepia c
el listeaz parametrii formali ai funciei care se definete.
O metod de a comunica datele ntre funcii este prin argumente. Parantezele mici care urmeaz dup
numele funciei nchid lista argumentelor.
n limbajul C argumentele funciilor sunt transmise prin valoare. Aceasta nseamn c n C funcia
apelat primete valorile argumentelor sale ntr-o copie particular de variabile temporare (n realitate pe stiv).
Funcia apelat nu poate altera dect variabilele sale particulare, adic copiile temporare.
Apelul prin valoare este o posibilitate, dar nu i o obligativitate. Apelul prin valoare conduce la
programe mai compacte cu mai puine variabile externe, deoarece argumentele pot fi tratate ca variabile locale,
i care pot fi modificate convenabil n rutina apelat.
Ca argument poate aprea orice expresie admis n C. Funcia returneaz valoarea acestei expresii funciei
apelante.
O funcie nu returneaz n mod obligatoriu o valoare. O instruciune return, fr expresie ca parametru,
cauzeaz numai transferul controlului funciei apelante nu i o valoare util.
La rndul su funcia apelant poate ignora valoarea returnat.
De obicei o funcie returneaz o valoare de tip ntreg. Dac se dorete ca funcia s returneze un alt tip,
atunci numele tipului trebuie s precead numele funciei, iar programul trebuie s conin o declaraie a acestei
funcii att n fiierul n care funcia este definit ct i n fiierul unde funcia este apelat. Pentru a evita orice
confuzie se recomand ca tipul valorii returnate de funcie s fie ntotdeauna precizat, iar dac dorim n mod
expres ca funcia s nu returneze o valoare s folosim tipul void. De exemplu, funcia atof(s) din biblioteca
asociat compilatorului convertete irul s de cifre n valoarea sa n dubl precizie. Vom declara funcia sub
forma:
double atof(char s[]); sau mpreun cu alte variabile de tip double:
double sum, atof(char s[]);
Dac o funcie returneaz o valoare de tip char, nu este nevoie de nici o declaraie de tip din cauza conversiilor
implicite. Totdeauna tipul char este convertit la int n expresii.
Dup cum se observ, diferitele pri pot s lipseasc; o funcie minim este:
dummy() {} funcia care nu face nimic. Aceast funcie poate fi util n programe, innd locul
unei alte funcii n dezvoltarea ulterioar a programului.
Numele funciei poate fi precedat de un tip, dac funcia returneaz altceva dect o valoare ntreag.
Numele funciei poate fi de asemenea precedat de clasa de memorie extern sau static. Dac nici un
specificator de clas de memorie nu este prezent, atunci funcia este automat declarat extern, deoarece n C nu
se admite ca o funcie s fie definit n interiorul altei funcii.
Declaraia unei funcii se face implicit la apariia ei. Se interpreteaz ca funcie orice identificator
nedeclarat anterior i urmat de paranteze (). Pentru a evita surprize neplcute datorit neconcordanei dintre
tipurile de parametri aceast practic nu este recomandat. Includerea <declaraiilor variabilelor locale>; i
<return <rezultatul final>; se fac dup necesitate.
Exemplu de funcie definit:
int max(int a, int b, int c) /* int este un specificator de tip care indic faptul c funcia max returneaz o valoare
ntreag; max(int a, int b, int c) este declaraia funciei i a parametrilor formali; */
{
// { . . . } este corpul funciei.
int m;
m = (a>b) ? a : b;
return (m>c) ? m : c;
}
Aceast funcie determin maximul dintre 3 numere date.
n limbajul C orice funcie este apelat prin numele ei, urmat de lista real a argumentelor, nchis ntre
paranteze rotunde.
Dac ntr-o expresie numele funciei nu este urmat imediat de o parantez (, adic funcia nu apare pe
poziia de apel de funcie atunci nu se realizeaz imediat apelul funciei respective ci se genereaz un pointer la
funcie
Apelul (referirea sau utilizarea) unei funcii se face prin:
nume_funcie (list_parametri_efectivi)
Acesta poate apare ca o instruciune, n cazul funciilor care nu ntorc un rezultat:
nume_funcie (list_parametri_efectivi);
De exemplu:
printf(x=%5.2lf\n,x);
mesaj();
Pentru funciile care ntorc un rezultat apelul de funcie poate apare ca operand ntr-o expresie.
De exemplu:
y=sin(x);
nr_zile=bisect(an)+365;
Se remarc faptul c lista de argumente (sau de parametri efectivi) poate fi vid.
S ilustrm mecanismul definirii unei funcii scriind funcia putere power(m,n) care ridic un ntreg m la o
putere ntreag pozitiv n. Astfel valoarea lui power(2,5) este 32. Aceast funcie desigur nu este complet,
deoarece calculeaz numai puteri pozitive de ntregi mici.
Prezentm mai jos funcia power i un program principal care o apeleaz, pentru a putea vedea i
structura unui program.
power(int x, int n)
{
int i, p; p = 1;
for (i=1; i<=n; ++i) p = p * x;
return p;
}
main() {
int i;
for (i=0; i<10; ++i) printf(" %d %d\n", i, power(2,i),
power(-3,i));
}
Funcia power este apelat n programul principal de dou ori. Fiecare apel transmite funciei dou
argumente.
Rezultatul este afiat de funcia de bibliotec printf ().
Numele funciei este urmat obligatoriu de paranteze, chiar dac lista parametrilor este vid.
n general numele funciei este ales dup dorina utilizatorului. Totui n fiecare program trebuie s
existe o funcie cu numele impus main; orice program i ncepe execuia cu funcia main. Celelalte funcii snt
apelate din interiorul funciei main. Unele dintre funciile apelate snt definite n acelai program, altele snt
coninute ntr-o bibliotec de funcii.
Funciile comunic ntre ele prin lista de argumente i prin valorile ntoarse de funcii. Comunicarea poate
fi realizat i prin variabilele externe, definite n afara tuturor funciilor care se numesc variabilele globale i au
o vizibilitate general pentru tot programul.
De obicei revenirea dintr-o funcie se face prin intermediul unei instruciuni return.
Valoarea pe care o funcie o calculeaz poate fi returnat prin instruciunea return, care dup cum am
vzut are dou formate:
return;
return expresie;
Ca argument poate aprea orice expresie admis n C. Funcia returneaz valoarea acestei expresii funciei
apelante.
O funcie nu returneaz n mod obligatoriu o valoare. O instruciune return, fr expresie ca parametru,
cauzeaz numai transferul controlului funciei apelante nu i o valoare util.
La rndul su funcia apelant poate ignora valoarea returnat.
De obicei o funcie returneaz o valoare de tip ntreg. Dac se dorete ca funcia s returneze un alt tip,
atunci numele tipului trebuie s precead numele funciei, iar programul trebuie s conin o declaraie a acestei
funcii att n fiierul n care funcia este definit ct i n fiierul unde funcia este apelat.
Pentru a evita orice confuzie se recomand ca tipul valorii returnate de funcie s fie ntotdeauna
precizat, iar dac dorim n mod expres ca funcia s nu returneze o valoare s folosim tipul void.
De exemplu, funcia atof(s) din biblioteca asociat compilatorului convertete irul s de cifre n valoarea
sa n dubl precizie. Vom declara funcia sub forma:
double atof(char s[]);
sau mpreun cu alte variabile de tip double:
double sum, atof(char s[]);
Funciile nu pot returna masive, structuri, reuniuni sau funcii.
Dac o funcie returneaz o valoare de tip char, nu este nevoie de nici o declaraie de tip din cauza
conversiilor implicite. Totdeauna tipul char este convertit la int n expresii.
Definirea unei funcii se poate face oriunde in cadrul codului sursa, sau chiar in alte fiiere, ins nu poate
fi fcuta in interiorul altei funcii. Deseori mai nti se declar prototipul unei funcii iar mai jos corpul funciei.
Prototipul funciei are rolul de a anuna numele funciei, tipul returnat si tipul si numarul parametrilor. n cazul
c funcia nu are parametri sau nu returneaza nici o valoare, se foloseste tipul vid void. Nu este necesar
prezena prototipului, dar dac acesta lipsete, iar funcia este apelat naintea declaraiei ei, unele compilatoare
(mai vechi) vor da mesaje de avertizare in momentul compilrii. Prototipurile au fost introduse n standardul
ANSI (versiunile mai vechi de C nu prevedeau prototipuri de funcii) pentru a permite compilatorului s fac
anumite verificri legate de numarul parametrilor funciei i de conversii ilegale ntre tipul parametrilor i cel al
argumentelor.
n C, cnd apelul unei funcii poate apare naintea declarrii ei, atunci funcia poate fi definita mai
trziu in acelai fiier, sau in alt fiier sau dintr-o biblioteca standard. In ANSI C, prototipul funciei remediaz
problema punnd la dispoziie numrul si tipul argumentelor funciei. Prototipul specifica, de asemenea, si tipul
returnat de funcie. Sintaxa prototipului unei funcii este:
tip nume_funcie (lista_tipuri_parametri);
In lista de parametri putem specifica chiar si parametrul, dar asta este optional. Daca Funcia nu are parametri,
atunci se foloseste "void".
Exemplu:
#include <>
main()
{ int n;
void tipareste_mesaj(int);
printf("Dati un numar natural mic: "); scanf("%d", &n);
tipareste_mesaj(n);
}
void tipareste_mesaj(k)
{ int i;
printf("Iti urez:\n");
for (i = 0; i < k; ++i) printf(" O zi buna ! \n");
}
Prototipul unei funcii poate fi plasat in corpul altei funcii, sau de regula, se scriu la inceputul programelor
dupa directivele #include <> si #define.
Exemple de prototipuri de functii:
// o functie care primeste doua variabile x, y de tip real dubla precizie si returneaza o variabila de tip double
double suma(double x, double y);
// functia zero primeste un tablou de 100 de numere reale in dubla precizie si returneaza un intreg
int zero(double tab s100t);
int zero(double tabst); /* nu se specifica dimensiunea */
// functia f primeste un intreg x si un sir de caractere t; nu returneaza nimic (void)
void f(int x, char tst);
// functia f nu primeste si nu returneaza nimic
void f(void);
O functie poate fi apelata numai daca a fost definita. Dar exista situatii in care apelul nu e precedat de
definitie, caz in care definitia trebuie inlocuita prin prototipul functiei. Prototipul este asemanator cu antetul, dar
e urmat de punct si virgula ; .
Prin prototip se informeaza compilatorul despre:
- tipul valorii returnate de functie
- existenta si tipurile parametrilor functiei
Observatii:
- Este posibil ca in prototip sa se omita numele parametrilor formali:
double suma(double, double);
int
zero(double tabst);
void f(int, charst);
- Compilatorul utilizeaza informatiile furnizate in prototip pentru a verifica tipurile parametrilor din
functia de apel.
- Exista fisiere cu prototipuri de functii utilizate frecvent in operatii de intrare iesire (stdio.h), operatii
matematice (math.h), operatii pe siruri de caractere (string.h), etc., fisiere care trebuie incluse in programul
sursa, daca se folosesc functii de biblioteca.
Mecanismul de transmitere a parametrilor ctre funcii n limbajul C este prin "valoare", spre deosebire de
alte limbaje (ca de ex. Pascal) unde se ntlnete i transmiterea prin valoare i prin adres. La transmiterea prin
valoare, modificrile asupra parametrilor efectuate n interiorul funciei nu se propaga si n afara funciei. Dac
totui se dorete alterarea efectiv a unui argument al funciei apelante, acest lucru se realizeaz cu ajutorul
pointerilor sau a variabilelor declarate externe. Deci, chiar daca mecanismul de transmitere a parametrilor este
doar prin valoare, in limbajul C se pot transmite parametri si prin adresa, intr-un mod indirect, folosind pointeri.
n general numele funciei este ales dup dorina utilizatorului. Totui n fiecare program trebuie s
existe o funcie cu numele impus main; orice program i ncepe execuia cu funcia main. Celelalte funcii snt
apelate din interiorul funciei main. Unele dintre funciile apelate sunt definite n acelai program, altele snt
coninute ntr-o bibliotec de funcii.
Comunicarea ntre funcii se face prin argumente i valori returnate de funcii. Comunicarea ntre funcii
poate fi fcut i prin intermediul variabilelor externe.
O funcie poate fi declarat i static. n acest caz ea poate fi apelat numai din fiierul unde a fost
definit.
Funciile n C pot fi folosite recursiv, deci o funcie se poate apela pe ea nsi fie direct, fie indirect.
n general ns recursivitatea nu face economie de memorie, deoarece trebuie meninut o stiv cu
valorile de prelucrat.
Funcia apelat nu poate altera dect variabilele sale particulare, adic copiile temporare.
Apelul prin valoare este o posibilitate, dar nu i o obligativitate. Apelul prin valoare conduce la
programe mai compacte cu mai puine variabile externe, deoarece argumentele pot fi tratate ca variabile locale,
i care pot fi modificate convenabil n rutina apelat.
Ca exemplu, prezentm o versiune a funciei putere care face uz de acest fapt:
power(int x, int n) {
int p;
for (p=1; n>0; --n) p = p * x;
return p;
}
Argumentul n este utilizat ca o variabil temporar i este decrementat pn devine zero; astfel nu este
nevoie de nc o variabil i. Orice operaii s-ar face asupra lui n n interiorul funciei, ele nu au efect asupra
argumentului pentru care funcia a fost apelat.
}
In antetul funciei, urmatoarele declaraii sunt echivalente:
int a[][5] int (*a)[5] int a[3][5]
Constanta 3 actioneaza ca o reminiscen a omului, dar compilatorul nu tine cont de ea.
n C sunt, pentru nceptori, uneori apar confuzi in legtura cu deosebirea dintre un tablou bidimensional si
un tablou de pointeri cum ar fi "a" din exemplul de mai sus. Fiind date declaraiile
int a[10][10];
int *b[10]; utilizarile lui "a" si "b" pot fi similare, in sensul ca a[5][5] si
b[5][5] sunt ambele referine legale ale aceluiasi "int".
Avantaje pentru utilizarea tablourilor (dezavantaje pentru pointeri):
- "a" este un tablou in toata regula: toate cele 100 celule de memorie trebuie alocate, iar pentru gasirea
fiecarui element:
- se face calculul obinuit al indicelui;
- pentru "b", oricum prin declararea sa se aloca 10 pointeri; fiecare trebuie facut sa pointeze un tablou de
intregi.
Presupunnd ca fiecare pointeaza cate 10 elemente din tablou, atunci vom obtine 100 celule de memorie
rezervate, plus cele 10 celule pentru pointeri. Astfel tabloul de pointeri utilizeaza sensibil mai mult spatiu si
poate cere un procedeu explicit de initializare.
De obicei, daca un tablou declarat "auto" nu este explicit initializat, atunci elementele sirului vor contine
valori "garbage".
Sirurile "static" si "external" sunt initializate implicit cu 0. Iata un mod simplu de a initializa toate valorile
unui tablou cu 0:
int a[2][2][3] = {0};
Cand un tablou multidimensional este un parametru formal in definitia unei functii, toate dimensiunile,
exceptand prima trebuie specificate.
Exemplu: Consideram initializarea:
int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
ceea ce nseamn o simpl identificare a numelui tabloului:
ia;
iar identificatorul tabloului este echivalent cu identificarea adresei primului element:
ia;
&ia[0];
Analogic se poate adresa la valoarea primului element prin dou moduri:
*ia;
ia[0]; // ambele expresii ntorc valoarea primului element
Accesul la elementul al doilea se poate face n mai multe moduri:
&ia[1];
ia+1;
*(ia+1); ia[1];
Exemplu:
#include <iostream>
int main()
{
int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
int *pbegin = ia;
int *pend = ia + 9;
while ( pbegin != pend ) {
cout << *pbegin <<;
++pbegin;
}
Pointerul *pbegin se iniialiaz cu adresa primului element. Fiecare parcurgere n ciclu mrete pointerul
Trimiterea tablourilor ca argumente pentru functii. Intr-o definitie de functie, un parametru formal care este
declarat ca un tablou este de fapt un pointer. Cand este trimis un tablou, atunci se trimite de fapt adresa de baza
(evident prin "call-by-value"). Elementele tabloului nu sunt copiate. Ca o conventie de notatie, compilatorul
permite folosirea parantezelor patrate ([,]) in declararea pointerilor ca parametri.
Exemplu: Suma elementelor unui sir de tip tablou
int suma(int a[], int n) /* n dimensiunea tabloului */
{
int i, s = 0;
for (i = 0; i < n; ++i)
s += a[i];
return s;
}
In antetul functiei precedente, declaratia:
int a[]; este echivalenta cu int *a;
Pe de alta parte, declaratiile de mai sus nu sunt echivalente daca se utilizeaza in alta parte:
prima se refera la creearea unui pointer constant (fara spatiu de memorie);
a doua va crea o variabila pointer.
Presupunem ca "v" este declarat ca fiind un tablou de 100 de elemente de tip "int". Dupa ce am atribuit valori
elementelor sale, putem utiliza functia "suma()" pentru a aduna anumite valori ale lui "v".
---------------------------------------------------------------| Apel
| Ce se calculeaza si se returneaza ? |
---------------------------------------------------------------suma(v, 100)
v[0] + v[1] + ... + v[99]
suma(v, 88)
v[0] + v[1] + ... + v[87]
suma(&v[7], k-7) v[7] + v[8] + ... + v[k - 1]
suma(v + 7, 2 * k) v[7] + v[8] + ... + v[2 * k + 6]
---------------------------------------------------------------Exemplu: Sortare cu bule - "Bubble sort". Algoritmii eficienti de sortare au, de obicei, O(n*log n)
operatii. Metoda sortarii cu bule este ineficienta din acest punct de vedere deoarece are O(n^2) operatii. Totusi,
pentru tablouri de lungime mica, numarul de operatii este acceptabil. Un mod "elegant" ar fi:
#include ..
Schema-bloc
START
citire(X,n)
afisare(X,n)
construireAB(X,A,B,n)
numarare(A,B,n,mA,mB)
afisare(A,n)
afisare(B,n)
NU
NU
mA<mB
DA
mA>mB
DA
schimbare_coloane(A,n)
schimbare_coloane(B,n)
afisare(A,n)
afisare(B,n)
STOP
citire(X,n)
afisare(X,n)
i=0
Citete: n
i=0
DA
i<n
NU
NU
i<n
j=0
DA
j=0
DA
j<n
NU
NU
j<n
Afieaz: X[i,j]
DA
Citete: X[i,j]
j=j+1
j=j+1
i=i+1
i=i+1
STOP
STOP
numarare(A,B,n,mA,mB)
mA=0
mB=0
i=0
NU
i<n
DA
j=0
NU
j<n
DA
NU
A[i][j]>B[i][j]
DA
mA=mA+1
NU
A[i][j]<B[i][j]
DA
mB=mB+1
j=j+1
i=i+1
STOP
construireAB(X,A,B,n)
i=0
NU
i<n
DA
j=0
NU
j<n
DA
NU
j>n-i-1
A[i][j]=X[i][j]
NU
DA
A[i][j]=0
j>i
B[i][j]=X[i][j]
DA
B[i][j]=0
j=j+1
i=i+1
STOP
schimbare_coloane(A,n)
j=0
j<n/2
NU
DA
i=0
NU
i<n
DA
aux=A[i][2*j]
A[i][2*j]=A[i][2*j+1]
A[i][2*j+1]=aux
j=j+1
i=i+1
STOP
Listingul programului
#include<stdio.h>
#include<conio.h>
#define N 50
void asteapta() {
printf("Apasati orice tasta pentru continuare...\n");
getch();
}
void afisare(int M[N][N],char nume,int n) {
int i,j;
printf("Matricea %c:\n",nume);
for(i=0;i<n;++i) {
for(j=0;j<n;++j) printf("%5d ",M[i][j]);
printf("\n");
}
}
void citire(int M[N][N],char nume,int &n) {
int i,j;
printf("n=");
scanf("%d",&n);
printf("Introduceti elementele matricei %c:\n",nume);
for(i=0;i<n;++i)
for(j=0;j<n;++j) scanf("%d",&M[i][j]);
}
void numarare(int A[N][N],int B[N][N],int n,int &mA,int &mB) {
int i,j;
mA=mB=0;
for(i=0;i<n;++i)
for(j=0;j<n;++j) {
if(A[i][j]>B[i][j]) ++mA;
if(A[i][j]<B[i][j]) ++mB;
}
}
void construireAB(int X[N][N],int A[N][N],int B[N][N],int n) {
int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j) {
if(j>n-i-1) A[i][j]=0; else A[i][j]=X[i][j];
if(j>i) B[i][j]=0; else B[i][j]=X[i][j];
}
}
void schimbare_coloane(int A[N][N],int n) {
int i,j,aux;
for(j=0;j<n/2;++j)
for(i=0;i<n;++i) {
aux=A[i][2*j];
A[i][2*j]=A[i][2*j+1];
A[i][2*j+1]=aux;
}
}
void main() {
int X[N][N],A[N][N],B[N][N],n,i,j,mA,mB;
clrscr();
citire(X,'X',n);
afisare(X,'X',n);
asteapta();
construireAB(X,A,B,n);
numarare(A,B,n,mA,mB);
afisare(A,'A',n);
asteapta();
afisare(B,'B',n);
asteapta();
if(mA>mB) {
printf("In primul tablou sunt mai multe elemente mai mari.\n");
printf("Schimbam coloanele pare cu cele impare in A si B...\n");
schimbare_coloane(A,n);
schimbare_coloane(B,n);
printf("Matricile dupa schimbare:\n");
afisare(A,'A',n);
asteapta();
afisare(B,'B',n);
}
else
if(mA<mB)
printf("In al doilea tablou sunt mai multe elemente mai mari");
else printf("In ambele tablouri sunt la fel de multe elemente mai mari");
getch();
}
Trimiterea argumentelor catre "main()"
C pune la dispozitie siruri de orice tip, inclusiv siruri de pointeri. Pentru scrierea de programe care folosesc
argumente in linia de comanda, trebuie sa folosim siruri de pointeri catre caractere. Pentru aceasta, functia
"main()" foloseste doua argumente, numite generic "argc" si "argv".
Exemplu:
#include
void main(int argc, char *argv[])
{ int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; ++i) printf("argv[%d] = %s\n", i, argv[i]);
}
Variabila "argc" precizeaza numarul de argumente din linia de comanda. Sirul "argv" este un sir de pointeri
catre caracter si poate fi gandit ca vector de siruri de caractere. Deoarece elementul "argv[0]" contine
intotdeauna numele comenzii, rezulta ca valoarea lui "argc" va fi mai mare sau egala cu 1.
Compilam programul de mai sus si obtinem executabilul "prog1.exe". Daca dam comanda
prog1
atunci pe ecran se va afisa
argc = 1
argv[0] = prog1
Daca dam comanda
prog1 fisier1 fisier2
atunci pe ecran se va afisa
argc = 3
argv[0] = prog1
argv[1] = fisier1
argv[2] = fisier2
Parametrul "argv" s-ar fi putut declara si astfel
char **argv;
Acesta este un pointer catre pointer catre "char" si acesta poate fi gandit ca un sir de pointeri catre "char",
care la randul lor pot fi ganditi ca vector de siruri de caractere. Observati ca nu alocam spatiu in memorie pentru
sirurile din linia de comanda. Acest lucru este facut de insusi sistemul C cand atribuie valori pentru argumentele
"argc" si "argv".
Anexa 2. Teste de verificre ale cunostintelor:
}
7. Analizai i argumentai ce valori va afia
/* A.c */
int x=666; /*.*/
main(){
f(3);
printf(" ::x = %d\n", x);
g(2); g(5);
printf(" ::x = %d\n", x); }
g(n){
static int x=17; /* g*/
printf("g::x = %2d g::n = %d\n", x++, n);
if(n) g(n-1); else x = 0; }
/* B.c */
extern x; /**/
f(n){
/* */
x++;
/**/
{ int x; /* */
x = n+1; /**/
n = 2*x; /**/
}
x = n-1; /**/
}
}
10. Analizai i argumentai ce valori va afia
// Generare matrice unitate
void matrunit (float u[][30], int n) {
int i,j;
for (i=0;i<n;i++) {
for (j=0;j<n;j++) u[i][j]=0;
u[i,i]=1; }
}
// afisare matrice patratica (cu 30 de coloane declarate)
void scrmatr (float a[][30], int n) { int i,j;
for (i=0;i<n;i++) {
for (j=0;j<n;j++)
printf ("%4.0f",a[i][j]);
}
// utilizare
void main () {
float x[30][30]; int n;
for (n=2;n<=10;n++) { matrunit(x,n);
scrmatr(x,n);
}
}
printf("\n");
getchar();
11. Analizai i argumentai ce valori va afia. Functie recursiva pentru ridicarea unui numar la o
putere intreaga pe baza relatiei de recurenta
x^k = x * x^(k-1) si cu x^0=1
double power (double x, int n) {
if (n==0)
return 1. ; return x * power(x,n-1); }
12. Analizai i argumentai ce valori va afia. Functie recursiva pentru ridicarea unui numar la o putere
intreaga cu numar redus de inmultiri, pe baza relatiei de recurenta
x^k = x^(k/2) * x^(k/2) daca k este par si x^k= x * x^(k-1) daca k impar
double power (double x, int n) {
double y;
if (n==0)
return 1;
if ( n %2 ==0) { y=power(x,n/2);
else return (x * power (x,n-1));
return ( y*y); }
3. Sa se elaboreze un program interactiv care prelucreaza un tablou de max N intregi ( N - predefinita ), prin
urmatoarele comenzi:
V - initializeaza tabloul, prin citirea elementelor pana la introducerea lui CTRL/Z sau a numarului maxim de
elemente
A - initializeaza tabloul, fiecare element fiind egal cu indicele sau
O - listeaza elementele tabloului ordonate crescator ( in tablou elementele trebuie sa ramana in ordinea
introducerii )
C - cauta o valoare in tablou, afisand indicele in cazul gasirii
M - cauta o valoare in tablou, pe care o sterge in cazul gasirii - dimensiunea tabloului va scadea astfel cu o
unitate ( nr_elem, nu N!!!); stergerea se realizeaza prin mutarea cu o pozitie inspre indicii mici, a tuturor
elementelor de tablou urmatoare celui care se sterge; o alta varianta este de a copia ultimul element peste cel
care se sterge
X - terminare.
4. Pentru matricea dat A={a i,j}, i=1,n; j=1,n; calculai componentele algebrice fa de elementele diagonalei
principale i obinei n matrice B da rangul 1. Matricea B se obine din A, prin excluderea liniei i coloanei cu
numrul i. Afiai matricele obinute i elementele ei minime.
5. Pentru matricea dat Y={yi,j}, i=1,n; j=1,n; efectuai transpunerea fa de diagonala secundar i obinei
matricea B, apoi calculai E=Y*B5*Y4. Verificai dac matricea E este singular sau nu.
6. Este dat matricea Q={qi,j}, i=1, , n; j=1, , n; delimitat n 5 sectoare dup o anumit schema (la sugestia
studentului) reprezentat ntr-o figur (pentru n impar valoarea lui k=n/2+1). Calculai:
Valoarea minim a sectorului 1;
Valoarea maxim a sectorului 2 i a sectorului 4;
Suma elemntelor sectorului 3;
7. Pentru matricea dat A={a i,j}, i=1,,n; j=1,,n; obinei vectorii B1,B2 care reprezint valorile maxime,
respectiv minime, ale elementelor diagonalelor paralele cu diagonala secundar. Apoi nmulii A 3AT la B1 si B2.
Afiai tablourile obinute ntr-o form clar.
8. Folosind funciile "rand()", "min(,)" si "max(,)", sa se genereze n numere naturale si sa se afiseze minimul si
maximul dintre acestea.
9. (Jocul cap-pajura, simulare Monte-Carlo) Presupunem ca dispunem de o moneda ideala (nemasluita). Doi
jucatori arunca cu moneda dupa urmatoarele reguli:
9.a. Se fac un numar total de n aruncari;
9.b. Primul jucator arunca moneda si celalalt spune "cap" sau
"pajura";
9.c. Daca acesta "ghiceste" ce va pica moneda, atunci se inverseaza jucatorii (adica arunca al doilea si primul
incearca sa
ghiceasca);
9.d. La sfarsit, trebuie afisat scorul (si procentul de castig al fiecaruia).
10. (Conjectura lui Goldbach) Orice numar par mai mare decat 2 se poate scrie ca suma a doua numere prime.
Scrieti un program C care verifica aceasta conjectura pentru numere situate intre m si n. De exemplu, daca
m=700 si n=1100, atunci afisati:
700 = 17 + 683
702 = 11 + 691
704 = 3 + 701
...
1098 = 5 + 1093
1100 = 3 + 1097
Generalizare: Scrieti toate combinatiile posibile de adunare a doua numere prime egal cu un numar dat.
#define NMAX 100
#include<stdio.h>
#include <stdlib.h>
#include <conio.h>
int n;
int citire(double a[NMAX])
{ int i;
for(i=0;i<n;i++)
if(scanf("%lf",&a[i])!=1)
{printf("Date eronate");
exit(1);
}
return 0;
}