+ All Categories
Home > Documents > Informatică Pentru Clasa a X-A

Informatică Pentru Clasa a X-A

Date post: 15-Jun-2015
Category:
Upload: carcalete77
View: 2,011 times
Download: 2 times
Share this document with a friend
35
Informatică pentru clasa a X-a Cap. 1 Tehnica programării modularizate 1. Noţiunea de subprogram Prin subprogram se înţelege un ansamblu alcătuit din tipuri de date, variabile şi instrucţiuni scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat (rulat) doar dacă este apelat de un program sau de un alt subprogram. Subprogramul este cea mai mică unitate de program care poate fi compilată separat. Exemplu : Se citeşte un vector cu n componente numere întregi. Se cere să se tipărească vectorul sortat. Această problemă poate fi rezolvată si clasic, utilizând funcţia main în care se vor realiza toate prelucrările necesare pentru rezolvarea problemei: - citeşte dimensiunea vectorului n - citeşte elementele vectorului - sortează vectorul utilizând unul din algoritmii cunoscuţi - afişează vectorul sortat De această dată vom încerca să rezolvăm problema utilizând tehnica programării modularizate, adică ”spărgând” problema în subprobleme mai mici care vor fi rezolvate, fiecare, de câte un subprogram. În acest caz, programul ar arăta astfel: - apelează subprogramul care citeşte dimensiunea şi elementele vectorului - apelează subprogramul care sortează vectorul - apelează subprogramul care afişează vectorul Utilizând acestă metodă, vom obţine următoarea structură de program: În structura modulară de mai sus am notat cu v vectorul supus prelucrării, iar cu n dimensiunea lui, adică numărul de elemente. În general, o problemă complexă se rezolvă mai uşor dacă o descompunem în altele mai simple; şansele de a greşi la scrierea unui subprogram sunt mai mici decât acelea de a greşi la scrierea unui program mare. Acesta din urmă rezultă din asamblarea subprogramelor la care se adaugă, eventual, câteva linii scrise în programul principal. Avantajele utilizării subprpogramelor sunt: 1 funcţia funcţia funcţia funcţia
Transcript
Page 1: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

Cap. 1 Tehnica programării modularizate

1. Noţiunea de subprogram

Prin subprogram se înţelege un ansamblu alcătuit din tipuri de date, variabile şi instrucţiuni scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat (rulat) doar dacă este apelat de un program sau de un alt subprogram.

Subprogramul este cea mai mică unitate de program care poate fi compilată separat.Exemplu: Se citeşte un vector cu n componente numere întregi. Se cere să se tipărească vectorul sortat.

Această problemă poate fi rezolvată si clasic, utilizând funcţia main în care se vor realiza toate prelucrările necesare pentru rezolvarea problemei:- citeşte dimensiunea vectorului n- citeşte elementele vectorului- sortează vectorul utilizând unul din algoritmii cunoscuţi- afişează vectorul sortat

De această dată vom încerca să rezolvăm problema utilizând tehnica programării modularizate, adică ”spărgând” problema în subprobleme mai mici care vor fi rezolvate, fiecare, de câte un subprogram. În acest caz, programul ar arăta astfel:- apelează subprogramul care citeşte dimensiunea şi elementele vectorului- apelează subprogramul care sortează vectorul- apelează subprogramul care afişează vectorulUtilizând acestă metodă, vom obţine următoarea structură de program:

În structura modulară de mai sus am notat cu v vectorul supus prelucrării, iar cu n dimensiunea lui, adică numărul de elemente.

În general, o problemă complexă se rezolvă mai uşor dacă o descompunem în altele mai simple; şansele de a greşi la scrierea unui subprogram sunt mai mici decât acelea de a greşi la scrierea unui program mare. Acesta din urmă rezultă din asamblarea subprogramelor la care se adaugă, eventual, câteva linii scrise în programul principal. Avantajele utilizării subprpogramelor sunt:- reutilizarea codului : o dată scris, un subprogram poate fi utilizat de mai multe programe- elaborarea algoritmilor prin descompunerea problemei în altele mai simple; în acest fel putem

rezolva mai uşor problema, eventual prin colaborarea unei echipe de programatori- reducerea numărului de erori care pot apărea la scrierea programelor- depistarea cu uşurinţă a erorilor : verificăm subprogramele, apoi modul în care le-am asamblat

În limbajul C/C++ subprogramele sunt de tip funcţie, inclusiv funcţia main este un subprogram, primul care se execută la rularea unui program.

1

funcţia main()

funcţia citire(v,n) funcţia sortare(v,n) funcţia scriere(v,n)

Page 2: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

2. Structura funcţiilor şi apelul lor

2.1 Generalităţi

În esenţă, o funcţie are structura:antetinstrucţiune compusă

a) Anteul conţine mai multe informaţii importante necesare compilatorului şi anume: numele funcţiei, lista parametrilor formali, tipul rezultatului.Structura antetului este:

tip nume(lista parametrilor formali)Lista parametrilor formali este de forma:

parametru1,parametru2,………..,parametrun

Fiecare parametru are forma:tip nume

Observaţie: Există şi posibilitatea ca lista parametrilor formali să fie vidă.

b) Instrucţiunea compusă cuprinde declaraţiile variabilelor locale şi instrucţiunile propriu-zise care descriu operaţiile realizate de către funcţie.

Observaţii:- poate fi tip al unei funcţii orice tip de dată cu excepţia tablourilor- dacă ţinem neapărat, există posibilitatea ca funcţia să întoarcă tablouri, dacă acestea sunt

înglobate în tipuri declarate cu struct, aşa cum se va vedea într-un paragraf ulterior.Exemple de antete de func ţii: - int suma(int a,int b) – funcţia se numeşte suma, returnează un rezultat de tip int şi are doi

parametri formali de tip int, numiţi a şi b- void t(int n,float v[20]) – funcţia se numeşte t, este de tip void (nu returnează rezultat

prin nume), are doi parametri formali, primul numit n, de tip int, al doilea numit v, de tip float* (pointer la float)

- char* sir(int n,char a[200]) – funcţia se numeşte sir, întoarce un pointer către un şir de caractere şi are doi parametri formali, unul de tip int, numit n şi altul de tip char* (pointer la şir de caractere) numit a

- elev mana(int n,char n[200]) – funcţie de tip elev, unde elev este de tipul structură următor:

struct elev{char nume[20];int varsta;

};

Observaţii:- O funcţie returnează rezultatul la întâlnirea instrucţiunii return, care are forma return

expresie; Trebuie ca tipul expresiei să coincidă cu tipul funcţiei sau să poată fi convertit implicit către acesta. La întâlnirea instrucţiunii return, după atribuirea valorii, execuţia funcţiei se încheie şi se revine la funcţia care a apelat-o. În absenţa instrucţiunii return, execuţia funcţiei se încheie după execuţia ultimei instrucţiuni. În acest caz nu se întoarce nici-o valoare (cazul funcţiilor de tip void).

- O funcţie poate fi apelată de sine stătător (prin nume şi lista parametrilor efectivi), dar poate fi inclusă şi în cadrul expresiilor, caz în care, la evaluarea expresiei este apelată. Acestă ultimă formă de apel nu este valabilă în cazul funcţiilor de tip void.

Exemplu:#include<stdio.h>int prod(int x,int y){

return x*y;}void main(){

int x=4,y=9;printf(“%d”,7+prod(x,y));

}

2

Page 3: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

Apelul funcţiei s-a realizat din interiorul expresiei 7+prod(x,y)Observaţii:- în cadrul expresiei, apelul este un operand; el intră în calcul cu valoarea returnată de funcţie- după apelul funcţiei se continuă evaluarea expresiei- la apel, ordinea de evaluare a parametrilor nu este definită; de exemplu, la apelul test(2-3,2+3) nu

ştim dacă înainte se efectuează scăderea sau adunarea

2.2 Declararea variabilelor

2.2.1 Noţiuni generale

Până în prezent am declarat variabile doar în corpul funcţiilor, inclusiv în cel al funcţiei main(). Variabilele astfel declarate se numesc locale. Sistemul de operare alocă fiecărui program trei zone distincte în memoria internă a calculatorului, în care se găsesc memorate variabilele programului. Harta simplificată a memoriei interne este prezentată în continuare:

segment de datesegment de stivă

heap

Segmentul de date este folosit pentru stocarea codului programului aflat în execuţie şi pentru variabilele care sunt folosite de către acesta pe toată durata execuţiei. Segmentul de stivă este utilizat pentru a realiza transferul parametrilor la apelul subprogramelor şi pentru a controla execuţia programului în cazul lucrului cu subprograme. Zona heap se numeşte şi zonă de accumulare a variabilelor dinamice şi se foloseşte pentru alocarea variabilelor dinamice, create la cererea expresă a programatorului, în timpul execuţiei unui program.

De asemenea, în limbajul C, există posibilitatea ca variabilele să fie memorate într-un anumit registru al microprocesorului. În acest caz, timpul de acces la astfel de variabile este foarte mic, deci se pot obţine programe optimizate. Numărul variabilelor care pot fi memorate în regiştrii interni este însă redus.

În general o variabilă se caracterizează prin patru atribute şi anume:- clasa de memorare- vizibilitatea- durata de viaţă- tipul variabilei, singurul studiat până în acest moment

Clasa de memorare precizează locul unde este memorată variabila respectivă. O variabilă poate fi memorată în segmentul de date, în cel de stivă, în heap sau într-un registru al microprocesorului.

Vizibilitatea precizează liniile textului sursă din care variabila respectivă poate fi accesată. Astfel avem:- vizibilitate la nivel de bloc (instrucţiune compusă)- vizibilitate la nivel de fişier, în cazul în care programul ocupă doar un singur fişier sursă (singurul

caz tratat momentan)- vizibilitate la nivel de clasă, legată de programarea orientată pe obiecte, facilitate specifică în C++

Durata de viaţă reprezintă timpul în care variabila respectivă are alocat spaţiu în memoria internă (deci există efectiv). Astfel avem:- durată statică, conform căreia variabila are alocat spaţiu în tot timpul execuţiei programului- durată locală, conform căreia variabila are alocat spaţiu în timpul în care se execută înstrucţiunile

blocului respectiv (blocul care conţine declaraţia variabilei)- durată dinamică, caz în care alocarea şi dealocarea spaţiului necesar variabilei respective se face

explicit de către programator, în timpul execuţiei programului, prin folosirea unor operatori şi funcţii speciale (de exemplu, new, malloc() etc.)

În limbajul C/C++ variabilele pot fi împărţite în trei mari categorii: locale, globale şi dinamice.

2.2.2 Variabile globale

Aceste variabile se declară în afara corpului oricărei funcţii, ca în exemplul următor:#include<stdio.h>int a;void t()

3

Page 4: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

{a=3;printf(“%d”,a);

}int b;void main(){

b=4;printf(“%d”,b);t();

}Variabilele a şi b sunt globale. Ele pot fi utilizate de toate funcţiile care urmează în textul sursă

declaraţiei variabilei respective. Deoarece pot fi utilizate, deci implicit şi modificate, de toate funcţiile care succed momentul declaraţiei, aceste variabile se numesc globale.

Observaţie: La declarare, variabilele globale sunt iniţializate de către compilator cu 0.

Atributele variabilelor globale sunt:- clasa de memorare este segmentul de date- vizibilitatea: sunt vizibile în toate funcţiile care le succed; în exemplul anterior, a poate fi acccesată

din corpul oricărei funcţii, în timp ce variabila b poate fi accesată numai din funcţia main- durata de viaţă este statică, adică au spaţiu de memorie rezervat în tot timpul execuţiei programului

2.2.3 Variabile locale

Aceste variabile sunt declarate în corpul funcţiilor, mai precis, pot fi declarate în orice bloc (instrucţiune compusă) al acestora.

Observaţie: Variabilele declarate în funcţia main() sunt tot variabile locale, deci sunt vizibile numai în această funcţie.

În exemplul următor, variabila a este declarată în corpul funcţiei t(), iar variabila b este declarată în corpul funcţiei main():

void t(){

int a=3;printf(“%d”,a+2);

}void main(){

int b=4;printf(“%d”,b--);

}

Atributele variabilelor locale sunt:- clasa de memorare este, implicit, segmentul de stivă. Există posibilitatea ca acestea să fie alocate

şi în registrele microprocesorului, caz în care declaraţia lor trebuie precedată de cuvântul cheie register, ca în exemplul următor: register int b=4;

- vizibilitatea variabilelor locale este la nivelul blocului în care au fost declarate.- durata de viaţă a variabilelor locale este atât timp cât durează execuţia blocului respectiv, adică

este locală

Observaţie: Variabilele locale nu sunt iniţializate implicit de către compilator cu 0, această sarcină revenind programatorului. În cazul în care iniţializarea este omisă, ele conţin o valoare oarecare numită valoare reziduală care poate duce la rezultate eronate.

Exemplul 1: În funcţia următoare am declarat două variabile de tip int, numite b şi c. Variabila b este vizibilă la nivelul funcţiei, dar variabila c este vizibilă doar la nivelul blocului în care a fost declarată. Ambele sunt variabile locale alocate pe segmentul de stivă.

void func(){

int b=7; // vizibila in toata functia{

4

Page 5: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

int c=9; // vizibila numai in acest bloc (instr.compusa)printf(“%d %d”,b,c);

}}

Exemplul 2: În programul următor am declarat trei variabile, toate numite a. Una este globală, iar două sunt locale, dar declarate în blocuri diferite.

#include<stdio.h>int a; // variabila globala,vizibila in orice punct din programvoid func(){

int a=4; // variabila locala,vizibila in toata functia {

int a=3; // variabila locala,vizibila numai in acest blocprintf(“%d”,a); // tipareste a=3a+=2;

}printf(“%d”,a); // tipareste a=4a++;

}void main(){

a=5; // refera variabila globala afunc();printf(“%d”,a); // tipareste a=5

}

Observa ţie : În cazul în care, într-un anumit bloc sunt vizibile (se pot accesa) mai multe variabile cu acelaşi nume, dar cu domenii de vizibilitate diferite, se accesează variabila cu vizibilitatea cea mai mică. Este cazul variabilei a din blocul interior funcţiei func() pentru care se consideră cea mai mică vizibilitate (cea de bloc) şi se tipăreşte valoarea 3.

Observaţie: Durata de viaţă a unei variabile locale poate fi modificată folosind atributul static, astfel încât, deşi respectiva variabilă nu este recunoscută în afara funcţiei, ea nu moare adată cu revenire dintr-un apel. Cu alte cuvinte, apeluri succesive vor regăsi, fiecare, valoarea lăsată de apelul anterior.Exemplu: În urma execuţiei programului următor, variabila m va avea valoarea 3, deoarece cele două apeluri succesive ale funcţiei f() vor returna valorile 1, respectiv 2, variabila locală a având atributul static.

#include<stdio.h>int f(){

static int a=1;return a++;

}void main(){

int m;m=f()+f();printf(“%d”,m);

}

2.3 Transmiterea parametrilor

Parametrii care se găsesc în antetul funcţiei se numesc parametri formali, iar cei care se găsesc în instrucţiunea de apel se numesc parametri efectivi.Exemplu: Funcţia următoare calculează suma a două numere naturale.

#include<stdio.h>int suma(int a,int b){

return a+b;}void main()

5

Page 6: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

{int c=4,d=3;printf(“%d\n”,suma(2,3));printf(“%d\n”,suma(2+7,3-1*2);printf(“%d\n”,suma(c,d);printf(“%d\n”,suma(1.9,3.3);

}Parametrii formali ai funcţiei sunt a şi b. Funcţia este apelată de mai multe ori. Parametrii

efectivi sunt pe rând:- 2, 3- 2+7, 3-1*2- c, d- 1.9, 3.3 După fiecare apel al funcţiei se tipăreşte suma obţinută. Între parametrii formali şi cei efectivi trebuie să existe o anumită concordanţă care este descrisă prin regulile următoare:- Numărul parametrilor formali trebuie să coincidă cu numărul parametrilor efectivi. La această regulă

există şi excepţii. În exemplul dat numărul parametrilor formali este 2, iar cel al parametrilor efectivi tot 2.

- Tipul parametrilor efectivi trebuie să coincidă cu tipul parametrilor formali sau tipul parametrilor efectivi să poată fi convertit implicit către tipul parametrilor formali. La apelul suma(2,3); parametrii efectivi sunt constante de tip întreg şi coincid cu tipul parametrilor formali. La apelul suma(2+7,3-1*2); parametrii efectivi sunt expresii de tip întreg. În acest caz, înainte de apel se evaluează expresiile respective. La apelul suma(c,d); parametrii formali sunt variabile de tip întreg date prin valorile lor. La apelul suma(1.9,3.3); parametrii efectivi sunt constante de tip real care se convertesc la tipul int prin trunchiere şi suma calculată este 1+3=4.

Observaţie: Nu este obligatoriu ca numele parametrilor formali să coincidă cu numele parametrilor efectivi şi, în multe situaţii nici nu este recomandabil, pentru a evita confuziile.

În momentul lansării în execuţie a unei funcţii (la apel), parametrii efectivi se transmit funcţiei apelate după următoarele reguli:- Pentru memorarea parametrilor efectivi subprogramele folosesc segmentul de stivă, întocmai ca

pentru variabilele locale.- Memorarea parametrilor efectivi transmişi se face în ordinea în care aceştia figurează în antet, de

la stânga spre dreapta.- În cadrul subprogramului, parametrii transmişi în momentul apelului şi memoraţi pe stivă sunt

variabile. Numele lor este cel din lista parametrilor formali. Aceste variabile se comportă ca nişte variabile locale subprogramului, deci nu sunt vizibile în afara funcţiei şi există cât timp funcţia este în execuţie.

- La revenirea în blocul apelant, conţinutul variabilelor memorate pe stivă se pierde, durata de viaţă a variabilelor locale fiind locală.

Există două mecanisme de transmitere a parametrilor, transmiterea prin valoare şi transmiterea prin referinţă.

2.3.1 Transmiterea prin valoare

Se utilizează atunci când suntem interesaţi ca subprogramul să lucreze cu acea valoare, dar să nu poată modifica parametrul efectiv corespunzător din blocul apelator. Se pot transmite prin valoare:

1. Valorile reţinute de variabile. În acest caz parametrii efectivi trebuie să fie numele variabilelor. Exemplu:

#include<stdio.h>void test(int n){

n++;printf(“n=%d\n”,n); // tipareste n=8

}void main(){

int n=7;test(n);printf(“n=%d\n”,n); // tipareste n=7

}

6

Page 7: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

Parametrul n este transmis prin valoare. În funcţia main() acest parametru este iniţializat cu valoarea 7. Când apelăm funcţia test(), se rezervă spaţiu pe stivă, spaţiu care are numele parametrului formal (în acest caz, tot n) şi care este iniţializat cu valoarea memorată de variabila n a programului principal. Altfel spus, pe stivă se copie valoarea parametrului efectiv de apel. În funcţie, variabila n (care este locală acestei funcţii) este incrementată şi devine 8, valoare care va fi tipărită. La ieşirea din funcţie, variabila n din stivă se pierde, adică nu mai are spaţiu alocat, prin urmare valoarea 8 este pierdută. În main() se tipăreşte valoarea variabilei n (locală acesteia) care are valoarea 7.

Pentru exemplul anterior, conţinutul stivei, în momentul apelului şi după execuţia funcţiei test(), este următorul:

Se observă că, în momentul apelului funcţiei test(), pe stivă sunt alocate două variabile cu acelaşi nume n. Prima variabilă este variabila locală funcţiei main() care se salvează pe stivă în momentul apelului pentru a putea reface contextul funcţiei main() după încheierea apelului. A doua variabilă este parametrul formal tip valoare n, vizibil numai în funcţia test() şi iniţializat în momentul apelului cu valoarea 7. Indiferent ce valori primeşte acest n în corpul funcţiei test(), după încheierea execuţiei acestei funcţii, spaţiul său este dealocat din stivă, adică variabila respectivă este distrusă. Din acest motiv, după execuţia funcţiei test(), conţinutul stivei este cel din dreapta. Se reface contextul din care s-a lansat apelul funcţiei test(), adică se recuperează din stivă valoarea variabilei locale n=7 şi adresa de revenire, adică adresa instrucţiunii printf.

2. Expresii. În acest caz, parametrii efectivi sunt expresii, care pot conţine şi funcţii şi care mai întâi se evaluează. Exemplu:

#include<stdio.h>#include<math.h>void test(int n){

printf(“n=%d\n”,n);}void main(){

test(5); // se va tipari 5test(7+(int)sqrt(45)); // se va tipari 13

}În funcţie se crează o variabilă numită n, reţinută pe stivă, care la primul apel va primi valoarea 5 şi la al doilea apel valoarea 13. La ieşirea din funcţie conţinutul acestei variabile se pierde.

Transmiterea parametrilor prin valoare se utilizează când nu dorim ca subprogramul apelat să poată modifica parametrii efectivi de apel. Acesta este modul implicit de transmitere a parametrilor în limbajul C. Dacă nu ar exista decât transmiterea prin valoare, ar fi imposibil să modificăm valoarea anumitor valori care sunt declarate în blocul apelator. Acest lucru este totuşi posibil dacă lucrăm cu variabile de tip pointer, care, aşa cum ştim deja, conţin adresele de memorie ale altor variabile din program. Având acces la locaţia de memorie a unei variabile (prin adresa ei), îi putem desigur modifica conţinutul. Funcţia următoare realizează interschimbarea valorilor a două variabile din programul principal. Pentru a putea face acest lucru, funcţia primeşte adresele de memorie ale celor două variabile, adică doi pointeri.

#include<stdio.h>void schimba(int *x,int *y){

int aux;

7

n=7, parametru valoare de apel, local funcţiei

testn=7 , var. locală funcţiei

main()adresa de revenire din

funcţia test

în momentul apelului

n=7 , var. locală funcţiei main()

adresa de revenire din funcţia test

după execuţia funcţiei test

adresa(n)

Page 8: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

aux=*x;*x=*y;*y=aux;

}void main(){

int a=7, b=12;schimba(&a,&b);printf(“a=%d\t b=%d”,a,b); // tipareste a=12, b=7

}Se observă că parametrii formali sunt doi pointeri la întreg care în momentul apelului primesc ca valori adresa variabilei a, respectiv b (obţinute prin aplicarea operatorului &). În limbajul C acesta este singurul mod prin care se pot transmite parametrii prin adresă, deci modifica de către un subprogram apelat.

Pentru exemplul anterior, evoluţia stivei este:

În cazul transmiterii prin adresă, pe stiva procesorului se depun, pe lângă adresa de revenire şi valorile variabilelor locale funcţiei main(), necesare pentru a reface contextul din care s-a făcut apelul, şi adresele de memorie ale parametrilor efectivi corespunzători. Deşi pointerii x şi y sunt locali funcţiei schimbă() şi sunt dealocaţi de pe stivă în momentul în care execuţia acestei funcţii se încheie, orice modificare a locaţiilor de memorie adresate de aceşti pointeri se păstrează şi după încheierea apelului. Din acest motiv, după execuţia funcţiei schimbă(), conţinutul stivei este cel din dreapta. Valorile variabilelor a şi b, locale funcţiei main(), au fost modificate în timpul execuţiei funcţiei schimba() care a avut acces la adresele lor de memorie. La revenirea din funcţie, se recuperează din stivă noile valori ale variabilelor a şi b, adresa instrucţiunii printf şi se continuă execuţia funcţiei main().

Observaţie: Există o excepţie de această regulă, şi anume, când parametrul este un tablou. În C, numele unui tablou este un pointer către componentele tabloului. Când transmitem prin valoare un tablou, ceea ce primeşte subprogramul este un pointer către elementele acestuia, adică adresa de început a tabloului în memorie. Având acces la această adresă, subprogramul poate modifica valorile reţinute în tablou. Practic, în cazul tablourilor, transmiterea prin valoare devine transmitere prin adresă.

2.3.2 Transmiterea tablourilor către funcţii

Fie următorul fragment de program:void main(){

int a[10];......func(a); // apelul unei functii cu parametrul a.....

}Dacă o funcţie primeşte un tablou unidimensional, atunci parametrul formal al acesteia poate fi declarat în trei moduri: ca pointer, ca tablou dimensionat sau ca tabloul nedimensionat. De exemplu, putem declara funcţia func() în următoarele moduri:

void func(int *x) // parametru formal de tip pointer{

8

y=&b, parametru formal de tip pointer, local funcţiei schimba()x=&a, parametru formal de tip pointer, local funcţiei schimba()b=12, variabilă locală funcţiei main()a=7, variabilă locală funcţiei main()adresa de revenire din funcţia schimba()

în momentul apelului funcţiei schimba()

b=7, variabilă locală funcţiei main()

a=12, variabilă locală funcţiei main()

adresa de revenire din funcţia schimba()

după execuţia funcţiei schimba()

adresa(a)

adresa(b)

Page 9: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

………}

sau ca:void func(int x[10]) // tablou dimensionat{

…..}

sau ca:void func(int x[]) // tablou nedimensionat{

……}

Toate cele trei metode de declarare determină rezultate asemănătoare, deoarece indică compilatorului că urmează să fie primit un pointer la întreg. Dimensiunea tabloului nu contează din punctul de vedere al funcţiei, deoarece C nu verifică depăşirea limitelor unui tablou. Din punct de vedere funcţional, declaraţia:

void func(int x[32]){

......}

este de ademenea funcţională, deoarece compilatorul C generează un cod care cere funcţiei func() să primească un pointer la întreg, fără a crea efectiv un tablou cu 32 de elemente.

Metoda de transmitere este aceeaşi şi când un tablou bidimensional este folosit ca argument al unei funcţii. În acest caz se transmite efectiv numai pointerul către primul element. Cu toate acestea, parametrul care primeşte un tablou bidimensional trebuie să definească măcar dimensiunea din dreapta a tabloului. Aceasta deoarece compilatorul C trebuie să cunoască lungimea fiecărui rând pentru a aplica corect indicii fiecărui termen al matricii. De exemplu, o funcţie care primeşte o matrice de 10*10 întregi va fi declarată astfel:

void func(int x[][10]){

....}

Se poate preciza şi dimensiunea din stânga, dar nu este absolut necesar.

2.3.3 Transmiterea structurilor către funcţii

Când membrul unei structuri este transmis unei funcţii, ceea ce se transmite funcţiei este de fapt valoarea acelui membru. Ca atare, se transmite doar o variabilă. Fie structura următoare:

struct info{

char x;int y;float z;char s[10];

}set;Iată exemple de transmitere ale fiecărui membru către o funcţie:

func(set.x); // transmite valoarea caracter a lui xfunc(set.y); // transmite val. intreaga a lui yfunc(set.z); // transmite val. virgula mobila a lui zfunc(set.s); // transmite adresa sirului sfunc(set.s[3]); // transmite val. tip caracter a lui s[3]

Dacă dorim să transmitem adresa unui anumit membru al unei structuri, inserăm operatorul & înaintea numelui structurii.

func(&set.x); // transmite adresa caracterului xfunc(&set.y); // transmite adresa intreagului yfunc(&set.z); // transmite adresa variabilei float zfunc(set.s); // transmite adresa sirului sfunc(&set.s[3]); // transmite adresa caracterului s[3]

Când o structură este folosită ca argument al unei funcţii, se va efectua transmiterea întregii structuri, folosind metoda standard a apelului prin valoarea. Aceasta înseamnă că structura nu va putea fi modificată. Tipul structurii trebuie să coincidă cu tipul parametrului formal care primeşte structura. Din

9

Page 10: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

acest motiv, declaraţia tipului structurii trebuie să aibă caracter global, pentru a putea fi folosită de către toate funcţiile din program, ca în exemplul următor:

#include<stdio.h>struct data{

int a,b;char ch;

}; // declaratie globala de tipvoid func(data x) // foloseste tipul global{

printf(“%d”,x.a);}void main(){

data arg; // foloseste tipul globalarg.a=157;func(arg);

} Deoarece limbajul C permite declararea pointerilor către structuri, putem modifica un argument de tip structură folosind mecanismul transmiterii prin adresă, cu ajutorul pointerilor ca în exemplul următor:

#include<stdio.h>struct ora{

int ore;int minute;int secunde;

}; // declaratie globalavoid func(ora *p) // pointer la structura globala{

…………….}void main(){

ora arg;…....func(&arg); // transmite adresa structurii

}

Observaţie: Poate fi tip al unei funcţii orice tip de dată cu excepţia tablourilor. Dacă ţinem neapărat, există posibilitatea ca funcţia să întoarcă tablouri, dacă acestea sunt înglobate în tipuri declarate cu struct, aşa cum se arată în exemplul următor:

#include<stdio.h>struct mat{

float matrice[6][8];};mat citire(int m,int n){

mat a;int i,j;for(i=0;i<m;i++) for(j=0;j<n;j++) scanf(“%f”,&a.matrice[i][j]);return a;

}void main(){

int i,j;mat mtr=citire(3,2);for(i=0;i<3;i++){

for(j=0;j<2;j++) printf(“%6.2f”,mtr.matrice[i][j]);printf(“\n”);

}}

10

Page 11: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

2.3.4 Transmiterea prin referinţă

În limbajul C++ există un tip special de date care permite ca o variabilă să fie identificată prin mai multe nume, tip numit referinţă. Aparent, programul lucrează cu mai multe variabile, dar de fapt toţi identificatorii respectivi referă aceeaşi locaţie de memorie. Declararea unei variabile de tip referinţă se face cu sintaxa:

tip& nume variabilă=valoare de iniţializare;În programul următor, variabila x este o referinţă pentru variabila y. Ele au aceeaşi valoare şi aceeaşi adresă de memorie, dar poartă nume diferite.

#include<stdio.h>void main(){

int x=7;int& y=x; // sau int x=7, &y=a;printf(“x=%d si are adresa %p\n”,x,&x);printf(“y=%d si are adresa %p\n”,y,&y);

}În cazul subprogramelor, parametrii sunt transmişi prin referinţă atunci când ne interesează ca

la revenirea din subprogram variabila transmisă să reţină valoarea stabilită în timpul execuţiei subprogramului.

În cazul transmiterii prin referinţă parametrii formali trebuie să fie referinţe la variabile. În acest caz subprogramul reţine pe stivă adresa variabilei transmisă prin referinţă şi având acces la adresa de memorie a parametrului efectiv corespunzător, îl poate modifica.Exemplu: Programul următor interschimbă valorile a două variabile transmise prin referinţă.

#include<stdio.h>void schimba(int &a, int &b){

int aux=a; a=b; b=aux;}void main(){

int x=7, y=5;schimba(x,y);printf(x=%d\ty=%d\n”,x,y);

}

Conclu zii : a) În momentul în care într-un subprogram este întâlnită instrucţiunea de apel a unui alt subprogram, controlul execuţiei este cedat subprogramului apelat şi pe stivă se depun, în ordine:- adresa de revenire din subprogramul apelat- valorile variabilelor locale subprogramului apelator- valorile parametrilor transmişi prin valoare- adresele parametrilor transmişi prin referinţăb) Revenirea din subprogramul apelat se face fie la întâlnirea instrucţiunii return (cazul funcţiilor care returnează un rezultat de un anumit tip), fie la întâlnirea acoladei care încheie instrucţiunea compusă a subprogramului apelat (cazul funcţiilor de tip void)c) La încheierea execuţiei subprogramului apelat se recuperează din stivă, în ordine, valorile variabilelor locale subprogramului apelator şi adresa de revenire, adică se reface contextul din care s-a făcut apelul.

2.4 Definirea şi declararea unui subprogram

Deşi aparent asemănătoare, cele două noţiuni diferă. A defini un subprogram, înseamnă a-l scrie efectiv (antet şi instrucţiune compusă). Este foarte important locul în care se defineşte un subprogram. A declara un subprogram, înseamnă a-l anunţa. Un subprogram nedeclarat nu poate fi folosit. Definiţia unui subprogram ţine loc şi de declaraţie.Exemplu: Programul următor conţine două funcţii f1 şi f2. Definiţiile ambelor funcţii se găsesc înaintea funcţiei main() şi din acest motiv ele pot fi apelate din main(). Definiţia funcţiei f1 este înaintea definiţiei

11

Page 12: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

lui f2, deci funcţia f1 poate fi apelată din f2, în schimb, din f1 nu poate fi apelată f2 pentru că declaraţia acesteia îi succede lui f1.

#include<stdio.h>void f1(){

printf(“functia f1\n”);}void f2(){

f1();printf(“functia f2\n”);

}void main(){

f1(); f2();

}Dacă dorim ca f1 să poată apela funcţia f2 folosim prototipul funcţiei care este antetul acesteia urmat de punct şi virgulă. Prototipul are rolul de a declara o funcţie şi nu conţine definiţia acesteia.Exemplu:

#include<stdio.h>void f1(); // prototip f1void s2(); // prototip f2void main(){

f1();}void f1() // definitia lui f1{

f2();printf(“functia f1\n”);

}void f2() // definitia lui f2{

f1();printf(“functia f2\n”);

}

Observaţie: În prototipul unei funcţii se poate omite numele parametrilor formali, precizându-se numai tipul acestora. Spre exemplu, este corect un prototip de forma float func(int, int&); care declară o funcţie cu rezultat de tip float si doi parametri, unul valoare de tip int şi unul referinţă la int.

În C++ este o practică uzuală să se scrie mai întâi prototipurile tuturor funcţiilor utilizate în program, fără funcţia main(), iar după funcţia main() să fie definite aceste funcţii. În acest fel, orice funcţie, mai puţin main(), poate fi apelată din oricare alta.

2.5 Funcţii cu număr variabil de argumente

O facilitate importantă a limbajului C este posibilitatea utilizării funcţiilor cu un număr variabil de argumente. Este obligatoriu ca cel puţin primul parametru să apară în lista parametrilor formali. Pentru parametrii variabili antetul va conţine “…”. Parametrii efectivi sunt depuşi, unul după altul, în ordinea declarării în antet, în stivă. Dacă la adresa primului parametru adunăm 1, obţinem adresa următorului parametru şi aşa mai departe. De regulă, parametrii ficşi conţin informaţii despre cei variabili (numărul lor, în unele cazuri tipul lor).

În exemplul următor, funcţia f are un număr neprecizat de parametri, aspect semnalat prin prezenţa celor trei puncte după parametrul fix n în antetul funcţiei. Accesarea parametrilor actuali în momentul apelului se bazează pe faptul că parametrii se memorează la adrese consecutive în stivă. Astfel, se pleacă de la adresa ultimului parametru fix, în acest exemplu &n. Valoarea &n+1 reprezintă adresa următorului parametru, adică a primului parametru variabil, &n+2 este adresa celui de-al doilea parametru variabil etc. În felul acesta, valorile care vor apărea la apel după parametrii ficşi vor putea fi

12

Page 13: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

accesaţi printr-un calcul obişnuit de adrese şi funcţia va returna maximul dintre elementele vectorului x, adică 23.

#include<stdio.h>int f(int n,…){

int *x=&n+1, m=x[0], j;for(j=1;j<n;j++) x[j]>m? m=x[j]: m=m;return m;

}void main(){

printf(“%d”,f(4,12,11,23,2);}

Un alt aspect important referitor la funcţiile limbajului C este posibilitatea de a iniţializa parametrii formali ai unei funcţii direct în antetul acesteia. În acestă situaţii, la apelul funcţiei pot să lipsească unul sau mai mulţi parametri actuali, chiar toţi parametrii. În cazul în care la apel lipseşte un parametru actual, compilatorul va folosi în funcţie valoarea cu care a fost iniţializat la declarare parametrul formal aferent.Exemplu: Programul următor este corect şi va afişa valorile m=6, n=15, p=34 şi q=52.

#include<stdio.h>int f(int a=1,int b=2,int c=3){

return a+b+c;}void main(){ int m,n,p,q; m=f(); n=f(10); p=f(12,19); q=f(11,23,18); printf(“%5d%5d%5d%5d”,m,n,p,q);}

2.6 Folosirea funcţiilor ca parametri de apel

Limbajul C permite transmiterea funcţiilor ca parametri de apel pentru alte funcţii. Numele funcţiei este dat ca parametru prin intermediul unui pointer către funcţie. Considerăm programul următor:

#include<stdio.h>#include<math.h>float ma(int x,int y){

return (x+y)/2.;}float mg(int x,int y){

return sqrt(x*y);}void calcul(int x,int y,float (*f)(int,int)){

printf(“%.1f”,f(x,y));}void main(){

int a,b;scanf(“%d %d”,&a,&b);if(a>=b) calcul(a,b,ma);

13

Page 14: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

else if(a>0 && b>0) calcul(a,b,mg);}

În acest exemplu, funcţia calcul are un antet mai deosebit. Primii doi parametri sunt doi întregi x şi y. Al treilea parametru, float (*f)(int,int) , reprezintă un pointer către o funcţie f. Această funcţie f are la rândul ei doi parametri de tipul int. Nu este necesar să se precizeze numele acestor parametri, ci doar tipul lor. Instrucţiunea printf(“%.1f”,f(x,y)); din corpul funcţiei f afişează valoarea întoarsă de funcţie. În funcţia main() se fac apelurile: calcul(a,b,ma);, respectiv calcul(a,b,mg);. La apel, al treilea parametru din antet (pointerul la funcţie), este înlocuit cu numele unei funcţii, ma, respectiv, mg. Aceste funcţii au fost scrise anterior. Spre exemplu, dacă se citesc valorile a=7 şi b=6, identificatorul f este înlocuit cu ma, se calculează media aritmetică a parametrilor x şi y şi se tipăreşte valoarea 6.5. Dacă se citeşte a=2 şi b=8, identificatorul f se înlocuieşte cu mg, se calculează media geometrică a parametrilor x şi y şi se tipăreşte valoarea 4.

3. Exemple de aplicaţii care folosesc subprograme

Exemplul 1: Se citesc două numere întregi m şi n. Să se tipărescă numerele prime aflate în intervalul [m,n].

Pentru a verifica primalitatea unui număr din intervalul dat vom folosi o funcţie care returnează 1 dacă numărul respectiv este prim, şi 0 în caz contrar.

#include<stdio.h>#include<math.h>int prim(int x){

int i;for(i=2;i<=sqrt(x);i++)

if(!(x%i)) return 0;return 1;

}void main(){

int m,n,i;printf("m,n="); scanf("%d %d",&m,&n);printf(" numerele prime din intervalul [%d,%d] sunt:\n",m,n);for(i=m;i<=n;i++)

if(prim(i)) printf("%6d",i);printf("\n");

}

Exemplul 2: Se citeşte un vector cu n componente numere întregi. Se cere să se tipărescă cmmdc al elementelor vectorului.

Pentru citirea vectorului vom scrie o funcţie care returnează (prin referinţă) numărul n al elementelor şi elementele propriu-zise ale vectorului, citite de la tastatură. Pentru determinarea cmmdc al elementelor vectorului, vom scrie o funcţie care calculează şi returnează cmmdc a două numere întregi a şi b, şi pe care o vom folosi într-o buclă pentru elementele vectorului.

#include<stdio.h>void citire(int& n, int x[]);int cmmdc(int a,int b);void main(){

int i,n,v[50],cm;citire(n,v);cm=cmmdc(v[0],v[1]);for(i=2;i<n;i++)

cm=cmmdc(cm,v[i]);printf("cmmdc=%d\n",cm);

}void citire(int& n, int x[]){

14

Page 15: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

int i;printf("n="); scanf("%d",&n);for(i=0;i<n;i++){

printf("el[%d]=",i);scanf("%d",&x[i]);

}}int cmmdc(int a,int b){

while(a!=b)if(a>b)

a-=b;else

b-=a;return a;

}

Exemplul 3: Se citesc două numere naturale m şi n, m<n. Să se tipărescă toate numerele palindromice aflate în intervalul [m,n]. Un număr este palindromic dacă citit de la dreapta la stânga şi de la stânga la dreapta reprezintă aceeaşi valoare.

Pentru a verifica dacă un număr natural x este palindrom, vom scrie o funcţie care vareturna 1 în caz afirmativ şi 0 în caz contrar. Funcţia va construi numărul cu cifrele în ordine inversă şi îl va compara cu parametrul efectiv primit.

#include<stdio.h>int palindrom(int x){

int inv=0,t=x;while(x){

inv=inv*10+x%10;x/=10;

}return inv==t;

}void main(){

int m,n,i;printf("m,n="); scanf("%d %d",&m,&n);printf("\t Numere palindromice din intervalul [%d,%d]:\n",m,n);for(i=m;i<=n;i++)

if(palindrom(i)) printf("%d ",i);printf("\n");

}

Exemplul 4: Să se scrie o funcţie care citeşte o matrice cu elemente numere întregi dintr-un fişier text cu numele f.in. Pe prima linie a fişierului se găsesc două valori separate prin spaţii care reprezintă numărul de linii şi, respectiv, de coloane (m şi n). Următoarele m linii ale fişierului conţin, în ordine, elementele aflate pe fiecare linie a matricei. Matricea astfel obţinută va fi tipărită în main().

Funcţia de citire a matricii va primi ca parametri de intrare referinţe la variabilele m şi n şi adresa tabloului citit, care are cel mult 10 linii şi 10 coloane.

#include<stdio.h>void citire(int& m,int& n,int a[10][10]){

int i,j;FILE *f;f=fopen("f.in","rt");fscanf(f,"%d %d",&m,&n);for(i=0;i<m;i++)

for(j=0;j<n;j++)fscanf(f,"%d",&a[i][j]);

fclose(f);}

15

Page 16: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

void main()

{int m,n,a[10][10],i,j;citire(m,n,a);printf("\n\t Matricea citita este:\n");for(i=0;i<m;i++){

for(j=0;j<n;j++) printf("%4d",a[i][j]);printf("\n");

}}

4. Exerciţii şi teste grilă

1. Precizaţi care dintre următoarele linii de program reprezintă corect,dpdv sintactic, lista de parametri şi valoarea returnată de o funcţie cu numele test, dacă cerem ca parametrii formali să fie două variabile de tip întreg, x şi y, şi o variabilă de tip real z, şi să returneze un rezultat întreg.

a) int test(int x,y,float z)b) int test(int x,y;float z)c) int test(int x,int y,float z)d) test(int x;int y;float z) inte) test(int x,int y,float z) int

2. Care dintre afirmaţiile de mai jos sunt adevărate?

a) la apelul unei funcţii, se produce înlocuirea parametrilor formali cu parametrii actuali

b) tipul parametrilor daţi la apelul unei funcţii trebuie să coincidă sau să fie compatibil cu tipul celor definiţi în antetul funcţiei

c) la apelul unei funcţii, se salvează pe stivă adresa de revenire, precum şi variabilele locale şi parametrii modulului apelat

d) orice funcţie trebuie să aibă întotdeauna cel puţin un parametru

e) nici una dintre afirmaţiile de mai sus

3. Se consideră un vector v care poate memora maxim 25 de numere întregi, din care folosim efectiv numai primele n elemente. Scrieţi antetul unei funcţii numită calcul, care primeşte drept parametri vectorul v împreună cu numărul său de elemente şi nu returnează nimic.

a) void calcul(int v[n],25)b) void calcul(int v[25],int n)c) void calcul(int v[],int n)d) void calcul(int v[],n)e) void calcul(int v,int n)

4. Considerăm o funcţie demo, de tip void pentru care se definesc ca parametri trei

variabile întregi. Cum realizăm apelul funcţiei, astfel încât la apel să dăm ca parametri variabilele întregi a,b şi c?

a) demo(int a,int b,int c);b) demo(int a;int b;int c);c) demo(a,b,c);d) demo(a;b;c);e) demo(int a,b,c);

5. Scrieţi o funcţie D care primeşte ca parametru un număr întreg a şi returnează valoarea lui a+2.

a) int D(int a);{D=(a+2);}b) int D(int a){D=a+2;}c) int D(int a);{return(a+2);}d) int D(int a){return a+2;}e) nici una dintre variantele

anteriare

6. Care dintre afirmaţiile de mai jos sunt adevărate?

a) parametrii definiţi în antetul unei funcţii se numesc actuali, iar cei care apar la apelul funcţiei se numesc formali

b) valoarea returnată de către o funcţie poate fi transmisă ca parametru altei funcţii

c) variabilele de tip tablou nu se pot transmite ca parametri funcţiilor

d) variabilele globale sunt cunoscute pe tot parcursul programului în care au fost declarate în toate modulele care urmează declaraţiei

e) corpul unei funcţii trebuie cuprins între “{“ şi “}”, numai dacă este alcătuit din cel puţin două instrucţiuni distincte

7. Avantajele utilizării funcţiilor într-un program sunt:

a) se poate obţine o economisire a spaţiului de memorie rezervat variabilelor folosite în cadrul programului

16

Page 17: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

b) o viteză mai mare în execuţia programului

c) posibilitatea de a executa de mai multe ori instrucţiunile cuprinse într-o funcţie

d) un program care conţine funcţii poate fi urmărit şi corectat mai uşor

e) nici unul dintre avantajele de mai sus8. Deduceţi şirul de valori care se afişează în urma execuţiei programului de mai jos:#include<stdio.h>int i,j,k;int test(int x,int y){

return (x-y);}void calcul(int p,int q){

int u,v;u=p-i; v=q+j;i=test(u,q);j=test(v,p);

}void main(){

i=2; j=3;calcul(i,,j);printf(“%3d %3d”,i,j);calcul(j,i);printf(“%3d %3d\n”,i,j);

}a) 2 3 2 3 b) 3 2 3 2c) 2 3 –3 4 d) –3 4 4 –3e) –3 4 10 –3

9. Câte erori va produce execţia programului următor?#include<stdio.h>#include<math.h>int calcul(int p,int q){

return(sqrt(p*q)); }void main(){

printf(“%d”,calcul(1,2));}

a) una b) două c) treid) patru e) nici una

10. Considerăm programul următor:#include<stdio.h>int m;void p(int& c){

int b;b=3*m; c=b+2; m+=3;printf(“%6d”,m); // (5)printf(“%6d %6d\n”,b,c);//(6)

}void main(){

m=3; p(m); // (1)p(3); // (2)

printf(“%6d”,m); // (3)printf(“%6d %6d”,b,c); // (4)

}Care dintre următoarele afirmaţii sunt adevărate?

a) în cursul execuţiei primului apel al funcţiei p, cel din linia (1), se vor afişa, în ordine, valorile 14,9,14 (liniile (5) şi (6))

b) cele două apeluri ale funcţiei p, din liniile (1) şi (2), sunt corecte şi echivalente (produc acelaşi rezultat în orice situaţie)

c) linia (3) afişează valoarea 14d) linia (4) afişează valorile 9 şi 14e) la fiecare execuţie a funcţiei p, se

salvează pe stivă valoarea lui c

11. Ce valori va afişa programul următor?#include<stdio.h>int n,m;void t(int n,int& m){

n+=2; m--;}void main(){

n=2; m=5;t(n,m);printf(“%d %d”,n,m);n=10; m=20;t(n,m);printf(“%d %d”,n,m);

}a) 4 4 12 19 b) 4 5 12 20c) 2 4 10 19 d) 2 5 10 20e) 7 2 22 10

12. Precizaţi ce se va afişa în urma execuţiei programului de mai jos:#include<stdio.h>int v[2],i;void test(int x[],int k){

x[k]=0;}void main(){

v[0]=1; v[1]=2;for(i=0;i<2;i++){ test(v,i); printf(“%2d%2d”,v[0],v[1]);}

}a) 0 2 0 0 b) 0 2 1 2c) 1 2 1 0 d) 1 2 1 2e) 1 2 2 2

13. Fie programul:#include<stdio.h>int j,x;int test(int,int);

17

Page 18: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

void main(){

x=2;printf(“%d”,test(x,x+3);//(1)printf(“%d”,x); //(2)

}int test(int a,int b){

int x=a+b;for(j=1;j<=x;j++) if(j>a && j<b) return j;return 0;

}Precizaţi care dintre afirmaţiile de mai jos sunt adevărate:

a) instrucţiunea (1) afişează valoarea 3b) instrucţiunea (2) afişează valoarea 7c) funcţia test returnează 0, indiferent

care ar fi parametrii daţi la apeld) corpul funcţiei test este eronat,

deoarece conţine două instrucţiuni return

e) programul este eronat, deoarece variabila x a fost declarată de două ori

14. Deduceţi ce valori va afişa, în ordine, programul următor?#include<stdio.h>void calcul(int *u,int *v){

int j;for(j=0;j<3;j++){ v[j]=1-u[j]; u[j]=0;}

}void main(){

int u[5],v[5],j;for(j=0;j<3;j++){ u[j]=j%2; v[j]=0;}calcul(u,v);for(j=0;j<3;j++)

printf(“%d “,u[j]);for(j=0;j<3;j++)

printf(“%d “,v[j]);}

a) 1 0 1 0 0 0 b) 0 0 0 1 0 1c) 1 0 1 0 1 0 d) 0 1 0 1 0 1e) 0 1 0 0 0 0

15. Deduceţi şirul de valori care se afişează în urma execuţiei programului următor.#include<stdio.h>int s,f;int sf(int a){

f-=a;return(a*a);

}void main()

{f=10; s=sf(f);printf(“%6d%6d”,s,f);f=10; s=sf(10); s*=sf(f);printf(“%6d%6d”,s,f);f=10; s=sf(f); s*=sf(10);printf(“%6d%6d”,s,f);

}a) 100,10,10000,10,10000,10b) 100,0,100,0,100,0c) 0,0,0,0,0,-10d) 100,0,10000,0,16960,0e) 100,0,0,0,10000,-10

16. Determinaţi valorile pe care le afişează programul de mai jos:#include<stdio.h>int x,y;int T(int m,int n){

m=n+x; n+=1;return(n+y+m);

}void main(){

y=10; x=12;printf(“%3d”,T(x,y));printf(“%3d%3d”,x,y);

}a) 43,22,10 b) 43,12,10c) 47,10,12 d) 44,22,11e) 44,12,11

17. Fie programul:#include<stdio.h>void F(……..){

a+=2; b--;c=a+b;

}void main(){

int x,y,z;x=2; y=4;F(x,y,z);printf(“%3d%3d%3d”,x,y,z);

}Funcţia F primeşte ca parametri trei numere întregi a,b,c. Cum trebuie scris antetul complet al funcţiei, astfel încât programul să afişeze, în ordine, valorile 4 4 7?

a) void F(int a,int b,int c)b) void F(int a,int& b,int& c)c) void F(int& a,int b,int& c)d) void F(int& a,int b,int c)e) void F(int& a,int& b,int& c)

18. Ce valoare trebuie citită în variabila m astfel încât programul următor să afişeze valoarea 4?#include<stdio.h>void F(int& nr,int x){

do{

18

Page 19: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

x=x/2; nr++;}while(x>0);

}void main(){

int m,n;scanf(“%d”,&m);n=0;F(n,m);printf(“%d”,n);

}a) 12 b) 13 c) 14 d) 15 e) 16

19. Precizaţi care dintre funcţiile de mai jos returnează 1 dacă numărul x este prim, 0 în caz contrar.

a) int p(int x){

int j,ok;for(j=2;j<x;j++) if(x%j==0) ok=0; else ok=1;return ok;

}b) int p(int x)

{int j;for(j=2;j<x;j++) if(x%j==0) return 0; else return 1;

}c) int p(int x)

{int j,ok=1;for(j=2;j<x;j++) if(x%j==0) ok=0;return ok;

}d) int p(int x)

{int j;return 1;for(j=2;j<x;j++) if(x%j==0) return 0;

}

20. Se consideră următoarea structură de program:#include<stdio.h>void main(){

int v[20],j,n;…………..calcul(v,2.5,10);

}void calcul(int v[],float x,int a){

……………..}Funcţia calcul fiind scrisă după funcţia main, are nevoie de un prototip care trebuie plasat

înaintea lui main. Cum poate arăta acest prototip?

a) void calcul(int v,float x, int a);b) void calcul(int v[], float x,int a);c) void calcul(int,float,int);d) void calcul(int [], float,int);e) void calcul(int*,float,int);

21. Deduceţi ce valori va afişa, în ordine, programul următor?#include<stdio.h>int u[5],v[5],w[5],t[5],j;void calcul(int* w,int* t){

for(j=0;j<3;j++){

w[j]=0;t[j]=v[j]-u[j];

}}void main(){

for(j=0;j<3;j++){

u[j]=2*j-1;v[j]=3*j-2;w[j]=u[j]+v[j];

t[j]=0;}

calcul(w,t);for(j=0;j<3;j++) printf(“%d “,w[j]);for(j=0;j<3;j++) printf(“%d “,t[j]);

}a) –3 2 7 –1 0 1 b) 0 0 0 –1 0 1c) –3 2 7 0 0 0 c) –1 0 1 –3 2 7d) 0 0 0 –3 2 7

22. Ce valori se vor afişa în urma execuţiei programului următor:#include<stdio.h>int f1(int *p){

*p=43;return 1;

}int *f2(int *q){

int m=f1(q);return &m;

}void main(){

int x,y;y=*f2(&x);printf(“\n%d %d”,x,y);

}a) programul este eronatb) 0 şi 0 c) 43 şi 43

19

Page 20: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

d) 1 şi 43 e) 43 şi 1

23. Considerăm următorul program:#include<alloc.h>#include<stdio.h>int *f(int *a,int *b){

return (*a>=*b)? a:b;}void main(){ int *x,*y; x=(int*)malloc(sizeof(int));//(1) y=(int*)malloc(sizeof(int));//(2) scanf(”%d %d”,x,y); //(3) printf(„%d”,*f(x,y)); //(4) free(x); //(5) free(y); //(6)}În timpul execuţiei programului sunt posibile următoarele situaţii:

a) funcţia nu returnează corect valoarea dorită, deoarece tipul valorii returnate nu este cel definit în antetul funcţiei

b) în locul liniilor (1) şi (2), pentru alocarea dinamică a memoriei putem scrie x=y=(int*)malloc(sizeof(int));

c) în locul liniilor (5) şi (6), pentru eliberarea memoriei alocate putem scrie free(x,y);

d) instrucţiunea scanf din linia (3) este eronată; corect era scanf(“%d”,&x, &y);, deoarece numele variabilelor citite trebuie precedat în scanf de operatorul ”&”

e) programul este în totalitate corect, el afişând astfel maximul a două numere întregi definite cu ajutorul pointerilor x şi y

24. Deduceţi ce numere va afişa programul următor:#include<stdio.h>int& f(int a,int b,int& c){

c=a+b;return c;

}void main(){

int x=2,y=3,z=11;printf(“%d”,f(x,y,z));printf(“%d”,z);f(x,y,z)=9;printf(“%d”,z);

}a) 5,11,5 b) 5,11,9 c) 5,11,11d) 5,11,9 e) 5,5,9

25. Ce valoare se va afişa în urma execuţiei programului următor?#include<stdio.h>

int f(int a=5,int b=2){

return –-a+2*b++;}void main(){

printf(“%d”,f());}

a) 7 b) 8 c) 9 d) 10 e) 11

26. Se consideră programul următor:#include<stdio.h>int f(int x,int y=5){

static int m=3;m+=x;return m>=y? m : -1;

}void main(){

int a,b,c;a=f(4); b=f(1,7); c=f();

}Care dintre cele trei apeluri realizate în main sunt corecte?

a) numai primele două apeluri sunt corecte iar valorile variabilelor sunt a=7 şi b=8

b) numai primele două apeluri sunt corecte iar valorile variabilelor sunt a=7 şi b=-1

c) numai al doilea apel este corect şi se obţine b=8

d) numai al doilea apel este corect şi se obţine b=-1

e) toate cele trei apeluri sunt corecte

27. Fie funcţia F de mai jos:int* F(int* a,int* b,int c){

int d=(*a+*b+c)/3;return &d;

}Presupunem că sunt declarate următoarele variabile:int *x,*y,z,*m,n;Care dintre secvenţele de program de mai jos nu afişează corect valoarea returnată de către funcţia F?

a) scanf(“%d %d %d”,x,y,&z);printf(“\n%d”,*F(x,y,z));

b) *m=*F(x,y,z);printf(“%d”,*m);

c) n=*F(x,y,z);printf(“%d”,n);

d) printf(“%d”,*F(2,3,4));

28. Fie funcţia:void afis1(int v[]){

int j=0;while(j<4) printf(“%d “,v[j++]);

20

Page 21: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

}Funcţiile afis2 şi afis3 de mai jos sunt corecte şi echivalente cu funcţia dată afis1? (adică afişează acelaşi şir de valori)void afis2(int v[4]){

int j=0;do printf(“%d “,*(v+j++);while(j<4);

}void afis3(int v[4]){

int j,*x[4];for(j=0;j<4;j++){ x[j]=&v[j]; printf(“%d “,*x[j]);}

}a) ambele funcţii afis2 şi afis3 conţin erorib) ambele funcţii afis2 şi afis3 sunt

corecte şi echivalente cu afis1c) ambele funcţii afis2 şi afis3 sunt

corecte, dar nici una dintre ele nu este echivalentă cu afis1

d) funcţia afis2 este corectă şi echivalentă cu afis1, iar afis3 conţine erori

e) funcţia afis3 este corectă şi echivalentă cu afis1, iar afis2 conţine erori

29. Care va fi valoarea lui n în urma execuţiei programului următor?#include<stdio.h>int* intreg(float* p){

return (int*)p;}void main(){

int n; float x=-3.56;n=x;n=*intreg(&x);

}a) n va avea valoarea –3b) n va avea valoarea –4c) n nu va avea în nici un caz valorile de

la a) sau b)d) n va avea valoarea –3.56e) programul conţine erori de sintaxă

30. Ce valori se vor afişa în urma execuţiei programului următor?#include<stdio.h>int q;int* A(int* m,int* n){

*n=*m+1;*m=*n+1;q=*m-1;return &q;

}void B(int* p){

int y=4;y=*A(&y,p);

}void main(){

int y=9,x;B(&x);printf(“%d %d”,x,y);

}a) programul este eronatb) 0 şi 9 c) 5 şi 0 d) 5 şi 9 e) 0 şi 0

31. Fie funcţiile f1 şi f2 având prototipurile:void f1(int (*p)[8]);void f2(int p[4][8]);

Analizaţi corectitudinea apelurilor celor două funcţii în următorul program:void main(){

int m[4][8],(*q)[8],*r[8];f1(m);f2(m);f1(q);f2(q);f1(r);f2(r);

}a) numai primele patru apeluri sunt

corecteb) numai primele două apeluri sunt

corectec) numai primele două apeluri sunt greşited) toate apelurile sunt greşitee) toate apelurile sunt corecte

32. Ce reprezintă declaraţia următoare:int *(*f)(int *);

a) este greşită sintacticb) funcţie care primeşte un argument

pointer la întreg şi întoarce pointer la întreg

c) pointer către întregd) pointer către funcţie care are argument

pointer către întreg şi întoarce pointer către întreg

e) o altă semnificaţie decât cele precedente

33. Fie programul:#include<stdio.h>int plus(int x){

return x++;}int minus(int x){

return –x;}void test(int p,int q, int (*F1)(int),int (*F2)(int)){

if(p && q) printf(“%d”,F1(p));

else printf(“%d”,F2(q));

21

Page 22: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

}void main(){

int a=2,b=5;test(a,b,plus,minus);test(3,0,plus,minus);test(a,b,plus(a),mins(b));test(3,0,plus(3),minus(0));

}Ce se poate spune despre apelurile funcţiei test realizate din main?

a) primele două apeluri sunt corecte, determinând afişarea valorilor 2, respectiv –1, iar ultimele două sunt eronate

b) primele două apeluri sunt corecte, determinând afişarea valorilor 3, respectiv –1, iar ultimele două sunt eronate

c) ultimele două apeluri sunt corecte, determinând afişarea valorilor 2, respectiv –1, iar primele două sunt eronate

d) ultimele două apeluri sunt corecte, determinând afişarea valorilor 3, respectiv –1, iar primele două sunt eronate

e) toate cele patru apeluri sunt eronate

34. Ce valoare se va afişa în urma execuţiei programului următor?#include<stdio.h>int f(int n,…){

int *a=&n+1, *b=a+2;return n*(*a+*b);

}void main(){

printf(“%d”,f(3,2,11,5,8));}

a) 21 b) 39 c) 18 d) 30e) antetul funcţiei este greşit

35. Ce trebuie pus în locul secvenţei XXX astfel încât programul de mai jos să furnizeze minimul unui număr variabil de argumente, precizat la apel prin valoarea lui n?#include<stdio.h>double f(int n,…){

double min=*(double *)(&n+1);for(int j=1;j<n;j++) if(XXX<min) min=XXX;return min;

}void main(){

int n=3;float a=2,b=8,c=-1;printf(“%f”,f(n,a,b,c));printf(“%f”,f(n,2.0,8.0,

-1.0));

printf(“%f”,f(3,2.0,8.0, -1.0));}

a) *(double *)(&n+1+j);b) *((double *)(&n+1)+j);c) *(double *)(&n+(1+j));d) *(double *)(&(n+1)+j);e) o altă construcţie decât cele anterioare

36. Precizaţi ce va afişa programul de mai jos:#include<stdio.h>char &f(char *p,int n){

return *(p+n);}void main(){

char *s=”abc”;f(s,1)=’a’;printf(„%s”,s);

}a) programul nu va afişa nimic pentru că

este greşitb) “aac” c) “abc” d) “aba” e) “aabc”

37. Care dintre apelurile de funcţie de mai jos va schimba valoarea lui n?#include<stdio.h>int *f(int& n){

return &n;}void main(){

int n=7;f(n)=2; // (1)*f(n)=3; // (2)

}a) ambele b) nici una c) 1d) 2 e) antetul funcţiei este greşit

38. Analizaţi programul de mai jos şi precizaţi care dintre afirmaţiile date sunt false.#include<stdio.h>int &f1(int& x){

return x=1;}int *f2(int *p){

int a=2;f1(a); *p=3;return p;

}void main(){

int b=4; f1(b); f1(b)=5;f2(&b);*f2(&b)=6;

}a) în urma execuţiei f1(b), obţinem b=4b) în urma execuţiei f1(b)=5, obţinem b=5

22

Page 23: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

c) în urma execuţiei f2(&b), obţinem b=3d) în urma execuţiei *f2(&b), obţinem b=6e) valoarea variabilei locale a din funcţia

f2 nu poate fi modificată prin nici un mecanism în funcţia main

39. Precizaţi valoarea variabilei n rezultată în urma execuţiei programului:#include<stdio.h>int f(char a[2]){

int j=0;while(a[j++]); return j;

}void main(){

int n=f(“abcdefgh”);}

a) 0 b) 2 c) 9d) corpul funcţiei conţine o buclă infinităe) programul are erori de sintaxă

40. Fie programul :#include <stdio.h>void fct(int a,int *b){ a+=3; *b+=a;}void main(){

int c, d; c=4; d=5;

fct(c,&d);printf(“%d%d”,c,d);fct(c,&d);printf(“%d%d”,c,d);

}Ce se afişează pe ecranul monitorului în urma execuţiei programului ?

a) 4545 b) 412412c) 712719 d) 412419

41. Se dă funcţia :int fct(int n){ int d=2; int g=(int) sqrt(n); int f=1; while (d<=g&&f) {

f=f&&n%d;d=d+1

} return f;}Să se precizeze ce prelucrare se realizează în această funcţie :

a) se determină factorii primi ai lui nb) se determină numere prime până la √nc) se verifică dacă numărul n este primd) se verifică dacă n se împarte exact la d

42. Fie funcţia :

int f(int a){ if(a>=’A’&&a<=’Z’)

return c+’a’-‘A’ else

return c;}Ce realizează funcţia ?a) converteşte litera mică a în litera mare Ab) converteşte litera mare A în litera mică ac) converteşte literele mici în litere marid) converteşte literele mari în litere mici

43. Ce se afişează pe ecranul monitorului , după execuţia următorului program ?#include <stdio.h>int i,j,k;void f1(int x,int *y){ *y=x+2; --x;}void f2(int u,int *v){ int m,n; m=u-j; f1(m,v); f1(*v+i,&n); *v+=n;}void main(void){ i=4; j=3; k=5; f2(i,&j); printf(“%d%d%d”,i,j,k); f2(j,&k); printf(“%d%d%d”,i,j,k); f2(k,&k); printf(“%d%d%d”,i,j,k); }

a) 4 3 54 3 104 3 20

b) 4 3 54 6 104 12 20

c) 4 12 54 12 104 12 6

d) 4 3 5 4 7 10 4 11 12

44. Presupunând că n este numărul de elemente ale unui vector de numere reale , să se specifice când funcţia de mai jos întoarce valoarea 0 .int f(int n){ int i; for(i=1;i<n-1;i++) if(x[i]==x[i+1]) return 0; return 1;

23

Page 24: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

}a) dacă două elemente din vector sunt

distincteb) dacă oricare două elemente din vector

sunt egalec) dacă primele două elemente din vector

sunt egaled) dacă două elemente consecutive sunt

egale , fără a considera primul element

45. Spuneţi ce realizează următoarul subprogram :void fct(char s[]){ int i,j,t; for(i=0,j=strlen(s)-1;i<j; i++,j--) { t=s[i];s[i]=s[j];s[j]=t; }}

a) inversează un şir de caractereb) aduce caracterul terminator al şirului pe

prima poziţie invalidându-l c) şterge un şir de caractered) introduce caractere aleatoare în şir

46. Ce realizeaza urmatoarea procedura :void f(FILE *p){

int c;while((c=getc(p))!=EOF) putc(c,stdout);

}a) copie , caracter cu caracter , un fisier in

alt fisierb) copie , caracter cu caracter , un fisier

pe ecranul monitoruluic) copie , caracter cu caracter , intrarea

standard la iesirea standardd) copie intrarea standard intr-un fisier

47. Se considera urmatoarea functie :int f(int n){ scanf(“%d”,&n); f=1; printf(“%d”,n);}Pentru n=100 pe ecranul monitorului se va afisa :

a) 100 b) 1c) programul are erori de sintaxad) programul are erori de semantica

48. Se consideră funcţia demai jos :int f(int n){ int x=0; int c=0; while(n) { c=n%10; x=x*10+c; n=n/10;

} return x;}Pentru n=121 , f capătă valoarea :

a) 121 b) 4 c) 3 d) 121000

49. Se consideră funcţia următoare :int f(int n){ int x=0; int c=0; int a=n; while (n) { c=n%10; x=x*10+c; n=n/10; } if(x==a) return 1; else return 0;} Valoarea f=1 arată că :

a) n este număr primb) n este număr parc) n este palindromd) x este divizor al lui n

50. Se consideră funcţia următoare :int f(void){ int i; printf(“%d”,i);}Valoarea afişată de funcţie este :

a) 0 b) 1 c) 32737d) nu se poate preciza valoarea afişată

51. Se consideră subprogramul :int f(int a,int b){ int r=a%b; while (r>0) {a=b;b=r;r=a%b;} return b;} Pentru a=45 si b=27 , valoarea lui f este:

a) 3 b) 9 c) 72 d) 135

52. Să se precizeze care sunt valorile care vor fi tipărite de programul de mai jos :int i,j;void p(int j){ j++; i=j+1;}void main(void){ i=2; j=4; p(i); printf(“%d %d”,i,j);}

a) 1 6 b) 1 4 c) 4 6 d) 4 4

53. Se consideră următoarea funcţie :float x[10];int f(int n){ int i,k=0; for(i=1;i<n;i++) if(x[i]==x[i-1]) k=k+1; if(k==0) return 0;

24

Page 25: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

else return k;} Dacă x=(5, 6, 6, 6, 3, 4, 4, 9) valoarea returnată pentru f este :

a) 3 b) 2 c) 7 d) 5

54. Care este implementarea corecta a functiei toupper ?I) int tomare(char c)

{ return(c-‘a’+’A’);}

II) int tomare(char c){ if(c>=’a’&&c<=’z’) return(c-‘a’+’A’); return c;}

III) int tomare(char c){ if(c>=’a’&&c<=’Z’) return(c+’a’-‘A’); return c;}a) I b) II c) III d) II si III

55. Fie funcţia f care primeşte la intrare un vector Vn prezentată mai jos :int f(int *v,int n){ int i; for(i=0;i<n;i++) { j=0; while(j<n) { if(v[i]==v[j]) return 1; else return 0; j++; } }}

a) funcţia returnează valoarea 1 dacă există elemente duplicate în vectorul v

b) numără apariţiile lui n în vectorc) realizează o altă operaţied) ordonează vectorul

56. Ce face următorul program ?int function p3(int x){ return x*x*x;}void main(void){ int x,y; scanf(“%d%d”,&x,&y); printf(“%d”,p3(x+y));}

a) este eronatăb) calculează x3

c) calculează (x+y)3

d) calculează y3

57. Se dă codul :void func(){ int x=0; static int y=0;

x++; y++; printf(“%d-%d\n”,x,y);}void main(){ func(); func();}Ce va afişa codul de mai sus când va fi executat ?

a) 1—0 1—0b) 1—1 1—1c) 1—1 1—2d) 1—1 2—2

58. Funcţia:void functie(int n,int (*a)[10]){ int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) scanf(“%2d”,&a[i][j]);}realizează :

a) citirea unei matricib) citirea unui vectorc) citirea a doi vectorid) citirea a două şiruri de caractere

59. Funcţia:void functie(int (*a)[10]){ int i,j; double temp; for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) { temp=a[i][j]; a[i][j]=a[j][i]; a[j][i]=temp; }}realizează :

a) transpusa unei matricib) inversarea unei matricic) inversarea a n liniid) inversarea a n coloane

60. Funcţia C :int functie(double x,int n,int *a){ int k,i; k=0; for(i=0;i<n;i++) if(a[i]<x) k++; return k;}returnează :

a) cele k elemente mai mici ca x dintr-un vector a

b) cele k-1 elemente mai mici ca x dintr-un vector a

c) cele k elemente mai mici egale ca x dintr-un vector a

d) cele k elemente mai mari ca x dintr-un vector a

61. Ce realizează funcţia de mai jos ?

25

Page 26: Informatică Pentru Clasa a X-A

Informatică pentru clasa a X-a

int f(int tab[],int n,int a){ int j,s,i; i=0; s=n-1; while(i<=s) { j=(i+s)/2; if(tab[j]==a) s=j-1;

else i=j+1; } return –1;}

a) realizează o sortare a elementelor tabloului tab

b) realizează o parcurgere a tabloului tab şi returnează elementul de la jumătatea acestuia

c) caută în tabloul tab un element cu valoarea egală cu a ; returnează indicele elementului respectiv

d) funcţia nu realizează nimic

62. Următoarele linii de cod :#include<stdio.h>void incr(int x,int y,int z){ x=x+1; y=y+1; z=z+1;}void main(void){ int a=10, b=20, c=30; printf(“a=%d b=%d c=%d”,a,b,c); incr(a,b,c) printf(“a=%d b=%d c=%d”,a,b,c);

}vor afişa următoarele rezultate:

a) a=10 b=20 c=30 a=11 b=21 c=31b) a=10 b=20 c=30 a=10 b=20 c=30c) a=11 b=21 c=31 a=10 b=20 c=30d) nici una din variantele 1-3

63. Următoarele linii de cod :#include<stdio.h>void incr(int *x,int *y,int *z){ *x=*x+1; *y=*y+1; *z=*z+1;}void main(void){ int a=10, b=20, c=30; printf(“a=%d b=%d c=%d”,a,b,c); incr(&a,&b,&c) printf(“a=%d b=%d c=%d”,a,b,c);}vor afişa următoarele rezultate:

a) a=10 b=20 c=30a=11 b=21 c=31

b) a=10 b=20 c=30a=10 b=20 c=30

c) a=11 b=21 c=31a=10 b=20 c=30

d) nici una din variantele 1-3

26


Recommended