Sunteți pe pagina 1din 110

Limbajul C pentru clasa a IX-a 1

____________________________________________________Cuprins

Cap.1 Elemente de baz ale limbajului C..................................................................................1


1.1 Structura unui program C ______________________________________________________1
1.2 Vocabularul limbajului_________________________________________________________1
1.3 Tipuri de date________________________________________________________________1
1.4 Directive preprocesor__________________________________________________________2
1.5 Exerciii i teste gril__________________________________________________________2
Cap.2 Tipuri fundamentale de date ...........................................................................................4
Tip.........................................................................................................................................4
Numr de bii........................................................................................................................4
Domeniu de valori................................................................................................................4
2.1 Constante___________________________________________________________________4
Exemple : 123.4 12e6 -111.2 ______________________________________________5
2.2 Variabile_____________________________________________________________________5
2.3 Exerciii i teste gril__________________________________________________________5
Cap.3 Funcii de intrare/ieire standard....................................................................................7
3.1 Clasificarea funciilor de intrare/ieire____________________________________________7
3.2 Funciile getch i getche_______________________________________________________7
3.3 Funcia putch________________________________________________________________7
3.4 Macrourile getchar i putchar___________________________________________________8
3.5 Funciile gets i puts__________________________________________________________9
3.6 Funcia printf_________________________________________________________________9
3.7 Funcia scanf________________________________________________________________11
3.8 Exerciii i teste gril_________________________________________________________13
Cap.4 Operatorii limbajului C..................................................................................................18
4.1 Precedena operatorilor_______________________________________________________18
4.2 Operatorul de atribuire simpl__________________________________________________19
4.3 Operatori aritmetici___________________________________________________________19
4.4 Operatorii relaionali__________________________________________________________20
4.5 Operatori logici______________________________________________________________20
4.6 Operatorii la nivel de bit_______________________________________________________21
4.7 Operatori compui de atribuire_________________________________________________22
4.8 Operatorul de conversie explicit (cast)__________________________________________23
4.9 Operatorul sizeof_____________________________________________________________23
4.10 Operatorii de adresare_______________________________________________________23
4.11 Operatorul condiional_______________________________________________________23
4.12 Operatorul virgul___________________________________________________________24
Limbajul C pentru clasa a IX-a 2

4.13 Exerciii i teste gril________________________________________________________24


Cap.5 Instruciunile limbajului C............................................................................................29
5.1 Instruciunea vid___________________________________________________________29
5.2 Instruciunea expresie________________________________________________________29
5.3 Instruciunea compus_______________________________________________________30
5.4 Instruciunea if______________________________________________________________30
5.5 Funcia standard exit_________________________________________________________32
5.6 Instruciunea while___________________________________________________________33
5.7 Instruciunea for_____________________________________________________________34
5.8 Instruciunea do-while________________________________________________________36
5.9 Instruciunea continue________________________________________________________38
5.10 Instruciunea break_________________________________________________________39
5.11 Instruciunea switch________________________________________________________40
5.12 Instruciunea goto__________________________________________________________42
5.13 Funciile standard sscanf i sprintf_____________________________________________43
5.14 Header-ul ctype.h___________________________________________________________46
Macro de verificare.............................................................................................................46
5.15 Funcii matematice uzuale___________________________________________________46
Valoarea returnat...............................................................................................................47
5.16 Exerciii i teste gril________________________________________________________47
Cap.6 Tablouri...........................................................................................................................55
6.1 Declararea tablourilor________________________________________________________55
Exemple:.............................................................................................................................55
6.2 Iniializarea tablourilor________________________________________________________55
6.3 Prelucrri elementare ale vectorilor____________________________________________56
6.3.1 Citirea elementelor unui vector________________________________________________56
6.3.2 Determinarea elementului minim/maxim________________________________________56
6.3.3 Determinarea primului element cu o anumit proprietate__________________________56
6.3.4 Determinarea ultimului element cu o anumit proprietate__________________________57
6.3.5 Eliminarea tuturor elementelor cu o anumit proprietate__________________________57
6.3.6 Eliminarea elementului din poziia k dat (1<=k<=n)______________________________57
6.3.7 Inserarea unui element y n poziia k dat (1<=k<=n)______________________________57
6.3.8 Permutarea circular cu o poziie spre stnga___________________________________58
6.3.9 Permutarea circular cu o poziie spre dreapta__________________________________58
6.3.11 Algoritmul de cutare binar_________________________________________________59
6.3.12 Interclasarea vectorilor_____________________________________________________59
6.4 Prelucrri elementare ale matricilor_____________________________________________60
6.4.1 Citirea elementelor unei matrici_______________________________________________61
6.4.2 Tiprirea elementelor unei matrici_____________________________________________61
Limbajul C pentru clasa a IX-a 3

6.4.3 Determinarea elementului maxim/minim________________________________________61


6.4.4 Identificarea elementelor specifice unei matrici ptratice__________________________61
6.5 Exerciii i teste gril_________________________________________________________62
..................................................................................................................................................67
Cap.7 Pointeri...........................................................................................................................68
7.1 Variabile pointer_____________________________________________________________68
7.2 Aritmetica pointerilor_________________________________________________________69
7.3 Legtura pointer tablou_____________________________________________________71
7.4 Exerciii i teste gril_________________________________________________________74
Cap.8 iruri de caractere.........................................................................................................79
8.1 Folosirea irurilor____________________________________________________________79
8.2 Tablouri de iruri_____________________________________________________________79
8.3 Funcii standard pentru prelucrarea irurilor de caractere___________________________80
8.3.1 Lungimea unui ir de caractere_______________________________________________80
8.3.2 Copierea unui ir de caractere________________________________________________80
8.3.3 Concatenarea irurilor de caractere____________________________________________81
8.3.4 Compararea irurilor de caractere_____________________________________________82
8.3.5 Cutarea n iruri de caractere________________________________________________82
8.4 Exemple de utilizare a funciilor standard________________________________________83
8.5 Funcii pentru conversii de date________________________________________________85
8.6 Exerciii i teste gril_________________________________________________________86
Cap.9 Structuri.........................................................................................................................91
9.1 Definirea tipurilor structur____________________________________________________91
9.2 Iniializarea structurilor_______________________________________________________92
9.3 Operaii permise asupra structurilor_____________________________________________93
9.4 Exerciii i teste gril_________________________________________________________94
Cap.10 Exploatarea fiierelor .................................................................................................96
10.1 Noiunea de fiier___________________________________________________________96
10.2 Deschiderea unui fiier_______________________________________________________96
10.3 nchiderea unui fiier________________________________________________________97
10.4 Funcia de verificare a sfritului unui fiier_____________________________________97
10.5 Funcii de citire/scriere caractere______________________________________________97
10.6 Funcii de citire/scriere pe iruri de caractere____________________________________98
10.8 Funcii de citire/scriere a fiierelor pe blocuri de octei___________________________100
10.10 Exerciii i texte gril______________________________________________________101
Rspunsuri la testele gril.......................................................................................................105
Bibliografie..............................................................................................................................107
Cap.1 Elemente de baz ale limbajului C

1.1 Structura unui program C

n C, elementul de baz al unui program este funcia. O funcie este o seciune de program
construit conform anumitor regului pentru declaraii i instruciuni de prelucrare a datelor problemelor.
Nu este permis definirea unei funcii n interiorul altei funcii. Structura cea mai general a unui
program C este urmtoarea :
directive preprocesare
declaraii globale
funcie1
funcie2
..
main
Orice program conine funcia main care este funcia principal a unui program. Execuia programului
ncepe cu execuia acestei funcii.
Pentru specificarea explicaiilor necesare unei mai bune nelegeri i utilizri a programelor se
folosete comentariul, care are sintaxa : /*text comentariu.*/
Textul din comentariu poate avea mai multe linii . Se poate folosi i forma: // ..............text comentariu
caz n care comentariul se refer la textul scris pn la sfritul liniei respective.
Exemplu : Programul urmtor va realiza doar afiarea unui mesaj cu ajutorul funciei printf.
#include<stdio.h>
/* includerea bibliotecii standard pentru citirea i scrierea datelor */
void main() /* funcia principal */
{
printf(Test C primul program !); /* afiare mesaj */
}

1.2 Vocabularul limbajului

Elementele de baz ale limbajului, numite i entiti sintactice sau atomi lexicali, fac parte din
urmtoarele categorii :
cuvinte rezervate : sunt nume rezervate instruciunilor, tipurilor fundamentale i sintaxei de
definire a funciilor i a tipurilor de date
identificatori : sunt nume de date, constante sau variabile. Sunt formate dintr-un ir de
caractere care ncepe cu o liter sau cu _ , urmtoarele caractere putnd fi litere, cifre sau _
constante : sunt valori fixe reprezentnd caractere, iruri de caractere, numere ntregi sau
raionale
delimitatori : reprezint simboluri care separ entitile (spaiu, tab etc) .
Observaie : limbajul C face distincie ntre literele mici i mari.

1.3 Tipuri de date

Prin tip de dat nelegem necesitatea definirii urmtoarelor aspecte :


dimensiunea zonei de memorie asociate
mulimea valorilor corespunztoare tipului
timpul de via asociat datei
mulimea operaiilor prin care valorile tipului pot fi prelucrate (modificate sau testate) i semnificaia
acestor operaii
operatorii utilizai i restricii n folosirea acestora
n C se lucreaz cu valori ce pot fi stocate n variabile sau constante. Valorile constante nu
se modific pe parcursul rulrii programului. Dac au asociat un nume, atunci se numesc constante
simbolice i se declar printr-o directiv de preprocesare numit macrodefiniie avnd sintaxa :
#define nume valoare
Exemplu : #define Ok 1
Dac nu au nume, constantele se autoreprezint prin nsi maniera lor de scriere.
Variabilele sunt datele care i pot modifica valoarea pe parcursul execuiei programului. Orice
variabil are asociat un nume i o zon de memorie care va fi prelucrat binar conform unor reguli
specifice de interpretare a tipurilor de date.
Observaie : orice variabil trebuie declarat nainte de utilizarea sa.
Tipurile de date pot fi predefinite (puse la dispoziie de limbaj) sau derivate (definite de
utilizator ).
O alt clasificare posibil este urmtoarea :
simple (scalare), care conin o singur valoare de un anumit tip
compuse, care conin mai multe valori de acelai tip sau de tipuri diferite
pointeri, care conin adrese de memorie ale unor entiti

1.4 Directive preprocesor

Reprezint operaii care vor fi efectuate naintea compilrii i anume :


includerea altor fiiere
verificarea anumitor condiii, a parametrilor de mediu sau a definiiilor
realizarea macrodefiniiilor
Directivele de preprocesare ncep cu caracterul # .
Exemplul 1 :
#include<stdio.h>
/*este inclus header-ul standard pentru intrri/ieiri */
Exemplul 2 :
#include file1.h // sunt incluse fiierele utilizatorului cu numele
#include file1.c // specificat
Limbajul C conine un mare numr de funcii pentru prelucrarea datelor. Ele sunt organizate, n
funcie de scopul urmrit, n biblioteci numite fiiere header avnd extensia h. Exemple de biblioteci
uzuale :
stdio.h , io.h pentru operaii de citire/scriere de la dispozitivele standard
stdlib.h , math.h pentru prelucrri numerice
ctype.h pentru prelucrarea sau verificarea caracterelor
mem.h , string.h pentru prelucrarea zonelor de memorie i a irurilor de caractere
alloc.h , malloc.h , stdlib.h - pentru alocarea memoriei
conio.h - pentru interfaa cu consola
graphics.h - pentru interfaa grafic
dos.h - pentru interfaa cu sistemul de operare

1.5 Exerciii i teste gril

1. La compilare se sesizeaz : a) separare a subprogramelor n


a) erorile de sintax i semantice interiorul unui program
b) erorile de calcul b) a delimita instruciunile care
c) nerespectarea ordinii opera- se execut cu prioritate
iilor din modelul matematic c) a permite utilizatorului s
d) furnizarea unor date eronate la introduc mesaje explicative
operaia de citire d) nu au nici o semnificaie

2. Delimitarea unui text ntre /* */ are rol de :


3. Care din urmtoarele cuvinte nu reprezint 6. Definirea corect a unei constante numit
un nume ? GST cu valoarea .125 este :
a) a_X b) a1b2c3 a) #define GST 0.125
c) 1abc d) _ABC b) GST .125;
c) float GST=0.125;
4. Care din urmtoarele instruciuni definete o d) #define GST .125
constant MAXSIZE cu valoarea 80 ?
a) constant MAXSIZE=80; 7. Care din numele de variabile de mai jos nu
b) #define MAXSIZE 80 este valid ?
c) #define MAXSIZE=80 a) go4it b) go_cart
d) constant MAXSIZE=80 c) 4season d) _what

5. Definirea corect a unei constante simbolice 8. Definii o constant simbolic PI cu valoarea


numit TRUE , care are valoarea 1 este : 3.14:
a) int TRUE=1; a) #define 3.14 PI;
b) #define TRUE=1; b) #define float PI 3.14;
c) #define TRUE 1; c) #define float PI=3.14;
d) #define TRUE 1 d) #define PI 3.14
e) #define PI=3.14
Cap.2 Tipuri fundamentale de date

Limbajul C lucreaz cu cinci tipuri de baz : int, char, float, double i void. Tipul void are
semnificaia de nimic sau orice tip n funcie de context. O prezentare a acestor tipuri apare n
tabelul urmtor :

Tip Numr de Domeniu de valori


bii
char 8 -128.127
unsigned char 8 0.255
signed char 8 -128127
int 16 -215.215-1
unsigned int 16 0..216-1
short int 16 -215.215-1
long int 32 -231.231-1
unsigned long int 32 0.232-1
float 32 valoarea absolut{3.4*10-38.3.4*1038}
double 64 valoarea absolut{1.7*10-308.1.7*10308}
long double 80 valoarea absolut{3.4*10-49321.1*104932}

Tipul char este folosit de obicei la prelucrarea caracterelor, dar poate fi folosit i ca ntreg de
format scurt. Modificatorii de tip signed i unsigned sunt folosii pentru datele de tip ntreg pentru a
specifica utilizarea, respectiv neutilizarea bitului de semn. Tipul logic nu este predefinit n C. Pentru el,
convenia de utilizare este : fals se consider valoarea 0, true se consider orice valoare nenul.

2.1 Constante

a) Constante ntregi : pot fi exprimate n bazele 8, 10 sau 16 . Constantele n baza 8 au ntotdeauna


prima cifr 0, iar cele n baza 16 au prefixul 0x sau 0X.
Exemple :
0172 /* are 0 n fa, este considerat n baza 8 */
120 /* este considerat implicit n baza 10 */
0x78 /* are 0x, este considerat n baza 16 */
Constantele de tip long au adugat la sfrit litera l sau L .
Exemplu : 1L 1000000L 581l
Pentru constantele unsigned se adaug la sfrit u sau U .
Exemplu : 0u 12000u 20000lu

b) Constante caracter : sunt reprezentate de unul sau mai multe caractere ncadrate ntre apostrofuri .
Exemple : X 1 \n \t %
Pentru a putea utiliza anumite caractere speciale se folosesc secvenele de evitare prezentate
n tabelul de mai jos :

Secvena Valoare hexazecimal Caracter ASCII Semnificaia


\0 0 NULL terminator de ir
\a 0x07 BELL generator de sunet
\b 0x08 BS back space
\f 0x0C FF sfrit de linie
\n 0x0A LF linie nou
\r 0x0D CR salt la nceputul rndului
\t 0x09 HT tab orizontal
\v 0x0B VT tab vertical
\\ 0x5C \ back slash
\ 0x27 apostrof
\ 0x22 ghilimele
b) Constante reale : sunt n virgul mobil i au n reprezentarea lor urmtoarele componente :
partea ntreag
punctul zecimal
partea fracionar
e sau E i un exponent

Exemple : 123.4 12e6 -111.2


c) iruri de caractere : se scriu ntre ghilimele, iar la sfritul irului compilatorul adaug automat
terminatorul de ir \0.

Exemplu : Testare siruri

2.2 Variabile

Declaraia unei variabile are sintaxa :


tip_baz list_variabile_declarate;
Lista poate fi format din una sau mai multe variabile separate ntre ele prin virgul. O variabil poate
s includ n declaraie i iniializarea sa.
Exemple :
int n, k=0;
float media;
char c=65;
unsigned long int f;
double salar;

2.3 Exerciii i teste gril

1. Care din urmtoarele nu este un tip de date c) constant unsigned integer


n C ? d) constant caracter
a) int b) numeric
c) float d) double 7. Pentru fiecare dintre constantele aflate n
coloana A) alegei din coloana B) tipul su:
2. Tipul de date INT n C este reprezentat pe : Coloana A) Coloana B)
a) 2 octei b) 8 octei A1) 5.0 B1) constant ntreag
c) 16 octei d) 32 octei A2) 5 B2) constant real
A3) 5 B3) const. hexazecimal
3. Tipul de date DOUBLE este reprezentat pe : A4) 05 B4) constant octal
a) 8 bii b) 16 bii A5) 5 B5) constant caracter
c) 32 bii d) 64 bii A6) 0x5 B6) constant ir de
caractere
4. Tipul de date CHAR este reprezentat pe : a) A1B2, A2B1, A3B5, A4B1,
a) 4 bii b) 8 bii A5B6, A6B3
c) 16 bii d) 32 bii
b) A1B2, A2B1, A3B5, A4B4,
5. Care este valoarea maxim a unui tip de A5B5, A6B3
date cu semn exprimat pe 8 bii ? c) A1B2, A2B1, A3B5, A4B4,
a) (2 la puterea 8) minus 1 A5B6, A6B3
b) (2 la puterea 7) minus 1 d) A1B2, A2B1, A3B5, A4B4,
c) 2 la puterea 16
d) (2 la puterea 16) minus 1 A5B6, A6eronat
e) A1B2, A2B1, A3B5, A4B1,
6. Ce tip de constant este 27U ? A5B6, A6eronat
a) constant integer universal
b) constant short int
8. Care dintre urmtoarele valori sunt constante
flotante scrise corect? 14. Considerm variabilele a, b, c, d i e.
1) 2307.98 2) +54.3 3) 20.07 Alegei varianta corect a declaraiilor, astfel
4) 198. 5) .13 6) 1.9 E4 nct atribuirile urmtoare s nu fie nsoite de
7) +2.7E+3 8) 2.e+4 conversii care s modifice valorile atribuite.
a) 1), 2), 3), 6), 7) a=3; b=8; c=2.1; d=-3.5; e=B;
a) float a,b,c.d; char e;
b) toate mai puin 5)
c) toate b) int a,b,c,d; char e;
d) toate mai puin b) c) int a,b,e; float c,d;
e) primele cinci d) int a,b; float c,d; char e;
e) int c,d; float a,b; char e;
9. Care dintre valorile de mai jos sunt constante
ntregi scrise corect? 15. O declaratie de genul :
a) 123 b) 17 c) +843 int i=7.3;
d) 0154 e) --67 va avea urmatorul efect :
a) semnalarea unei erori din partea
10. Care dintre construciile de mai jos compilatorului
reprezint constante tip caracter? b) va atribui lui i valoarea 7.3 i
1) 2) \ 3) a va semnala un avertisment din
4) 5) \\ 6) \13 partea compilatorului
7) a 8)
a) 2), 3) ,8) b) toate
c) va modifica tipul variabilei i
c) toate mai puin 5) si 6) d) va atribui lui i valoarea 7
d) 2), 3), 4), 8)
e) 3), 4), 5). 6), 8) 16. Declaraia corect pentru definirea unui
ntreg numit suma este :
11. Care dintre urmtoarele declaraii de a) suma:integer; b) integer suma;
variabile declar corect o variabil x ce poate c) int suma; d) suma int;
memora valori reale?
a) float x; b) double x; 17. Declaraia corect pentru definirea unei
c) unsigned float x; variabile caracter numit litera este :
d) x:float; e) x:double; a) litera:=char; b) char litera;
c) litera: char;
12. Care dintre liniile de program de mai jos d) character litera;
realizeaz iniializarea corect a variabilei x la
declararea sa? 18. Definirea corect a unei variabile numit
a) int x==2; b) x:int=2; bani care poate fi utilizat pentru a memora
c) int x=2; d) int x 2; valori reale simpl precizie este :
e) x=2:int; a) bani: real; b) real bani;
c) float bani; d) bani float;
13. Care dintre variabile vor avea valori ntregi
dup execuia secvenei de program 19. Definirea corect a unei variabile ntregi
urmtoare? numit total iniializat cu zero este :
int a=3, b, c; a) total: integer=0;
float x=-11.23; b) total=0, int;
char d; c) int total=0;
b=x; d=A; c=M-N; d) int=0 , total;
a) variabila x b) variabila c
c) variabila d d) variabila a 20. Ce numr este echivalent cu 4e3 ?
a) 4000 b) 400
e) variabila b
c) .004 d) .0004
Cap.3 Funcii de intrare/ieire standard

3.1 Clasificarea funciilor de intrare/ieire

Prin intrri/ieiri nelegem un set de operaii care permit schimbul de date ntre un program i
un periferic. n general, operaia de introducere a datelor de la un periferic se numete operaie de
citire, iar cea de ieire pe un periferic scriere. Numim terminal standard terminalul de la care s-a
lansat programul.
Funciile de citire/scriere se pot clasifica, dup tipul datelor manevrate, n urmtoarele categorii:
pentru caractere
pentru iruri de caractere
cu format
n funcie de locul de efectuare a operaiilor de citire/scriere, funciile se mpart n :
funcii de citire/scriere la consol
funcii de citire/scriere ntr-o zon de memorie
funcii de citire/scriere ntr-un fiier oarecare
Funciile utilizate mai frecvent pentru realizarea operaiilor de intrare/ieire folosind terminalul
standard sunt :
pentru intrri : getch, getche, gets i scanf
pentru ieiri : putch, puts i printf
La acestea se adaug macrourile getchar pentru intrri i putchar pentru ieiri. Aceste
macrouri sunt definite n header-ul stdio.h i folosirea lor implic includerea acestui fiier.

3.2 Funciile getch i getche

Funciile getch i getche sunt independente de implementare. Ambele permit citirea direct de
la tastatur a unui caracter. Funcia getch() citete de la tastatur fr ecou, deci caracterul tastat nu
se afieaz pe ecanul monitorului. Ea permite citirea de la tastatur att a caracterelor corespunztoare
codului ASCII, ct i a celor corespunztoare unor funcii speciale cum ar fi tastele F1, F2 etc. sau
combinaii de taste speciale. La citirea unui caracter al codului ASCII, funcia returneaz codul ASCII al
caracterului respectiv.
n cazul n care se acioneaz o tast care nu corespunde unui caracter ASCII, funcia getch()
se apeleaz de dou ori : la primul apel funcia returneaz valoarea zero, iar la cel de-al doilea apel se
returneaz o valoare specific tastei acionate.
Funcia getche() este analog cu funcia getch, cu singura diferen c ea realizeaz citirea cu
ecou a caracterului tastat. Aceasta nseamn c se afieaz automat pe ecran caracterul tastat.
Ambele funcii nu au parametri i se pot apela ca operanzi n expresii. La apelarea lor se vizualizeaz
fereastra utilizator i se ateapt tastarea unui caracter. Programul continu dup tastarea caracterului.
Funciile getch i getche au prototipurile n fiierul conio.h, deci utilizarea lor implic
includerea acestui fiier.

3.3 Funcia putch

Funcia putch afieaz un caracter pe ecranul monitorului. Ea are un parametru care


determin imaginea afiat la terminal. Funcia poate fi apelat astfel : putch(expresie);
Prin acest apel se fieaz imaginea definit de valoarea parametrului expresie. Valoarea
parametrului se interpreteaz ca fiind codul ASCII al caracterului care se afieaz. Dac valoarea se
afl n intervalul [32,126], atunci se afieaz un caracter imprimabil al codului ASCII. Dac valoarea
respectiv este n afara acestui interval, atunci se afieaz diferite imagini care pot fi folosite n diverse
scopuri, cum ar fi de exemplu trasarea de chenare.
Funcia putch afieaz caractere colorate n conformitate cu culoarea curent setat n modul
text de funcionare al ecranului. La revenirea din funcia putch se returneaz valoarea parametrului de
apel, adic codul imaginii afiate. Prototipul funciei se afl n fiierul conio.h.
Exemplul 1: S se scrie un program care citete un caracter imprimabil i-l afieaz apoi pe ecran.
#include<conio.h>
void main()
{
putch(getch());
}
Exemplu 2 : Se citete de la tastatur un caracter fr ecou, se afieaz caracterul, apoi se trece
cursorul pe linia urmtoare.
#include<conio.h>
void main()
{
clrscr();
putch(getch());
putch(\n);
getch();
}

3.4 Macrourile getchar i putchar

Aceste macrouri sunt definite n fiierul stdio.h. Ele se apeleaz la fel ca funciile. Macroul
getchar permite citirea cu ecou a caracterelor de la terminalul standard. Se pot citi numai caractere ale
codului ASCII, nu i caractere corespunztoare tastelor speciale. Prin intermediul macroului getchar
caracterele nu se citesc direct de la tastatur. Caracterele tastate la terminal se introduc ntr-o zon
tampon pn la acionarea tastei Enter. n acest moment, n zona tampon, se introduce caracterul de
rnd nou (newline) i se continu execuia lui getchar. Se revine din funcie returnndu-se codul ASCII
al caracterului curent din zona tampon. La un nou apel al lui getchar se revine cu codul ASCII al
caracterului urmtor din zona tampon. La epuizarea tuturor caracterelor din zona tampon, apelul lui
getchar implic tastarea la terminal a unui nou set de caractere care se rencarc n zona tampon.
Un astfel de mod de desfurare a operaiei de citire implic o anumit organizare a memoriei
i accesului la caractere, organizare care conduce la noiunea de fiier.
n general, prin fiier se nelege o mulime ordonat de elemente pstrate pe suporturi de
memorie extern. Elementele unui fiier se numesc nregistrri. Cu toate c fiierele sunt n general
pstrate pe discuri, este util s se considere organizate n fiiere chiar i datele care se tasteaz sau se
afieaz la terminal. n acest caz nregistrarea este un rnd afiat la terminal sau succesiunea de
caractere tastat la terminal i terminat la apsarea tastei Enter.
Fiierele conin o nregistrare special care marcheaz sfritul de fiier. Aceast nregistrare
se realizeaz la tastatur prin secvene speciale, spre exemplu tastnd <Ctrl>+Z al crui ecou este ^Z.
Macroul getchar returneaz valoarea constantei simbolice EOF (End of File) la ntlnirea
sfritului de fiier. Aceast constant este definit n fiierul stdio.h i n general are valoarea 1.
Macroul getchar se apeleaz fr parametri i de obicei este un operand al unei expresii : getchar();.
Macroul puchar afieaz un caracter al codului ASCII. El returneaz codul caracterului afiat
sau 1 la eroare. Se poate apela cu : putchar(expresie); Valoarea expresiei reprezint codul ASCII
al caracterului care se afieaz.
Exemplu : S se scrie un program care citete un caracter folosind macroul getchar, l afieaz
folosind macroul putchar i trece cursorul pe linia urmtoare.
#include<stdio.h>
#include<conio.h>
void main()
{ clrscr();
putchar(getchar());
putchar(\n);
getch();
}
3.5 Funciile gets i puts

Funcia gets poate fi folosit pentru a introduce de la terminalul standard o succesiune de


caractere terminat prin acionarea tastei Enter. Citirea se face cu ecou i se pot citi numai caracterele
codului ASCII. Funcia are ca parametru adresa de nceput a zonei de memorie n care se pstreaz
caracterele citite. De obcei, acest zon de memorie este alocat unui tablou unidimensional de tip
char. Deoarece numele unui tablou are ca valoare adresa de nceput a zonei de memorie alocat,
rezult c numele unui tablou poate fi utilizat ca parametru al funciei gets. n felul acesta, caracterele
citite se vor pstra n tabloul respectiv.
Funcia gets returneaz adresa de nceput a zonei de memorie n care s-au pstrat
caracterele. La ntlnirea sfritului de fiier (<Ctrl>+Z) se returneaz valoarea zero. Zero nu reprezint
o valoare posibil pentru gets i de aceea, ea poate fi folosit pentru a semnala sfritul de fiier. De
obicei, valoarea returnat de gets nu se testeaz fa de zero, ci fa de constanta simbolic NULL
definit n fiierul stdio.h.
Rezult c dac tab este declarat prin : char tab[255]; atunci apelul : gets(tab); pstreaz
n tab succesiunea de caractere tastat de la terminal n linia curent. Totodat, caracterul newline se
nlocuiete cu NUL (\0).
Funcia puts afieaz la terminalul standard un ir de caractere ale codului ASCII. Dup
afiarea irului respectiv, cursorul trece automat pe o linie nou (deci caracterul NUL se nlocuiete cu
newline). Funcia are ca parametru adresa de nceput a zonei de memorie care conine caracterele de
afiat. n cazul n care irul de caractere care se afieaz se pstreaz ntr-un tablou unidimensional de
tip char, drept parametru se poate folosi numele acestui tablou.
Funcia puts returneaz codul ultimului caracter al irului de caractere afiat (caracterul care
precede NUL) sau 1 la eroare. Dac tab are declaraia de mai sus i el pstreaz un ir de caractere,
atunci apelul : puts(tab); afieaz la terminalul standard irul respectiv de caractere i apoi trece
cursorul pe linia urmtoare. Funciile gets i puts au prototipurile n fiierul stdio.h.
Exemplul : S se scrie un program care citete de la intrarea standard numele i prenumele unei
persoane, afieaz iniialele personei respective pe cte un rnd, fiecare iniial fiind urmat de un
punct.
#include<stdio.h>
#include<conio.h>
void main()
{ char nume[30];
char prenume[30];
clrscr();
gets(nume); gets(prenume);
putchar(nume[0]);
putchar(.);
putchar(prenume[0]);
putchar(.);
puts(\nPentru a termina programul actionati o
tasta );
getch();
}

3.6 Funcia printf

Pentru scrierea cu format a datelor se folosete funcia printf care face scrierea datelor n
fiierul standard de ieire (stdout). Sintaxa de utilizare este :
int printf(mesaje si lista de formate, expr_1, expr_2, .,expr_n);
Funcia printf realizeaz urmtoarele :
accept o serie de argumente de tip expresie pe care, dup ce le evalueaz, le transform n iruri
de caractere conform formatului specificat
scrie irurile n fiierul standard de ieire (sunt acceptate secvenele de evitare)
Dac numrul de argumente specificate n format nu corespunde cu numrul argumentelor din
lista de expresii, atunci apar rezultate neateptate care pot avea efecte duntoare. Rezultatul ntors de
funcie, n caz de succes, este numrul de octei scrii, iar n caz de eroare, valoarea ntoars este
EOF. Specificatorii de format folosii pentru printf sunt prezentai n tabelul urmtor :
Specificator Semnificaie
%e , %E Numr real de forma iiii.zzzzzz , unde nr.zecimale z este dat de precizie
(6 implicit)
%f Numr real de forma i.zzzzzz , unde nr. zecimale este dat de precizie (6
implicit) i pentru partea ntreag este folosit doar o cifr
%g , %G Numr real care suprim caracterele terminale care nu influeneaz
valoarea , adic cifrele 0 de la sfrit i punctul zecimal , dac are
partea fracionar 0
%i Numr ntreg n baza 8, 10, sau 16 n funcie de primul sau primele dou
caractere
%d Numr ntreg n baza 10
%o Numr ntreg n baza 8 ; nu este necesar scrierea cifrei 0 la nceputul
numrului
%x Numr ntreg n baza 16 ; nu este necesar scrierea secvenei 0x la
nceputul numrului
%u Numr ntreg fr semn
%s ir de caractere
%c Un singur caracter

Expresiile afiate se pot alinia la stnga sau la dreapta i se poate fora afiarea semnului astfel :
semnul plus afieaz explicit semnul expresiei
semnul minus aliniaz expresia afiat la stnga
absena oricrui semn semnific alinierea expresiei afiate la dreapta
Pentru numerele ntregi i pentru irurile de caractere se poate specifica un numr care
nseamn spaiul folosit pentru afiare. Dac spaiul necesar este mai mic sau egal cu numrul
specificat, atunci se vor afia suplimentar spaii (sau zerouri, dac numrul este precedat de cifra 0)
pn la completarea spaiului de afiare.
Pentru numerele reale se pot specifica, opional, semnul pentru aliniere i dou numere
separate prin punct. Primul precizeaz dimensiunea total de afiare, iar al doilea precizia, adic
numrul de zecimale afiate.
n cazul irurilor de caractere, specificarea a dou numere separate prin punct indic faptul c
primul numr reprezint numrul de caractere din ir care se vor afia, iar al doilea reprezint limita
superioar de tiprire, completarea fcndu-se cu spaii la dreapta sau stnga, n funcie de modul de
aliniere. Poate apare fenomenul de trunchiere a irului afiat n cazul n care dimensiunea acestuia
depete limita inferioar.
n cazul unui numr ntreg, al doilea numr indic o completare la stnga cu zerouri pn se
ajunge la dimensiunea de afiare specificat.
Exemple:
Valoarea datei Specificator Afiare
3.14159265 %5f 3.141593
123.672 %7f 123.672000
3.14159265 %7.2f 3.14
123.672 %10.1f 123.7
-123.672 %10.1f -123.7
3.14159265 %10.0f 3
123.672 %10.0f 124

Numrul zecimalelor se definete prin precizia indicat n specificatorul de format. Dac ea este
absent atunci se afieaz 6 zecimale. Ultima cifr afiat este rotunjit prin lips sau prin adaos.
Exemple:
Valoarea datei Specificator Afiare
3.14159265 %e 3.141593e+00
123.672 %e 1.236720e+02
123.672 %.1E 1.2E+02
0.673 %E 6.73000E-01
123.672 %.0E 1E+02
Numrul zecimalelor se definete prin precizia indicat n specificatorul de format. Dac ea este
absent atunci se afieaz 6 zecimale. Ultima cifr afiat este rotunjit prin lips sau prin adaos.
Exponentul ncepe cu litera e dac specificatorul de format se termin cu e i cu E dac el se termin
cu E. Urmeaz un semn plus sau minus dac exponentul este negativ. Dup semn se afl un ntreg
zecimal de cel puin dou cifre.
Exemplul 1: folosirea afirii cu format pentru numere ntregi
#include<stdio.h>
void main()
{ int nr=4321;
printf(\n nr=%d,nr); // nr=4321
printf(\n nr=%-d*,nr); // nr=4321*
printf(\n nr=%6d,nr); // nr= 4321
printf(\n nr=%-6d*,nr); // nr=4321 *
printf(\n nr=%6.8d,nr); // nr=00004321
printf(\n nr=%-6.8d*,nr); // nr=00004321*
}
Exemplul 2 : folosirea afirii cu format pentru numere reale
#include<stdio.h>
#include<conio.h>
void main()
{ double x=123.01234567;
clrscr();
printf(\n x=%f,x); // x=123.012346
printf(\n x=%-f*,x); // x=123.012346*
printf(\n x=%16f,x); // x= 123.012346
printf(\n x=%-16f*,x); // x=123.012346 *
printf(\n x=%.10f,x); // x=123.0123456700
printf(\n x=%-.10f*,x); // x=123.0123456700*
printf(\n x=%12.4f,x); // x= 123.0123
printf(\n x=%-12.4f*,x); // x=123.0123 *
getch();
}
Exemplul 3 : folosirea afirii cu format pentru irurile de caractere
#include<stdio.h>
#include<conio.h>
void main()
{ char s[44]=Testare comportament printf pentru siruri !;
clrscr();
printf(\nsirul=%s,s);
printf(\nsirul=%-s*,s);
printf(\nsirul=%50s,s);
printf(\nsirul=%-50s*,s);
printf(\nsirul=%50.60s,s);
printf(\nsirul=%-50.60s*,s);
printf(\nsirul=%20.30s,s);
printf(\nsirul=%-20.30s*,s);
getch();
}

3.7 Funcia scanf

Funcia de citire cu format scanf are sintaxa :


scanf(lista de formate , adresa_var1 , adresa_var2,..);
Aceast funcie realizeaz urmtoarele operaii :
citete din fiierul standard de intrare stdio o secven de cmpuri de intrare, caracter cu caracter,
pn la terminarea introducerii cmpurilor i apsarea tastei <Enter> ;
formateaz fiecare cmp conform formatului specificat n lista de formate. Din caracterele citite se
calculeaz valori numerice sau literale, conform tipului fiecrei variabile, dimensiunilor de format
specificate i a separatorilor de cmpuri predefinii (spaiu, tab i enter) sau impui explicit ;
valorile astfel construite sunt stocate la adresele variabilelor specificate ca argumente ;
Ordinea formatelor variabilelor trebuie s coincid cu ordinea listei adreselor variabilelor n care
se face citirea. Fiecare variabil care se dorete a fi citit trebuie corelat cu un format specific.
Observaie :Indiferent de formatul folosit, la ntlnirea unui spaiu n introducerea datelor, este
terminat citirea variabilei.
Pentru funcia de citire scanf trebuie folosit operatorul adres &. Pentru variabilele citite cu
aceast funcie trebuie precizate adresele la care se stocheaz n memoria calculatorului valorile
variabilelor. Funcia va introduce valorile citite direct la acele adrese. Singurul caz n care nu este
obligatorie folosirea operatorul adres pentru citirea valorii unei variabile cu funcia scanf este citirea
unui ir de caractere .
Observaie : citirea cu ajutorul funciei scanf a irurilor de caractere care conin spaii este imposibil.
n cazul n care formatul specificat este necorespunztor, rezultatul obinut poate fi neprevzut.
Valoarea ntoars de scanf n caz de succes, este numrul de variabile care au fost citite corect. Dac
nu a fost citit nici o variabil (de exemplu s-a introdus un ir n loc de un numr ) funcia ntoarce
valoarea 0. Dac apare o eroare naintea oricrei citiri i asignri, funcia returneaz EOF (constant de
sistem avnd valoarea ntreag 1).
Specificatorii de format ai funciei scanf() sunt prezentai n tabelul urmtor:

Cod Semnificaie
%c Citete un caracter
%d Citete un ntreg zecimal
%i Citete un ntreg zecimal
%e Citete un numr float
%f Citete un numr float
%g Citete un numr float
%o Citete un numr octal fr semn
%s Citete un ir de caractere
%x Citete un numr hexazecimal fr semn
%p Citete un pointer
%n Argumentul asociat primete o valoare ntreg egal cu numrul
de caractere deja citite
%u Citete un numr ntreg fr semn
%[ ] Scanare pentru un set de caractere

O caracteristic foarte interesant a funciei scanf() este numit scanset. Un specificator


scanset se poate crea prin includerea unei liste de caractere n interiorul unor paranteze drepte. Spre
exemplu, iat un specificator scanset coninnd literele ABC : %[ABC]. Cnd scanf() ntlnete un
specificator scanset, se ncepe citirea caracterelor i depozitarea lor ntr-un tablou punctat de
argumentul corespunztor. Citirea va continua ct timp caracterul citit face parte din scanset. n
momentul n care caracterul citit nu face parte din scanset, funcia scanf() oprete citirea pentru acest
specificator i avanseaz la urmtorul specificator din irul de control. Folosind semnul n scanset se
specific un domeniu. De exemplu, urmtorul specificator se refer la literele de la A la Z : %[A-Z].
Uneori cnd scansetul este mare, este mai uor s specificm ceea ce nu face parte din scanset.
Pentru a realiza acest lucru, setul trebuie precedat de semnul ^. De exemplu, [^0123456789]. Cnd
scanf() ntlnete acest scanset, va citi orice caracter exceptnd cifrele de la 0 la 9. Se poate suprima
asignarea unui cmp punnd un asterisc imediat dup semnul %. Aceast proprietate este foarte util
cnd introducem informaii care conin i caractere de care nu avem nevoie. De exemplu, dndu-se :
int j,k;
scanf(%d%*c%d,&j,&k);
i datele de intrare sub forma : 555-2345, scanf() va asigna valoarea 555 variabilei j, va nltura
semnul i va asigna valoarea 2345 variabilei k.
Iat un exemplu de scanset care accept caractere litere mici i litere mari. ncercai s
introducei cteva litere, apoi orice alt caracter i apoi din nou litere. Dup ce apsai tasta Enter numai
literele introduse naintea caracterelor care nu au fost litere vor fi coninute n str.
#include<stdio.h>
void main()
{
char str[80];
printf(Introduceti litere si apoi orice altceva\n);
scanf(%[a-zA-Z],str);
printf(%s,str);
}
Dac dorii s citii un ir coninnd spaii folosind funcia scanf(), va trebui s utilizai scansetul
urmtor:
#include<stdio.h>
void main()
{
char str[80];
printf(Introduceti litere si spatii\n);
scanf(%[a-zA-Z ],str);
printf(%s,str);
}
Se pot specifica de asemenea semne de punctuaie, simboluri i cifre, astfel c, virtual, se poate citi
orice tip de ir.
Programul urmtor ilustreaz efectul pe care l are prezena unor caractere non-spaiu n irul
de control. El ne permite s introducem o valoare zecimal, cifrele din stnga punctului zecimal sunt
asignate unei variabile ntregi, iar cele din dreapta punctului zecimal sunt asignate unei alte variabile
ntregi.
#include<stdio.h>
void main()
{
int j,k;
printf(Introduceti un numar zecimal : );
scanf(%d.%d,&j,&k);
printf(stanga:%d\t dreapta:%d,j,k);
}

Observaie : Dac este posibil apariia erorilor la introducerea datelor, este necesar ca imediat dup
apariia unei erori s folosim una din funciile :
fflush(stdin); - pentru golirea buffer-ului fiierului standard de intrare
fflushall(); - pentru golirea tuturor buffer-elor fiierelor
Exemple :
char a[20];
int n;
scanf(%[A-Z]s,a);
/*citete un ir format numai din litere mari */
scanf(%[a-zA-Z]s,a);
/* citete un ir format din litere mari si mici */
scanf(%3d,&n);
/* citete un numr ntreg de cel mult trei cifre */

3.8 Exerciii i teste gril

1. S se determine ce tiprete urmtoarea c) chiar dac nu este semnalat


instruciune : nici o eroare la compilare, nu
unsigned n=100; se afieaz valoarea dorit,
printf("%04x",n); deoarece nu am folosit un
a) 0100 b) 100 specificator de format adecvat
c) 0064 c) A10
3. Fie declaraiile :
2. Ce face secvena ? int n;long double x;char s[100];
float n=16; Care din secvenele urmtoare sunt corecte
printf("%x",n+1); pentru citirea variabilelor ?
a) afieaz numrul n baza 16 a) scanf("%i %s %lg",&n,&s,&x);
b) d eroare de compilare deoarece b) scanf("%d %s %Lg",&n,&s,&x);
nu am folosit o variabil la c) scanf("%d %s %Lg",&n,s,&x);
scriere d) scanf("%d %c %lf",&n,&s,&x);
e) scanf("%d %",&n,&s,&x); b) nu apar erori la compilare;
deoarece n interiorul
4. Fie declaraia : char s[20]; formatului s-a pus virgul, nu
Care din secvenele de mai jos citesc corect un se vor citi corect numerele
ir de caractere s ? c) nu apar erori la compilare;
a) scanf("%c",s); deoarece s-a pus virgul,
b) scanf("%c",&s); numerele introduse trebuie
c) scanf("%s",s); separate prin virgul
d) scanf("%s",&s); d) nu apar erori la compilare;
e) scanf("%",s); pentru numerele introduse poate
f) scanf("",s); fi folosit orice secven
delimitatoare
5. Fie declaraia : char str[80];
Care din urmtoarele secvene vor face citirea 10. Fie secvena urmtoare :
unui ir de maxim 80 caractere care s nu int a; char str[20];
conin caracterul . ? scanf("%i", &a);
a) scanf("%[.]s",str); fflush(stdin);
b) scanf("%[^.]s",str); gets(str);
c) scanf("%80[^.]s",str); Datele de intrare se introduc astfel :
d) scanf("%80[^.]c",str); 100
e) scanf("%80[.^]s",str); abcd
Ce se ntampl dac scoatem funcia fflush din
6. Fie declaraia : char s[100]; secvena anterioar ?
Care din urmtoarele secvene va face citirea a) este semnalat eroare la
unui ir de caractere care s conin numai compilare
cifre? b) nu se mai citete de pe linia a
a) scanf("%[0123456789]",s); doua irul "abcd", acesta lund
valoarea ""(ir vid)
b) scanf("%s",s); c) ambele date sunt citite corect,
c) scanf("%[^0-9]s",s); numrul lund valoarea 100 iar
d) scanf("%[09]s",s); irul valoarea "abcd"

e) scanf("%[0-9]s",s); 11. Fie urmtoarele declaraii de variabile:


f) scanf("%['0'-'9']",s); int a; float x; char m;
g) scanf("%['0'...'9']",s); Care dintre instruciunile de mai jos realizeaz
citirea corect a variabilelor a,x i m?
7. Cum putem introduce un numr x ntreg de a) scanf(%d %f %c,&a,&x,&m);
maxim 4 cifre care s nu conin cifra 0? b) scanf(%d,%f,%c,a,x,m);
a) scanf(%4d,&x); c) scanf(%f.%d.%c,&a,&x,&m);
b) scanf(%4[^0]s,x); d) scanf(a=%d,x=%f,c=
c) scanf(%04d,&x); %c,a,x,m);
d) scanf(%d0,&x); e) scanf(a=%d\nx=%f\nc=%c\n,
&a,&x,&m);
8. Fie declaraiile : int a, b, c;
i apelul: 12. Fie declaraiile:
scanf("%2d%3d%4d",&a,&b,&c); int a=34; float x=6.25;
Care va fi valoarea variabilelor dup Precizai care dintre instruciunile de afiare
introducere, dac la intrare se tasteaz urmtoare trebuie executat astfel nct s se
123456? afieze pe ecran rndul de mai jos:
a) a=123 , b=345 , c=56 34##:#6.250
b) a=12 , b=345 , c=6
unde prin # am simbolizat caracterul spaiu.
c) a=123456 , b=0 , c=0 a) printf(\n%4d:%-10f,a,x);
b) printf(\n%-4d:%6.3f,a,x);
9. Ce se ntmpl dac se folosete secvena c) printf(\n%6d:%10f,a,x);
urmtoare ?
int m, n; d) printf(\n%-d:%-.3f,a,x);
scanf("%d,%d",&m,&n); e) printf(\n%d:%f,a,x);
a) obinem eroare la compilare
pentru c n interiorul
formatului s-a pus virgul
13. Dac de la tastatur se introduce caracterul d) funciile getchar i getche
a, iar codurile literelor mici sunt succesive, preiau caracterul de ndat ce a
ncepnd cu 97, ce afieaz programul fost tastat, fr s mai atepte
urmtor? confirmarea cu ENTER
#include<stdio.h> e) toate cele trei funcii au
#include<conio.h> prototipul n header-ul conio.h
void main()
{ 16. char x=A;
char c, p; putchar(x);
p=getchar(): putchar(x+1);
int n=p+259; Referindu-ne la codul de mai sus i
c=n; presupunnd c funcia putchar ia ca
putchar(c); argument un ntreg, ce vom avea la ieire dup
} execuie ?
a) 356 b) a c) d a) BA b) A66 c) AB
b) 100 e) programul este d) Se va genera o avertizare la
greit compilare i execuia nu este cea
ateptat
14. Care dintre secvenele de mai jos nu conin
erori i afieaz cuvintele Program i simplu 17. Unde scrie funcia printf() ?
unul sub altul (fiecare pe cte un rnd) ? a) stdout b) stdio
a) c) stdin d) stderr
{
printf(Program); 18. Cs a
printf(\nsimplu); fun language!
} Selectai codul care va produce ieirea de mai
b) sus:
{ a) printf(Cs a\fun\
printf(Program\n); language!\n);
printf(simplu);
b) printf(Cs a
}
\fun\language!);
c)
c) printf(Cs a\n fun
{
language!\n);
printf(Program\nsimplu);
d) printf(Cs
printf(\n);
a\n \fun\
}
language!\n);
d)
{
printf(Program); 19. short int x; /*presupunem c x este
printf(simplu\n); pe 16 bii*/
} Care este numrul maxim care poate fi tiprit
e) nici unul dintre programele folosind printf(%d\n,x), presupunnd c
anterioare x este declarat aa cum am artat mai sus ?
a) 127 b) 255
15. Funciile getchar(), getch() i getche() c) 32767 d) 65536
citesc de la tastatur un caracter. Ce deosebiri
exist ntre cele trei funcii ? 20. Fie secvena :
printf(\n%10.0f,x);
a) funciile getchar i getche Pentru x=3.14159265 se va afia :
realizeaz citire cu ecou, iar
a) 3 b) 3.14
getch citete caracterul fr
ecou
c) 3.1415 d) 3.141593
b) funcia getchar citete
caracterul cu ecou, iar 21. Fie secvena :
funciile getche i getch printf(\n.1E,x);
realizeaz citirea fr ecou Pentru x=123.672 se va afia :
c) funciile getchar i getch a) 1.2E+02 b) 1.236E+02
preiau caracterul numai dup
apsarea tastei ENTER c) 123E+02 d) 1E+02
22. Fie secvena : a) 05365 b) 0xAF5
printf(\n*%15.10S*,x);
Pentru x=program c++, se va afia : c) AF5 d) 5365
a) * program c+* (5 spaii
n fa) 29. Se d urmtorul program :
b) *program c++* #include <stdio.h>
void main()
c) *program c* {
d) * program c++* (4 spaii double x;
n fa) scanf(%lf,&x);
printf(%e,d);
23. Fie secvena : }
printf(\n*%07d*,x);
Efectul acestui program este :
Pentru x=123, se va afia : a) citete i afieaz un numr
a) *0000123* b) *123* real
c) * 123* d) *123 * b) citete un numr cu exponent i
l afieaz
24. Fie secvena : c) citete un numr real i
printf(\n%.4e,x); afieaz valoarea sa cu
Pentru x=-123.5e20, se va afia : exponenial
a) 1.2350e+22 b) 1.235e+22 d) afieaz un numr real
c) 12.3500e+21 d) 1.2350e+20
30. Care este efectul instruciunii
25. Care este efectul apelului funciei printf(%u,x) unde x este o variabil de
printf(%x,a), unde a este o variabil de tip ntreg de valoare 0xAF25 :
tip ntreg de valoare 0xAF5 : a) 20669 b)
a) 0xAF5 b) 5365 c) AF25
AF5 c) 44837 d) 0xAF25
d) valoarea binar a variabilei a
31. Care este efectul apelului funciei
26. Care este efectul urmtorului program : printf(%x,b) unde b este o variabil de
#include <stdio.h> tip ntreg de valoare 0x12ABC :
#include <conio.h> a) 12AB b) 12ABC
void main(void) c) 0x12ABC d) 2ABC
{
putchar(getche()-A+a); 32. Care este efectul apelului functiei
printf(\n); printf(%lx,b) unde b este o variabil de
} tip ntreg n dubl precizie de valoarea
a) citete i afieaz un caracter 0x12ABC :
b) citete o liter mare i a) 0x12ABC b) 12ABC
afieaz litera mic cores-
punztoare c) ABC d) 012ABC
c) citete o liter mic i
afieaz litera mare cores- 33. Fie urmtorul program :
punztoare #include <stdio.h>
d) citete un caracter main()
{
27. Se definete constanta simbolic SIR int k;
astfel: scanf(%d,&k);
#define SIR EXAMEN ADMITERE printf(%x,k);
Efectul apelului lui printf(%-10.6s,SIR) }
este urmtorul : n urma lansrii n execuie a programului,
a) EXAMEN ADMITERE valoarea lui k introdus va fi 65. Care va fi
b) EXAMEN (4 spaii in fa) rezultatul afiat ?
c) EXAMEN (4 spaii dup) a) 65 b) 41 c) 32 d) 60
d) EXAMEN ADM
34. Precizai care sunt valorile afiate, dac se
28. Care este efectul apelului funciei vor citi n ordinea indicat valorile numerice 5 2
printf(%o,a) unde a este o variabil de -3:
tip ntreg de valoare 0xAF5 : { int a, b;
scanf(%d%d%d,&a,&b,&a); 36. Scriei o instruciune care afieaz valoarea
printf(%d,a); variabilei ntregi total :
printf(%d\n,b); a) printf(%s\n,total);
printf(%d,a+b); b) printf(%d\n,total);
} c) printf(%s\n,total);
a) 5 2 d) printf total;
7
b) 3 2 37. Scriei o instruciune care citete un
-1 caracter i-l memoreaz n variabila litera :
c) 5 2 7 a) scanf(litera);
d) exist erori de sintax b) scanf(litera);
c) scanf litera;
35. Care sunt valorile tiprite de programul d) scanf(%c,&litera);
urmtor :
void main(void) 38. Scriei o instruciune care afieaz valoarea
{ int a,b; unei variabile de tip real small_value cu trei
a=5; b=13; zecimale exacte :
printf(%d+%2d=%2d,a, b, a+b); a) printf(small_value:3);
}
a) a+b=a+b b) 5+13=18 b) printf(%.3f\n,small_value);
c) printf(%s\n,small_value:3
c) 5+13:2=18:2 d) a+b:2=a+b:2 );
d) printf %.3f,small_value;
Cap.4 Operatorii limbajului C

Limbajul C dispune de o gam extins de operatori. Pe lng setul de operatori uzuali, limbajul
are definii operatori care ofer faciliti asemntoare limbajelor de asamblare. Exist astfel operatori
aritmetici, operatori de atribuire simpl sau compus, operatori logici, operatori de prelucrare pe bii etc.

4.1 Precedena operatorilor

Precedena operatorilor determin ordinea de evaluare a operaiilor dintr-o expresie. n funcie


de preceden, operatorii C sunt mprii n 15 categorii prezentate n tabelul urmtor :

Categorie Operatori Semnificaie


1. Prioritate maxim ( ) Apel de funcie
[ ] Expresie cu indici
. Selectori de membru la structuri
2. Operatori unari ! Negare logic
~ Negare bit cu bit (complementare cu 1)
+ - Plus i minus unari
++ -- Incrementare/decrementare (pre i post)
& * Obinerea adresei/indirectare
sizeof Dimensiune operand (n octei)
(tip) Conversie explicit de tip - cast
3. Operatori de * / nmulire/mprire
multiplicare % Restul mpririi ntregi
4. Adunare , scdere + - Plus i minus binari
5. Deplasri << >> Deplasare stnga/dreapta pe bii
6. Relaionali < <= Mai mic/mai mic sau egal
> >= Mai mare/mai mare sau egal
7. Egalitate == Egal
!= Diferit
8. & SI logic bit cu bit
9. ^ SAU EXCLUSIV bit cu bit
10. | SAU logic bit cu bit
11. && SI logic
12. || SAU logic
13. Op. condiional ?: Operatorul condiional (ternar)
14. Operatori de = Atribuire simpl
atribuire *= /= Atribuire produs , ct , rest
%=
+= -= Atribuire sum , diferen
&= ^= Atribuire SI , SAU EXCLUSIV , SAU (bit)
!=
<<= Atribuire cu deplasare stnga/dreapta
>>=
15. Virgula , Evaluare expresie1 , expresie2 . Valoarea
rezultatului este expresie2.

Cei din prima categorie au prioritatea maxim. Precedena descrete cu ct crete numrul
categoriei din care face parte operatorul. Operatorii din aceeai categorie au acelai grad de
preceden. Ordinea de evaluare a operaiilor este de la stnga la dreapta, cu excepia operatorilor
unari (categoria 2), a operatorului condiional (categoria 13) i a operatorilor de atribuire (categoria 14)
care au ordinea de evaluare de la dreapta la stnga.
Totui ordinea de efectuare a operaiilor nu este ntotdeauna perfect determinat. Se poate
face o reorganizare a expresiilor pentru a obine un cod mai eficient, dar ordinea de efectuare a
operaiilor nu este strict definit. n funcie de context, acelai operator poate avea semnificaii diferite.
Spre exemplu operatorul & (ampersand) poate fi considerat ca :
- operatorul binar SI pe bii (a & b)
- operatorul unar, adresa unui operand (&a)
Semnificaia depinde de numrul de argumente folosite, unul sau dou .

4.2 Operatorul de atribuire simpl

Acest operator (=) realizeaz memorarea valorii unei expresii ntr-o variabil. Are sintaxa :
variabila=expresie;
Efectul este stocarea valorii expresiei din membrul drept la adresa variabilei scrise n membrul stng.
Exemplul 1:
char c;
int i,k;
float x;
c=a;
i=3;
k=d;
/* k=100 ; d de tip caracter este convertit la un tip ntreg */
x=c+i;
/* x=100 ; se face conversie la un tip ntreg : 97+3=100 */
n plus, atribuirea nsi are o valoare, i anume valoarea variabilei din stnga dup memorarea
coninutului valorii expresiei. Datorit acestui efect, rezult n final o valoare a expresiei de atribuire
care poate fi folosit direct ntr-o alt atribuire. De aceea este permis atribuirea multipl.
Exemplul 2 :
int i,j,k ;
i=j=k=1;
care este echivalent cu secvena :
k=1; j=k; i=j;
Se observ o mai bun compactare a codului surs n primul caz, de folosire a atribuirii multiple. Toate
cele trei variabile au dup atribuire valoarea 1.
Exemplul 3:
int i,j,k;
j+1=i;
i=1+j=k;
Ambele instruciuni de atribuire sunt incorecte, pentru c j+1 nu este o variabil.

4.3 Operatori aritmetici

Operatorii aritmetici din C pot folosi, mai puin operatorul modulo care poate lucra numai cu
numere ntregi, att numere ntregi ct i numere reale.
Exemplul 1 : Folosirea operatorilor aritmetici .
int i,j,n;
float x;
n=10*4-7; /* n=33 */
i=9/2; /* i=4 ca rezultatul mpririi a dou numere ntregi */
j=n%i; /* j=1 ca restul mpririi a dou numere ntregi */
x=n; /* x=33.00 - ca numr real*/
x=x%i;
/* se obine eroare operatorul % fiind definit numai pentru numere ntregi*/
Exemplul 2 : La acelai rezultat conteaz tipul variabilei din stnga .
int i;
float x;
i=7./2;
/* i=3 pentru c 3.5 real este convertit la tipul ntreg al lui i */
X=7./2; /* x=3.5 pentru c x este de tip real */
n concluzie, rezultatul este convertit la tipul variabilei din membrul stng al atribuirii.
Exemplul 3: n operaiile cu constante conteaz dac ele sunt de tip ntreg sau real.
int i,j;
i=5/2+7/2;
/* rezultatele mpririi dintre dou numere ntregi sunt convertite tot la
numere ntregi i i=2+3=5 */
j=5./2+7/2.;
/* rezultatele mpririi dintre un numr real i un numr ntreg sunt
numere reale, 2.5+3.5=6.0 , deci j=6 */
Spre deosebire de ceilali operatori aritmetici, operatorii de incrementare i decrementare sunt specifici
limbajelor de asamblare. Ei sunt mult mai rapizi, efectul lor constnd n mrirea/micorarea variabilei cu
1 n modul urmtor :
- ++var sau var++ : variabila var este mrit cu o unitate, n primul caz, nainte de utilizarea
ei (preincrementare), iar n al doilea caz, dup utilizarea ei (postincrementare )
- --var sau var-- : variabila var este micorat cu o unitate, n primul caz, nainte de utilizarea
ei (predecrementare), iar n al doilea caz, dup utilizarea ei (postdecrementare)
Are importan dac operatorii de incrementare i decrementare se folosesc la stnga sau la dreapta
variabilei.
Exemplul 4:
int i,j=7;
i=j++; /* i=7 , j=8 */
sau i=++j; /* i=8 , j=8 */
Exemplul 5:
int a=2,b=3,c,d;
c=d=(a++ +1)b--; /* a=3 , b=2 , d=0 , c=0 */

4.4 Operatorii relaionali

Operatorii relaionali (categoriile 6 i 7) pot fi folosii pentru date de tip aritmetic i pointeri.
Rezultatul este 0 dac relaia nu este ndeplinit i 1 dac este ndeplinit.
Exemplu :
int egal,x,y;
x=17;
y=2*x-1;
egal=x==y; /* egal=0 */

4.5 Operatori logici

Cum n limbajul C nu exist tipul boolean, operatorii logici admit operanzi de orice tip scalar
(simplu) pe care i interpreteaz conform comparaiei cu 0. Dac valoarea este 0, expresia este
considerat fals, iar dac valoarea este nenul, expresia se consider adevrat. Rezultatul unei
expresii logice este de tip ntreg i se bazeaz pe conveniile : adevrat=1 , fals=0.

Tabela de adevr a operatorilor logici


x y x && y x || y !x
0 0 0 0 1
0 !=0 0 1 1
!=0 0 0 1 0
!=0 !=0 1 1 0

Exemplul 1: Dou forme echivalente pentru verificarea egalitii lui x cu 0.


x==0 sau !x
Exemplul 2 : Mai multe variante de verificare a condiiei ca x i y s fie ambii 0.
a) x==0 && y==0
b) !x && !y
c) !(x!=0||y!=0)
d) !(x||y)

4.6 Operatorii la nivel de bit

Posibilitatea utilizrii operatorilor pe bii ofer limbajului C faciliti asemntoare cu cele ale
limbajelor de asamblare. Operanzii pot fi numai tipuri ntregi .
Fie biii b1 i b2. Rezultatul aplicrii operatorilor pe bii este :

Operatori pe bii
b1 b2 b1 & b2 b1 ^ b2 b1 | b2 ~ b1
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 0 1 0

Operatorii <<, respectiv >>, sunt numii operatori de deplasare pe bii la stnga, respectiv la
dreapta. Ei au sintaxa :
a<<n /* echivalent cu a*2n */
a>>n /* echivalent cu a/2n */
Exemplul 1: Fie declaraia int j;
atunci expresia j&1 are valoarea 0 dac j este par i valoarea 1, dac j este impar.
Exemplul 2:
int t=1,j=6,k,n;
t=1<<j; /* t=1*26 */
k=t>>2; /* k=26/22=24 */
n=t&k;
/* n=0 pentru c t i k nu au nici un bit de pe aceeai poziie egal cu 1 */
Exemplul 3: Fie constanta 0u, o constant ntreag de tip unsigned care se reprezint pe 16 bii, deci
este practic reprezentat ca 16 de 0. Operaia ~(0u) neag cei 16 bii de 0 care vor lua valoarea 1, deci
se va obine valoarea 216-1=65535.
Exemplul 4: Tiprirea rezultatului operaiilor pe bii a dou numere.
#include<stdio.h>
void main()
{ int a,b;
printf(introduceti cele doua numere : );
scanf(%d %d,&a,&b);
printf(a|b=%d\n,a|b);
printf(a&b=%d\n,a&b);
printf(a^b=%d\n,a^b);
}
Exemplul 5: Operatorii | i & pot fi folosii pentru a seta sau terge anumite cmpuri de bii.
(k&1<<j)>>j ; /* determin valoarea bitului de pe poziia j */
k=k&~(1<<j); /* seteaz bitul de pe poziia j la 0 */
k=k|1<<j; /* seteaz bitul de pe poziia j la 1 */
k=k^1<<j; /* complementeaz bitul de pe poziia j */
Exemplul 6: Programul determin numrul format prin extragerea a n bii consecutivi dintr-un numr
dat x ncepnd cu poziia p.
#include<stdio.h>
void main()
{ int n,p,x;
printf(numarul : ); scanf(%d,&x);
printf(numarul de biti : ); scanf(%d,&n);
printf(pozitia : ); scanf(%d,&p);
printf(numarul este : %d, (x>>p)&~(~0<<n));
}
n partea stng a operatorului & se elimin primii p bii prin deplasarea la dreapta. Pentru a extrage
cei n bii, se realizeaz n partea dreapt un filtru, setnd primii n bii pe 1 i tergndu-i pe ceilali.
Exemplul 7: Un caz concret de utilizare a operaiilor la nivel de bit este cel al reprezentrii mulimilor
de valori. Astfel, s presupunem c dorim s inem evidena literelor majuscule dintr-un ir de caractere
introduse de la consol. n acest scop se poate folosi cte un singur bit pentru a codifica absena (0)
sau prezena (1) fiecrei litere. Deoarece alfabetul latin este format din 26 litere, pentru a pstra
evidena tuturor majusculelor trebuie s folosim o variabil (m) de tip long (32 de bii). Dintre cei 32 de
bii din reprezentarea variabilei vom utiliza numai 26, informaia referitoare la o liter oarecare x fiind
pstrat n bitul din poziia Z-x. n absena majusculelor, toi biii fiind 0, condiia de mulime vid se
exprim sub forma !m. Includerea n mulime a unei majuscule x se realizeaz prin intermediul atribuirii:
m=m|(1L<<Z-x)
Se remarc utilizarea constantei 1L, de tip long. Dac n locul ei s-ar fi utilizat constanta 1 (implicit de
tipul int ), atunci informaiile referitoare la primele 10 litere din alfabet nu ar fi fost actualizate, deoarece
rezultatul deplasrii la stnga, cu mai mult de 15 bii, a unei valori de tip int este nul. Verificarea
prezenei n mulime a caracterului x se poate realiza n urmtoarele dou variante :
m&(1L<<Z-x) sau (m>>Z-x)&1

4.7 Operatori compui de atribuire

Operatorul de atribuire poate fi combinat cu o serie de operatori aritmetici i operatori la nivel


de bit rezultnd enunuri prescurtate i uneori optimizri ale timpului de execuie.
Expresia var= var operator expresie; mai poate fi scris i var operator = expresie;
Exist 10 combinaii posibile permise operatorilor de atribuire compus i anume :
- 5 combinaii cu operatori aritmetici : += , - = , *= , /= , %=
- 5 combinaii cu operatori pe bii : |= , &= , ^= , <<= , >>=
Executarea unei instruciuni care folosete operatori compui de atribuire este mult mai rapid
deoarece compilatorul, cunoscnd c primul operand i rezultatul au aceeai locaie de memorie,
folosete un numr mai mic de operaii, avnd nevoie de un timp de execuie mai mic dect atribuirea
n cazul general.
Exemplul 1: Folosirea operatorului de aflare a restului .
int k=6,j=5;
k%=j; /* k=6%5=1 */
Exemplul 2: Folosirea operatorului de deplasare pe bii .
int k=7,j=3;
k<<=j; /* k=k*23=7*8=56 */
Exemplul 3 : Folosirea operatorului de deplasare la dreapta pe bii i apoi a operatorului aritmetic de
adunare.
int a=3,b=5,c;
a+=b>>=c=2; /* c=2 , b=5/22=1 , a=3+1=4 */
Exemplul 4 : Folosirea operatorului SAU EXCLUSIV pentru interschimbarea valorilor a dou variabile.
unsigned int k=6,j=9;
k^=j^=k^=j;
Exemplul 5 : Folosirea operatorului I pe bii .
long k;
k&=~k; /* k=0 , indiferent de valoarea sa iniial */
Exemplul 6 :
unsigned short k;
short j;
k|=~k; /* k=216-1=65535 , indiferent de valoarea sa anterioar */
j|=~j; /* dac j este cu semn, atunci valoarea sa devine 1 */
Exemplul 7:
int k;
k^=k; /* k=0 , indiferent de valoarea sa anterioar */
Exemplul 8:
int k=-25;
k<<=2; /* k= -25*22= -100 */
4.8 Operatorul de conversie explicit (cast)

Pentru a modifica ordinea de evaluare a operaiilor n mod explicit, se folosete perechea de


paranteze rotunde. Dar perechea de paranteze rotunde poate fi folosit i ca operator. Acesta se
numete operator de conversie explicit, n limba englez cast. El este utilizat pentru ca operatorul s
poat alege explicit tipul dorit, preciznd ntre paranteze conversia cerut. Sintaxa de utilizare este:
(tip_conversie) expresie;
Este necesar utilizarea cast-ului cnd se dorete folosirea unui alt tip dect cel implicit.
Exemplul 1:
float a,n;
a=(int)sqrt(n); /* se determin partea ntreag a lui radical din n */
Exemplul 2:
int a, b;
c=(double) a/b; /* rezultatul real al mpririi a dou numere ntregi */

4.9 Operatorul sizeof

Efectul aplicrii operatorului sizeof este aflarea dimensiunii n octei a unui tip de date sau a
rezultatului unei expresii. Sintaxa de utilizare este sizeof(expresie);
Perechea de paranteze rotunde este obligatorie. Deoarece tipul operanzilor este determinat
nc de la compilare, evaluarea se poate face i n etapa de preprocesare.
Exemplu :
sizeof(double); /* are valoarea 8 */
long a[100]; /* tablou cu 100 elemente de tip long */
sizeof(a); /* are valoarea 100*4=400 */

4.10 Operatorii de adresare

Se utilizeaz pentru obinerea adresei unui element sau pentru obinerea coninutului de la o
anumit adres. Cazurile tipice n care sunt folosii sunt :
- accesul la cmpurile unei structuri sau ale unei uniuni
- memorarea adresei unui element
- accesul indirect la un element
- accesul la un element al unui tablou
Operatorii de adresare sunt :
[ ] indexare
. selecie direct
selecie indirect
& determinare adres
* adresare indirect

4.11 Operatorul condiional

Este un operator cu trei operanzi. Se folosete pentru situaiile n care exist dou variante de
obinere a rezultatului, n funcie de ndeplinirea unei condiii. Are sintaxa :
expr_cond ? rezultat_1 : rezultat_2;
Semnificaia este :
daca expr_cond atunci rezultat=rezultat_1
altfel rezultat=rezultat_2
Exemplul 1:
double max,a,b;
max=(a>b)?a:b; /* se determin maximul a dou numere */
Exemplul 2:
unsigned k;
printf(%s,k?diferit de 0 :egal cu 0);
/* se afieaz dac numrul k este sau nu diferit de 0 */
Exemplul 3 : Determinarea maximului a trei numere.
max=(a>b)?(a>c?a:c):(b>c?b:c);
Exemplul 4 : Tiprete relaia dintre dou valori ntregi.
printf(%d %c %d\n,a,(a>b)?>:(a<b)?<:=,b);

4.12 Operatorul virgul

De obicei, virgula este folosit ca delimitator pentru declaratori, variabile sau parametri ai unei
funcii. O alt semnificaie este aceea c reprezint o expresie care evalueaz componentele sale n
ordine de la stnga la dreapta.
Exemplul 1:
int i=7,a,j=3;
a=i,i+=j; /* a=7 , i=10 */
sau
i+=j,a=i; /* i=10 , a=10 */
Exemplul 2:
double x, y, temp;
(x>y)?(temp=x, x=y, y=temp):y ;
/* are ca efect ordonarea cresctoare a variabilelor x i y ; ca rezultat se
obine cea mai mare dintre valorile x i y */

4.13 Exerciii i teste gril

1. Fie expresia a<b&&a<c. S se verifice c) operatorii relaionali au o


afirmaiile urmtoare : preceden mai mare dect
a) expresia este incorect operatorii logici
sintactic d) toi operatorii relaionali au
b) este corect i este echivalent acelai nivel de prioritate
cu : (a<b)&&(a<c)
5. Fie declaraia : int i,x,y; S se verifice
c) este corect i este echivalent
cu expresia : a<(b&&a)<c care expresii sunt corecte :
a) (i+1)++ b) i+++ 1 c) --x+y
d) ++i++ e) &x+1 f) &(x+1)
2. S se verifice utilizarea cror operaii este g) -x&1
permis :
a) a-=b; b) -a=b;
c) -a=-b; d) a<<=2; 6. Precizai efectul operaiilor :
int x,y,z;
scanf("%d" , &x); y-=(z=x,x<0);
3. Fie o expresie care conine operatori
Pentru obinerea rezultatului erau necesare
aritmetici, relaionali i de atribuire i nu conine
parantezele rotunde ?
paranteze. S se precizeze, care va fi ordinea
de evaluare a operatorilor ?
7. Fie declaraia : unsigned n;
a) de atribuire, relaionali, arit-
metici Care din expresiile urmtoare determin octetul
b) aritmetici,relaionali, de atri- inferior al variabilei n ?
buire a) n%256 b) n>>4 c) n & 0xFF
c) de atribuire, aritmetici, rela- d) (n<<4)>>4 e) n>>8
ionali f) (n<<8)>>8

4. Care din urmtoarele afirmaii sunt 8. Fie definiiile :


unsigned m=0xF0F,n=0xF0F0;
adevrate ?
a) operatorii pe bii au ordinea de char format[]="\n n=%4x";
evaluare naintea operatorilor S se gseasc care vor fi valorile afiate dup
logici urmtoarele operaii :
b) operatorii de atribuire compus a) printf(format,m);
au o precedena mai mic dect b) printf(format,n);
operatorul de atribuire simpl c) printf(format,~m);
d) printf(format,~n); 16. S se transcrie sub form de expresii de
e) printf(format m|n); atribuire expresiile de mai jos :
f) printf(format,m&n); a) y=2x3-8x2+7x-1
g) printf(format,m^n); b) y=(ax+b)/(cx+d)
c) a=max(x+y,x-y)
9. Evaluai rezultatul i corectitudinea d) m=max(3x2+1,6x-20)
urmtoarelor secvene : e) x=1, 5a3-2, 8a2+3, 7a-1
int i=1,j=2,k=-7; f) x=a*b*c-(a-b)(a-c)+(b-c)
double x=0.0,y=2.5; g) dac (x+y)!=0 atunci z=x/(x+y)
a) -i-5*j>=k+1 b) 3<j<5 altfel z=0
c) i+j+k==-2*j d) x/!!y
e) x&&i||j-3 17. S se transcrie sub form de expresie de
atribuire :
10. Ce valoare vor avea variabilele x si y dup a) y=|2x+10|
secvena de instruciuni ? b) a=max(x,y,z)
int x=7,y; c) dac x>y si x>z atunci u=v,
y=x<<=2; altfel u=v/2
a) 32 b) 28 c) 64 d) dac x>y sau x>z,atunci
p=a+b,altfel p=a-b
11. S se determine care din urmtoarele e) dac nici una din condiiile
expresii sunt corecte : i>j, i>k, i>n nu are loc, atunci
a) z=x++==4||y--<5; x=a, altfel x=b
b) a=x==y==z; f) dac c are ca valoare codul
ASCII al unui caracter alb,
12. Realizai cu ajutorul operatorului condiional atunci i se mrete cu 1, altfel
"?" urmatoarele operaii : se micoreaz cu 1
a) determinarea valorii absolute a g) dac a>b>1 i a<10, atunci
unui numr x x=a/b, altfel x=100
b) determinarea minimului n h) dac c are ca valoare un cod
valoare absolut a dou numere diferit de codul caracterelor
c) determinarea maximului a trei albe, atunci i=x+y, altfel i=x-y
numere i) dac valorile variabilelor a,b
si c pot reprezenta lungimile
laturilor unui triunghi, atunci
13. Ce face urmtorul program ?
#include<stdio.h> x are ca valoare perimetrul
main() acestui triunghi, altfel are
{ int i,j; valoarea 0.
scanf("%d% d" ,&i ,&j);
printf("\n i=%d , j=%d", i, j); 18. Fie declaraia : int x,i,j; S se scrie o
i=i-j , j=j+i , i=j-i; expresie care are ca valoare ntregul format cu
printf("\n i=%d , j=%d", i, j); j bii din x , ncepnd cu al i-lea bit.
}
a) realizeaz un calcul algebric 19. double x=1/2.0+1/2;
oarecare printf(x=%.2f\n,x);
b) adun valorile absolute ale lui Ce se va tipri dup execuia codului de mai
i i j sus ?
a) x=0.00 b) x=0.25
c) interschimb valorile varia- c) x=0.50 d) x=0.75
bilelor i i j
20. Care va fi valoarea lui i dup execuia
14. Care din cele trei expresii sunt echivalente urmtoarelor instruciuni :
ntre ele ? i=4; i=i?18:2;
a) 1<<n+1; b) 1<<(n+1) a) 4 b) 18
c) (1<<n)+1 c) 2 d) 9
15. Fie expresia : (int) (sqrt(n)) 21. Se declar variabila
Are importan folosirea perechii de paranteze unsigned int a=0x3FF
rotunde pentru tipul int ? Dar pentru sqrt(n) ? Care este valoarea expresiei a>>3 ?
a) 3FF b) 0xBF
c) 0x7F d) 0x3FC
a) 0xE b) 0xF
22. Se dau int a=0,b=1,c=2.Valoarea c) 0x1 d) 0x8
variabilei cp din expresia:
cp=rez=a+b+c>c&&b*c<a+b*c 31. Fie relaia 4/5|3+4%5&3. Care este
este : rezultatul evalurii ei ?
a) 1 b) 0 a) 4 b) 3 c) 1 d) 1
c) 2 d) 1.5
32. Fie secvena de cod :
23. Se d variabila b=0xFF10 de tip int x=1*2+4/4+3%5;
unsigned int i expresia b>>3. Efectul Valoarea lui x este :
acestei expresii este : a) se va genera eroare b) 3
a) 1FF2 c) 6 d) 5
b) valoarea binar a variabilei
b 33. Presupunnd urmtoarea secven de cod :
c) 0xFF13 d) 0x1FE2 int a=5,b=2;
float c=a/b;
24. Se dau variabilele de tip ntreg Care va fi valoarea lui c ?
a=0x125,b=0455,c=293,d=0xAF,x,y a) 2.5 b) 2 c) 3 d) 1
i expresia x=y=(a==b&a==c)^d. Variabilele
x si y au valoarea : 34. Avem urmtorul program :
a) AF b) 0257 int main()
c) 10101111 d) 0xAF { float x, y, z;
x=1.3; y=1.2; z=x%y;
25. Fie expresia de mai jos : return 0;
(x>-1) && !(x>1)||(x>=5) }
Intervalul selectat este : La sfritul programului variabila z va avea
valoarea :
a) x (-1,1] [5, ) a) 0.1 b) 0 c) 1
b) x (- ,-1) [1, ) d) programul genereaz eroare la
c) x (- ,-1) (1,5) compilare
d) x [-1,1] [5, )
35. Fie secvena :
26. Care este intervalul descris de expresia double x,y;
logic de mai jos ? .
(x<=-2)||(x>-1)&&!(x>=1)||(x>5) x=9; y=3(x-10);
..
a) x (- , -2] (-1,1] [5, )
Care afirmaie este adevarat :
b) x (- ,-2] [-1,1] (5, ) a) y=-3 b) y=3
c) x(- ,-2] (-1,1] [5, ) c) eroare la compilare deoarece
d) x (- ,-2] (-1,1) (5, ) lipsete operator
d) eroare la compilare deoarece nu
27. Care din urmtorii operatori relaionali este se poate scdea un double
invalid ?
a) == b) <> c) < d) > 36. Urmrii secvena de mai jos i precizai
valoarea variabilei y:
28. Care din urmtorii operatori are prioritatea int a, b=3;
cea mai mic ? int x=2;
a) == b) + c) d) ! int z=2*b+x;
a) 2 b) 3 c) 4 d) 5
e) secvena este eronat
29. Dup execuia secvenei de cod, ce valoare
va avea variabila z ?
int z; 37. tiind c n conformitate cu standardul
int x=5; ASCII literele mari au codurile succesive
int y=-10; ncepnd cu 65, precizai care dintre variabilele
z:=x--y; x, y, z i u vor avea valoarea 2 la finele
a) 10 b) 5 c) 5 d) 15 execuiei programului de mai jos.
void main()
30. Ce rezultat va produce operaia : {
0xB & 0x5 int x=-3, y=1, z=2, u;
x++;
y+=2; b) x=y>0 ? b: a;
z-=1+sqrt(y+2); // radical c) x=!y>0 ? b : a;
de ordin doi d) y>0 ? x=a :x=b;
u=A-C; e) !(y>0) ? x=b : x=a;
}
a) x b) y c) z d) u e) nici una 43. Ce valoare afieaz programul urmtor ?
#include<stdio.h>
38. Se consider variabilele ntregi x,y i z, void main()
fiind cunoscute valorile x=4 i y=2. Care {
dintre expresiile de mai jos are valoarea 0 ? int x=5, y;
a) x+y>x%y+1 b) z=(x-y!=0) y=(sizeof(x-1)==sizeof(int)) ?
c) x-2*y=0 d) !x sizeof(x) : sizeof(3);
e) x && y printf(%d, y);
}
39. tiind c a, b, c, d, x sunt variabile reale cu a) 3 b) 1 c) 2 d) 4
a<=b i c<=d, scriei sub form de expresie : e) programul este eronat
x[a, b] sau x[c, d].
44. Ce valori va afia programul urmtor ?
a) (x>=a||x<=b)&&(x>=c||x<=d) #include<stdio.h>
b) void main()
((x>=a)&&(x<=b))||((x>=c)&&(x<=d)) {
c) (!(x<a)&&!(x>b))||(!(x<c)&&! int a=10, b=6, c=4, d;
(x>d)) d=(c=a-6, a=b%c, b+=a, a/2);
d) ((x>=a)||(x<=b))&&((x>=c)|| printf(\n%d %d %d %d,a,b,c,d);
(x<=d)) }
e) (x>=a && x<=b) || (x>=c && x<=d) a) 0 16 6 5 b) 2 8 4 1
c) 4 2 8 1 d) 6 0 16 5
40. Fie declaraiile de variabile: e) alte valori
int x=4, z=13;
float z;
45. Ce valoare afieaz programul de mai jos ?
Care dintre instruciunile de mai jos nu atribuie #include<stdio.h>
corect valoarea 8.5 variabilei z ? void main()
a) z=(x+y)/2.; {
b) z=((float)x+y)/2: int a=3, b=2, n=4, x;
c) z=(x+y.)/2; x=(a<<n) + (a&b) + (n|b);
d) z=(x+y)/(float)2; printf(%d, x);
e) z=(float)(x+y)/2; }
a) 2 b) 8 c) 51
41. Ce afieaz programul urmtor, dac d) 56 e) programul este greit
valoarea citit de la tastatur este 2 ?
#include<stdio.h> 46. Fie variabilele ntregi a=1,b=2,c=3,d=4.
void main()
Care dintre construciile de mai jos sunt
{
expresii scrise corect, cu valoarea 0 ?
int x,y,z; a) !d b) a+b<d c) a*b+c
scanf(%d, &x); d) a=b<c e) (a<b)!=(b<c)
y=--x;
y+=3;
47. Pentru care dintre seturile de valori ale
z=x-2*y++;
variabilelor x, y, z de mai jos expresia
printf(%d, z++);
} (x<y)<((z!=x)<((z-y)<x) are valoarea 1?
a) 9 b) 8 c) 7 a) x=3; y=5; z=4 b) x=4; y=3; z=4
d) 6 e) 5 c) x=3; y=4; z=3 d) x=5; y=4; z=3
e) x=5; y=5; z=5
42. Fie trei variabile ntregi a, b, x. Precizai
48. Care dintre urmtoarele expresii au
care dintre expresiile condiionale de mai jos nu
valoarea 1 dac i numai dac valorile
este o transcriere corect a enunului: dac
numrul y este pozitiv, atunci x ia variabilelor ntregi x i y sunt numere pare ?
a) x-y==2 b) x*y%4==0
valoarea lui a, n caz contrar x ia
c) (x+y)%2==0 d) y%x==2
valoarea lui b. e) (x%2==0)&&(y%2==0)
a) x=(y>0) ? a : b;
49. Care dintre urmtoarele expresii sunt x=A;
adevrate dac i numai dac valorile printf(%d, sizeof(x));
variabilelor x i y sunt numere naturale c=A;
consecutive ? printf(%d,sizeof(c));
a) x-y==1 b) (x==1)&&(y==2) printf(%d,sizeof(float)-2);
b) (x-y==1)&&(y-x==1) x=sizeof(int); x=++x/2;
c) y==x+1 printf(%d, x==2);
e) (x-y==1)||(y-x==1) }
a) nici o data b) o data
50. Se consider urmtoarele declaraii de c) de 2 ori d) de 3 ori
variabile : int a,b,e; float c,d;. Care e) de 4 ori
dintre instruciunile de mai jos sunt incorecte ?
a) a=a*b; b) e=a<c; 55. Ce valori afieaz programul urmtor ?
c) b=a+a/b; d) d=(a+b)/2; #include<stdio.h>
e) c*d=a-b; void main()
{
51. Fie variabilele x,y,z de tipul int, fiind int x=10, y=6, m, n, p;
cunoscute valorile iniiale x=3, y=5. Care n=(m=x++, y++, p=x+y);
dintre instruciunile de mai jos trebuie executat printf(\n%d %d %d,m n,p);
astfel nct, dup execuie, valoarea variabilei z }
s fie 21 ? a) 10 18 16 b) 11 18 18
a) z=2*x+3*y--; b) z=2*x+3*--y; c) 10 18 18 d) 11 18 17
c) z=2*x--+3*y; d) z=2*--x+3*y; e) 10 18 17
e) z=2*x+3*y;
56. Ce valoare putem introduce la citirea
52. Fie trei variabile ntregi a,b,x. Scriei cu variabilei y, astfel nct programul de mai jos s
ajutorul unei expresii condiionale enunul tipreasc 1 ?
dac x nu aparine [a,b] , atunci #include<stdio.h>
x ia valoarea lui a, n caz contrar void main()
{
x ia valoarea lui b.
int x=2, y, z;
a) x=((x<a)||(x>b))? a : b;
scanf(%d, &y);
b) x=(x<a||x>b)? a : b;
z=y+3*x++;
c) x=((x<a)&&(x>b))? a : b;
printf(\n%d,(z%2==0&&x>=1)?1:0);
d) x=(x<a)||(x>b)? b : a;
}
e) (x<a)||(x>b))? (x=a) : (x=b);
a) 2 b) 3 c) 4
d) orice valoare par
53. tiind c n standardele ASCII caracterele e) orice valoare impar
liter mare au codurile succesive ncepnd cu
65, deducei ce valoare va afia programul
57. Fie variabilele a,b,c de tipul int, cu valorile
urmtor.
a=11, b=5, c=7. Care dintre expresiile de mai
#include<stdio.h>
void main() jos are valoarea 1?
a) (a|~b)&1 b) (~a&b)|1
{
c) (a&~b)|1 d) (a&b)|~1
int x,y,z,p; char m,n;
e) (~a|b)&1
m=C; n=A;
x=m; y=2*m-n; z=3;
p=x<y?(y<z ? z:y):(z<x?x:z); 58. Precizai valoarea pe care o va avea
printf(\n%d, p); variabila c n urma execuiei programului de
} mai jos:
#include<stdio.h>
a) 1 b) 3 c) 69 d) 67 e) 0
void main()
{
54. tiind c valorile de tipul int se memoreaz char c=d;
pe 2 octei, iar cele de tipul float pe 4 octei, de int n=99;
cte ori va afia programul urmtor valoarea 2? c=n+1=c-1;
#include<stdio.h>
}
void main()
a) d b)c c) b
{
d) NULL e) atribuirea este
int x; char c;
greit
Cap.5 Instruciunile limbajului C
Limbajul C a fost prevzut cu instruciuni menite s permit realizarea simpl a structurilor
proprii programrii structurate. Structura secvenial se realizeaz cu ajutorul instruciunii compuse,
structura alternativ cu ajutorul instruciunii if, structura repetitiv condiionat anterior, prin intermediul
instruciunilor while i for, structura selectiv cu ajutorul instruciunii switch, iar structura repetitiv
condiionat posterior cu ajutorul instruciunii do-while.
Limbajul C are i alte instruciuni care reprezint elemente de baz n construirea structurilor
amintite mai sus. Astfel de instruciuni sunt : instruciunea expresie i instruciunea vid. Alte
instruciuni prezente n limbaj asigur o flexibilitate mai mare n programare. Acestea sunt instruciunile:
return, break, continue i goto .

5.1 Instruciunea vid

Se reduce la punct i virgul (;). Ea nu are nici un efect. Instruciunea vid se utilizeaz n
construcii care cer prezena unei instruciuni, dar nu trebuie s se execute nimic n punctul respectiv.
Astfel de situaii apar frecvent n cadrul structurii alternative i repetitive, aa cum se va vedea n
continuare.

5.2 Instruciunea expresie

Se obine scriind punct i virgul dup o expresie. Deci, instruciunea expresie are sintaxa :
expresie ;
n cazul n care expresia din compunerea unei instruciuni expresie este o expresie de atribuire, se
spune c instruciunea respectiv este o instruciune de atribuire. Un alt caz frecvent utilizat este acela
cnd expresia este un operand ce reprezint apelul unei funcii. n acest caz, instruciunea expresie
este o instruciune de apel a funciei respective.
Exemplul 1:
int x; x=10;
Este o instruciune de atribuire, variabilei x i se atribuie valoarea 10.
Exemplul 2:
double y; y=y+4; sau y+=4;
Este o instruciune de atribuire, care mrete valoarea lui y cu 4.
Exemplul 3:
putch(c-a+A);
Este o instruciune de apel a funciei putch.
Exemplul 4:
double a; a++;
Este o instruciune expresie, care mrete valoarea lui a cu unu.
Exemplul 5:
double a; ++a;
Are acelai efect ca i instruciunea expresie din exemplul precedent.
Observaie : Nu orice expresie urmat de punct i virgul formeaz o instruciune expresie efectiv.
De exemplu construcia a; dei este o instruciune expresie, ea nu are nici un efect.
Exemplul 6 : S se scrie un program care citete valorile variabilelor a, b, c, d, x de tip double i
afieaz valoarea expresiei (a*x2+b*x+c)/(a*x2+b*x+d) dac numitorul este diferit de 0 i 0 n caz
contrar.
#include<stdio.h>
#include<conio.h>
void main()
{ double a,b,c,d,x;
doube y,z,u;
clrscr();
printf(a=); scanf(%lf,&a);
printf(b=); scanf(%lf,&b);
printf(c=); scanf(%lf,&c);
printf(d=); scanf(%lf,&d);
printf(x=); scanf(%lf,&x);
y=a*x*x;
z=b*x;
u=y*x+z+d;
printf(exp=%g\n,u ?(y+z+c)/u:u);
getch();
}

5.3 Instruciunea compus

Instruciunea compus este o succesiune de instruciuni incluse ntre acolade, succesiune care
poate fi precedat i de declaraii :
{
declaraii
instruciuni
}
Dac declaraiile sunt prezente, atunci ele definesc variabile care sunt definite att timp ct controlul
programului se afl la o instruciune din compunerea instruciunii compuse.
Exemplu : Presupunem c ntr-un anumit punct al programului este necesar s se permute valorile
variabilelor ntregi a i b. Aceasta se poate realiza astfel :
{ int t;
t=a;a=b;b=t;
}
Variabila t este definit din momentul n care controlul programului ajunge la prima instruciune din
instruciunea compus (t=a;). Dup execuia ultimei instruciuni a instruciunii compuse, variabila t nu
mai este definit (nu mai ocup memorie).
Instruciunea compus se utilizeaz unde este necesar prezena unei instruciuni, dar
procesul de calcul din punctul respectiv este mai complex i se exprim prin mai multe instruciuni. n
acest caz instruciunile respective se includ ntre acolade pentru a forma o instruciune compus. Acest
procedeu de a forma o instruciune compus din mai multe instruciuni se utilizeaz frecvent n
construirea structurilor alternative i ciclice.

5.4 Instruciunea if

Are urmtoarele formate :


format1 : if(expresie)
instruciune;
format2: if(expresie)
instruciune1;
else
instruciune2;

La ntlnirea instruciunii if nti se evalueaz expresia din paranteze. Apoi, n cazul formatului
1, dac expresia are valoarea diferit de zero (adic true) se execut instruciune, altfel se trece n
secven la instruciunea urmtoare instruciunii if. n cazul formatului 2, dac expresia are o valoare
diferit de zero, atunci se execut instruciune1 i apoi se trece n secven la instruciunea aflat
dup instruciune2, altfel (condiia este zero, adic false) se execut instruciune2.
n mod normal, n ambele formate, dup execuia instruciunii if se ajunge la instruciunea
urmtoare ei. Cu toate acestea, este posibil i o alt situaie cnd instruciunile din compunerea lui if
definesc ele nsele un alt mod de continuare a execuiei programului.
Deoarece o instruciune compus este considerat ca fiind un caz particular de instruciune,
rezult c instruciunile din compunerea lui if pot fi instruciuni compuse. De asemenea, instruciunile
respective pot fi chiar instruciuni if. n acest caz se spune c instruciunile if sunt imbricate.
Exemplul 1: Se d funcia : y=3x2+2x-10, pentru x>0 i y=5x+10, pentru x<=0. S se scrie un
program care citete valoarea lui x i afieaz valoarea lui y.
#include<stdio.h>
#include<conio.h>
void main()
{ float x,y;
clrscr();
scanf("%f",&x);
if(x>0)
y=3*x*x+2*x-10;
else
y=5*x+10;
printf("x=%f\ty=%f\n",x,y);
getch();
}
Exemplul 2: S se scrie un program care citete valoarea lui x, calculeaz i afieaz valoarea lui y
definit ca mai jos :
y=4x3+5x2-2x+1 , pentru x<0
y=100 , pentru x=0
y=2x2+8x-1 , pentru x>0

#include<stdio.h>
#include<conio.h>
void main()
{ float x,y,a;
clrscr();
scanf("%f",&x);
a=x*x;
if(x<0)
y=4*x*a+5*a-2*x+1;
else
if(!x)
y=100;
else
y=2*a+8*x-1;
printf("x=%f\ty=%f\n",x,y);
getch();
}
Exemplul 3: S se scrie un program care citete valorile variabilelor nentregi a i b, calculeaz
rdcina ecuaiei : ax+b=0 i afieaz rezultatul.
#include<stdio.h>
#include<conio.h>
void main()
{ double a,b;
clrscr();
if(scanf("%lf %lf",&a,&b)!=2)
/* valideaz numrul coeficienilor reali citii */
printf("coeficienti eronati\n");
else
if(a)
printf("a=%g\tb=%g\tx=%g\n",a,b,-b/a);
else
if(!b)
printf("ecuatie nedeterminata\n");
else
printf("ecuatia nu are solutie\n");
getch();
}
Programul de mai sus conine o instruciune if imbricat. Pentru a mri claritatea programelor se
obinuiete s se decaleze spre dreapta (cu un tabulator) instruciunile din compunerea instruciunii if.
n acest program s-a realizat test relativ la valorile tastate pentru a i b. Dac funcia scanf() nu
returneaz valoarea 2, nseamn c nu s-au tastat dou numere de la terminal. De aceea, n astfel de
situaii se afieaz mesajul coeficieni eronai.
Exemplul 4: S se scrie un program care citete coeficienii a,b,c,d,e,f ai unui sistem de dou ecuaii
lineare cu dou necunoscute, determin i afieaz soluia acestuia atunci cnd are o soluie unic.
#include<stdio.h>
#include<conio.h>
void main()
{ double a,b,c,d,e,f,x,y,det1,det2,det;
clrscr();
if(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=6)
printf("coeficienti eronati\n");
else
if(!(det=a*e-b*d))
printf("sistemul nu este determinat\n");
else
{ det1=c*e-b*f;
det2=a*f-c*d;
x=det1/det;
y=det2/det;
printf("x=%g\ty=%g\n",x,y);
}
getch();
}

5.5 Funcia standard exit

Funcia exit are prototipul : void exit(int cod);


i el se afl n fiierele header stdlib.h i process.h. La apelul acestei funcii au loc urmtoarele
aciuni:
se videaz zonele tampon (bufferele) ale fiierele deschise n scriere
se nchid toate fiierele deschise
se ntrerupe execuia programului
Parametrul acestei funcii definete starea programului la momentul apelului. Valoarea 0 definete o
terminare normal a execuiei programului, iar o valoare diferit de 0 semnaleaz prezena unei erori
(terminarea anormal a execuiei programului).
n concluzie, putem apela funcia exit pentru a termina execuia unui program, indiferent de
faptul c acesta se termin normal sau din cauza unei erori.
Exemplu : S se scrie un program care citete valorile variabilelor a,b,c, calculeaz i afieaz
rdcinile ecuaiei de gradul 2 : ax2+bx+c=0.
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<stdlib.h>
void main()
{ double a,b,c,d,delta;
clrscr();
printf("coeficientul lui x patrat : ");
if(scanf("%lf",&a)!=1)
{ printf("coeficientul lui x patrat eronat\n");
exit(1); /* terminare la eroare*/
}
printf("coeficientul lui x : ");
if(scanf("%lf",&b)!=1)
{ printf("coeficientul lui x eronat\n");
exit(1);
}
printf("termenul liber : ");
if(scanf("%lf",&c)!=1)
{ printf("termenul liber eronat\n");
exit(1);
}
/* afieaz coeficienii citii */
printf("a=%g\tb=%g\tc=%g\n",a,b,c);
if(!a && !b && !c)
{ printf("ecuatie nedeterminata\n");
exit(0); /* terminare fr erori*/
}
if(!a&&!b)
{ printf("ecuatia nu are solutie\n");
exit(0);
}
if(!a)
{ printf("ecuatie de gradul 1\n");
printf("x=%g\n",-c/b);
exit(0);
}
delta=b*b-4*a*c;
d=2*a;
if(delta>0)
{ printf("ecuatia are doua radacini reale si
distincte\n");
delta=sqrt(delta);
printf("x1=%g\tx2=%g\n",(-b+delta)/d,
(-b-delta)/d);
exit(0);
}
if(!delta)
{ printf("ecuatia are radacina dubla\n");
printf("x=%g\n",-b/d);
exit(0);
}
printf("radacini complexe\n");
delta=sqrt(-delta)/d;
d=-b/d;
printf("x1=%g+i(%g)\n",d,delta);
printf("x2=%g-i(%g)\n",d,delta);
getch();
}

5.6 Instruciunea while

Are sintaxa : while(expresie) instruciune;


Prima parte din acest format constituie antetul instruciunii while, iar instruciune este corpul
ei. La ntlnirea acestei instruciuni nti se evalueaz expresia din paranteze. Dac ea are valoarea
true (este diferit de 0), atunci se execut instruciune. Apoi se revine la punctul n care se evalueaz
din nou valoarea expresiei din paranteze. n felul acesta, corpul ciclului se execut att timp ct
expresia din antetul ei este diferit de 0. n momentul n care expresie are valoarea 0, se trece la
instruciunea urmtoare instruciunii while.
Corpul instruciunii while poate s nu se execute niciodat. ntr-adevr dac expresie are
valoarea 0 de la nceput, atunci se trece la instruciunea urmtoare instruciunii while fr a executa
niciodat corpul instruciunii respective.
Corpul instruciunii while este o singur instruciune care poate fi compus. n felul acesta
avem posibilitatea s executm repetat mai multe instruciuni grupate ntr-o instruciune compus.
Corpul instruciunii while poate fi o alt instruciune while sau s fie o instruciune compus care s
conin instruciunea while. n acest caz se spune c instruciunile while respective sunt imbricate.
Instruciunile din corpul unei instruciuni while pot s defineasc un alt mod de execuie a
instruciunii while dect cel indicat mai sus. Astfel, se poate realiza terminarea execuiei instruciunii
while fr a se mai ajunge la evaluarea expresiei din antetul ei. De exemplu, dac n corpul unei
instruciuni while se apeleaz funcia exit, atunci se va termina execuia ciclului while, deoarece se
ntrerupe chiar execuia programului. Despre instruciunea while se spune c este o instruciune ciclic
condiionat anterior.
Exemplul 1: S se scrie un program care calculeaz i afieaz valoarea polinomului p(x)=3x2-7x-10
pentru x=1,2,.,10.
#include<stdio.h>
#include<conio.h>
void main()
{ int x;
clrscr();
x=1;
while(x<=10)
{ printf("x=%d\tp(x)=%d\n",x,3*x*x-7*x-10);
x++;
}
getch();
}
Exemplul 2: S se scrie un program care citete un ir de ntregi separai prin caractere albe i
afieaz suma lor. Dup ultimul numr se va tasta un caracter alb urmat de un caracter nenumeric (de
exemplu, caracterul sfrit de fiier <Ctrl>+Z, o liter, etc.), iar dup aceea se va aciona tasta Enter.
#include<stdio.h>
#include<conio.h>
void main()
{ int i,s=0;
clrscr();
while(scanf("%d",&i)==1)
s+=i;
printf("suma=%d\n",s);
getch(); }
Exemplul 3: S se scrie un program care citete un ntreg n[0,170], calculeaz i afieaz pe n!.
Avem: n!=1*2*3*..*n , pentru n >0 i 0!=1 , prin definiie.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{ int n,i;
double f;
clrscr();
printf("n=");
if(scanf("%d",&n)!=1)
{ printf("nu s-a tastat un intreg\n");
exit(1);
}
if(n<0 || n>170)
{ printf("n nu apartine intervalului [0,170]\n");
exit(1);
}
f=1.0;
i=2;
while(i<=n)
f*=i++;
printf("n=%d\tn!=%g\n",n,f);
getch();
}

5.7 Instruciunea for

Instruciunea for, ca i instruciunea while, se utilizeaz pentru a realiza o structur repetitiv


condiionat anterior. Are sintaxa :
for(exp1 ; exp2 ; exp3) /* antet */
instruciune; /* corpul ciclului*/
unde exp1, exp2 i exp3 sunt expresii.
Expresia exp1 se numete partea de iniializare a ciclului for, iar exp3 este partea de
reiniializare a lui. Expresia exp2 este condiia de terminare a ciclului for i ea joac acelai rol cu
expresia din ciclul while. Instruciunea for se execut astfel :
Se execut secvena de iniializare definit de exp1
Se evalueaz exp2. Dac are o valoare diferit de 0 (este true), atunci se execut instruciunea
care formeaz corpul ciclului. Altfel, (expresia are valoarea 0 adic false) se termin execuia
instruciunii for i se trece la instruciunea urmtoare.
Dup executarea corpului ciclului se execut secvena de reiniializare definit de exp3. Apoi se
reia execuia de la pasul 2 .
Ca i n cazul instruciunii while, instruciunea din corpul ciclului for nu se execut niciodat
dac exp2 are valoarea 0 chiar de la nceput. Expresiile din antetul lui for pot fi i vide. Caracterele
punct i virgul vor fi ntotdeauna prezente. n general, instruciunea for poate fi scris cu ajutorul unei
secvene n care se utilizeaz instruciunea while astfel :
exp1;
while(exp2)
{ instruciune;
exp3;
}
Aceast echivalare nu are loc ntr-un singur caz i anume atunci cnd, n corpul instruciunii se
utilizeaz instruciunea continue. Reciproc, orice instruciune while poate fi scris cu ajutorul unei
instruciuni for n care exp1 i exp3 sunt vide. Astfel, instruciunea while(exp) instruciune; este
echivalent cu instruciunea for(; exp ;) instruciune; .
O instruciune for de forma for(; ;) instruciune; este valid i este echivalent cu
instruciunea : while(1) instruciune;. Un astfel de ciclu se poate termina prin alte mijloace dect cel
obinuit, cum ar fi instruciunea de revenire dintr-o funcie, un salt la o etichet etc. Din cele de mai sus
rezult echivalena celor dou cicluri while i for. Se recomand folosirea instruciunii for n ciclurile n
care sunt prezente prile de iniializare i reiniializare, aa numitele cicluri cu pas.
Exemplul 1: S se scrie un program care citete ntregul n din intervalul [0,170], calculeaz i
afieaz pe n! .
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{ int n,i;
double f;
clrscr();
printf("n=");
if(scanf("%d",&n)!=1)
{ printf("nu s-a tastat un intreg\n");
exit(1);
}
if(n<0 || n>170)
{ printf("n nu apartine intervalului [0,170]\n");
exit(1);
}
for(f=1.0,i=2;i<=n;i++) f*=i;
printf("n=%d\tn!=%g\n",n,f);
getch();
}
Exemplul 2: Urmtorul program continu s cicleze pn cnd este tastat litera q. n loc s verifice
variabila de control a ciclului, instruciunea for verific dac de la tastatur a fost introdus caracterul q.
#include<stdio.h>
#include<conio.h>
void main()
{
int i;
char ch;
clrscr();
ch=a;
for(i=0;ch!=q;i++)
{ printf(pas: %d\n,i);
ch=getche();
}
getch();
}
n acest caz, testul de condiie care controleaz ciclul nu are nimic n comun cu variabila de control a
ciclului. Variabila ch a primit o valoare iniial pentru a ne asigura c ea nu conine accidental chiar
litera q n momentul n care programul ncepe execuia.
Exemplul 3: O alt variant a lui for este aceea c scopul su poate fi gol ca n programul urmtor:
#include<stdio.h>
#include<conio.h>
void main()
{
char ch;
clrscr();
for(ch=getche();ch!=q;ch=getche());
printf(\n am gasit pe q);
getch();
}
Instruciunea care asigneaz lui ch o valoare a fost mutat n interiorul ciclului. Aceasta nseamn c
atunci cnd ciclul pornete, este apelat funcia getche(). Apoi valoarea lui ch este testat mpreun cu
q, se execut inexistentul corp al lui for i apoi are loc o nou apelare a funciei getche() n seciunea
de incrementare a ciclului. Acest proces se repet pn cnd utilizatorul introduce litera q. Scopul lui
for poate fi gol deoarece limbajul C admite instruciunea vid.

5.8 Instruciunea do-while

Realizeaz structura ciclic condiionat posterior. Aceast instruciune poate fi realizat cu


ajutorul celorlalte instruciuni definite pn n prezent. Cu toate acestea, prezena ei n limbaj mrete
flexibilitatea n programare. Sintaxa ei este :
do
instruciune /* corpul ciclului */
while(expresie);
Instruciunea se execut n felul urmtor : se execut instruciune, se evalueaz expresie;
dac aceasta are o valoare diferit de 0 (true) atunci se revine la execuia instruciunii, altfel (expresia
are valoarea 0) se trece n secven, la instruciunea urmtoare instruciunii do-while.
Se observ c n cazul acestei instruciuni nti se execut instruciune i apoi se testeaz condiia de
repetare a execuiei ei. Instruciunea do-while este echivalent cu secvena :
instructiune;
while(expresie) instruciune;
n cazul instruciunii do-while corpul ciclului se execut cel puin o dat, spre deosebire de cazul
instruciunii while i for, cnd este posibil s nu execute niciodat.
Exemplul 1: S se scrie un program care afieaz factorii primi ai unui numr ntreg nenegativ
introdus de la tastatur.
#include<stdio.h>
#include<conio.h>
void main()
{ unsigned n,d=2,e;
clrscr();
printf("\nIntroduceti numarul : ");
scanf("%u",&n);
printf(" Desc. in factori primi este :\n");
do
{ e=0;
while(!(n%d))
{ n=n/d;
e++;
}
if(e) printf("%d ^ %d\n",d,e);
d=d+((d==2) ?1:2);
}while(n>1);
getch();
}
Exemplul 2: Faptul c ciclul do execut ntotdeauna corpul ciclului cel puin o dat face ca el s fie
perfect pentru a verifica intrarea ntr-un meniu. De exemplu, urmtorul program va repeta ciclul de citire
a opiunii pn cnd utilizatorul va introduce un rspuns valid:
#include<stdio.h>
#include<conio.h>
void main()
{
float a,b;
char ch;
clrscr();
printf(Doriti : \n);
printf(Adunare,Scadere,Multiplicare,Impartire? \n);
do{
printf(Introduceti prima litera : );
ch=getche();
printf(\n);
}while(ch!=A && ch!=S && ch!=M && ch!=I);
printf(Introduceti primul numar : );
scanf(%f,&a);
printf(Introduceti al doilea numar : );
scanf(%f,&b);
if(ch==A)
printf(%f,a+b);
else if(ch==S)
printf(%f,a-b);
else if(ch==M)
printf(%f,a*b);
else if(b) printf(%f,a/b);
getch();
}
Exemplul 3: Ciclul do este folositor n special cnd programul ateapt s se produc un anumit
eveniment. De exemplu, urmtorul program ateapt ca utilizatorul s tasteze litera q. Programul
conine o singur apelare a funciei getche().
#include<stdio.h>
#include<conio.h>
void main()
{
char ch;
clrscr();
do{
ch=getche();
} while(ch!=q);
printf(\n am gasit pe q);
getch();
}
Exemplul 4: Funcia kbhit() din header-ul conio.h este foarte folositoare cnd dorim s permitem
utilizatorului s ntrerup o rutin fr s l form s rspund la un mesaj. De exemplu, programul
urmtor afieaz o tabel cu procentul 5% aplicat unor valori care se incrementeaz cu 20. Programul
continu s afieze tabela pn cnd utilizatorul apas o tast sau pn cnd a fost atins valoarea
maxim.
#include<stdio.h>
#include<conio.h>
void main()
{ double amount;
amount=20.0;
printf(Apasati o tasta pentru stop.\n);
do{
printf(valoarea:%lf,procent:%lf\n,amount,amount*0.05);
if(kbhit()) break;
amount=amount+20;
}while(amount<10000);
}

5.9 Instruciunea continue

Aceast instruciune se poate utiliza numai n corpul unui ciclu. Ea permite abandonarea
iteraiei curente. Sintaxa ei este : continue;. Efectul instruciunii este urmtorul :
a) n corpul instruciunilor while i do-while
La ntlnirea instruciunii continue se abandoneaz iteraia curent i se trece la evaluarea
expresiei care stabilete continuarea sau terminarea ciclului respectiv (expresia inclus ntre paranteze
rotunde i care urmeaz dup cuvntul cheie while).
b) n corpul instruciunii for
La ntlnirea instruciunii continue se abandoneaz iteraia curent i se trece la execuia
pasului de reiniializare.
Instruciunea continue nu este obligatorie. Prezena ei mrete flexibilitatea n scrierea
programelor C. Ea conduce adesea la diminuarea nivelurilor de imbricare ale instruciunilor if utilizate n
corpul ciclurilor.
Exemplul 1: Instruciunea continue este opus instruciunii break. Ea foreaz ca urmtoarea iteraie
a ciclului s aib loc trecnd peste instruciunile dintre ea i testul de condiie. De exemplu, urmtorul
program nu va afia nimic niciodat:
#include<stdio.h>
void main()
{
int x;
for(x=0;x<100;x++)
{ continue;
printf(%d,x);
}
}
Instruciunea continue este folosit rareori, nu pentru c folosirea ei nu ar fi o practic bun, ci pentru
c aplicaiile n care ar putea fi utilizat sunt mai rare.
Exemplul 2: O bun utilizare a lui continue este aceea de a porni din nou o secven de instruciuni
atunci cnd apare o eroare. De exemplu, programul urmtor calculeaz suma total a numerelor
introduse de utilizator. nainte de a aduna o valoare la suma total, el verific dac numrul a fost
introdus corect. Dac numrul nu a fost introdus corect, pornete din nou ciclul, folosind instruciunea
continue.
#include<stdio.h>
#include<conio.h>
void main()
{
int i, total;
char ch;
clrscr();
total=0;
do{
printf(numarul urmator(0 pentru stop): );
scanf(%d,&i);
printf(Este %d corect ? (Y/N) ,i);
ch=getche();
printf(\n);
if(ch==N) continue;
total+=i;
}while(i);
printf(Totalul este %d\n,total);
getch();
}

5.10 Instruciunea break

Este nrudit cu instruciunea continue. Ea are formatul : break;


Poate fi utilizat n corpul unui ciclu. n acest caz, la ntlnirea instruciunii break se termin execuia
ciclului n al crui corp este inclus i execuia continu cu instruciunea urmtoare instruciunii ciclice
respective. Aceast instruciune, la fel ca i instruciunea continue, mrete flexibilitatea la scrierea
programelor n limbajele C i C++ .
Exemplul1: S se scrie un program care citete dou numere naturale i pozitive, calculeaz i
afieaz cel mai mare divizor comun al lor.
#include<stdio.h>
#include<conio.h>
#include<math.h>
void main()
{ long m,n;
long a,b;
long r;
clrscr();
do
{ printf("primul numar=");
if(scanf("%ld",&m)==1 && m>0) break;
printf("nu s-a tastat un intreg pozitiv\n");
} while(1);
do
{ printf("al doilea numar=");
if(scanf("%ld",&n)==1 && n>0)
break;
printf("nu s-a tastat un intreg pozitiv\n");
} while(1);
a=m; b=n;
do /* algoritmul lui Euclid */
{ r=a%b;
if(r)
{ a=b; b=r;}
}while(r);
printf("(%ld,%ld)=%ld\n",m,n,b);
getch();
}
Exemplul 2: Instruciunea break permite ieirea dintr-un ciclu, din oricare punct din interiorul su.
Cnd instruciunea break este ntlnit n interiorul unui ciclu, acesta se va termina imediat, iar
controlul va trece la instruciunea ce urmeaz dup ciclu. De exemplu, programul urmtor afieaz
numai numerele de la 1 la 10.
#include<stdio.h>
#include<conio.h>
void main()
{
int i;
clrscr();
for(i=1;i<100;i++)
{ printf(%d,i);
if(i==10) break;
}
getch();
}
Exemplul 3: Instruciunea break poate fi folosit cu oricare din cele trei cicluri ale limbajului. ntr-un
ciclu pot exista oricte instruciuni break. n general, se recomand ca instruciunea break s fie
utilizat pentru scopuri speciale i nu ca ieire normal din ciclu. Instruciunea break este utilizat n
cicluri n care o condiie special poate cauza oprirea imediat a ciclului. Spre exemplu, n programul
urmtor, apsarea unei taste poate opri execuia programului:
#include<stdio.h>
#include<conio.h>
void main()
{
int i;
char ch;
clrscr();
for(i=1;i<10000;i++)
if(!(i%6))
{ printf(%d Mai doriti ? (Y/N): ,i);
ch=getche();
if(ch==N) break;
printf(\n);
}
getch();
}

5.11 Instruciunea switch

Permite realizarea structurii selective. Aceasta este o generalizare a structurii alternative i a


fost introdus de Hoare. Ea poate fi realizat prin instruciuni if imbricate. Utilizarea instruciunii switch
face ca programul s fie mai clar dect dac se utilizeaz varianta cu instruciuni if imbricate. Structura
selectiv, n forma n care a fost ea acceptat de ctre adepii programrii structurate, se realizeaz n
limbajul C cu ajutorul urmtorui format al instruciunii switch :
switch(expresie)
{ case c1:
sir_1
break;
case c2:
sir_2
break;
.
case cn:
sir_n
break;
default:
sir
}
unde :
c1,c2,,cn sunt constante
sir_1,sir_2,..sir_n,sir sunt succesiuni de instruciuni
Instruciunea switch cu formatul de mai sus se execut astfel :
Se evalueaz expresia dintre parantezele rotunde
Se compar pe rnd valoarea expresiei cu valorile constantelor c1,c2,,cn. Dac valoarea
expresiei coincide cu una din constante, s zicem cu ci, atunci se execut secvena sir_i, apoi se
trece la instruciunea urmtoare instruciunii switch, adic la instruciunea aflat dup acolada
nchis care termin instruciunea. Dac valoarea respectiv nu coincide cu nici una din
constantele c1,c2,.cn, atunci se execut succesiunea de instruciuni sir din default i apoi se
trece la instruciunea urmtoare instruciunii switch.
Menionm c este posibil s nu se ajung la instruciunea urmtoare instruciunii switch n
cazul n care succesiunea de instruciuni selectat pentru execuie (sir_i sau sir) va defini ea nsi un
alt mod de continuare a execuiei programului (de exemplu, execuia instruciunii de revenire dintr-o
funcie, saltul la o instruciune etichetat etc.). Succesiunile sir_1,sir_2,..,sir_n se numesc
alternativele instruciunii switch. Alternativa sir este opional, deci ntr-o instruciune switch secvena
default : sir poate fi absent. n acest caz, dac valoarea expresiei nu coincide cu valoarea nici uneia
dintre constantele c1,c2,.. ..cn, atunci instruciunea switch nu are nici un efect i se trece la execuia
instruciunii urmtoare. Instruciunea switch de mai sus este echivalent cu urmtoarea instruciune if
imbricat :
if(expresie==c1)
sir_1
else
if(expresie==c2)
sir_2
else
if(expresie==c3)
sir_3
else
if
..
else
if(expresie==cn)
sir_n
else
sir;
Instruciunea break de la sfritul fiecrei alternative permite ca la ntlnirea ei s se treac la
execuia instruciunii urmtoare instruciunii switch. Se obinuiete s se spun c instruciunea break
permite ieirea din instruciunea switch.
Instruciunea break poate fi utilizat numai n corpurile ciclurilor i n alternativele instruciunii
switch. Prezena ei la sfritul fiecrei alternative nu este obligatorie. n cazul n care instruciunea
break este absent la sfritul unei alternative, dup execuia succesiunii de instruciuni din
compunerea alternativei respective se trece la execuia succesiunii de instruciuni din alternativa
urmtoare a aceleai instruciuni switch. Adic, dac o instruciune switch are formatul :
switch(expresie)
{ case c1:
sir_1
case c2:
sir_2
}
atunci ea este echivalent cu urmtoarea secven :
if(expresie==c1)
{ sir_1
sir_2
}else
if(expresie==c2)
sir_2;
Exemplul 1: Urmtorul program recunoate numerele 1,2,3 i 4 i afieaz numele cifrei introduse.
#include<stdio.h>
void main()
{
int i;
printf(Introduceti un intreg intre 1 si 4 : );
scanf(%d,&i);
switch(i)
{
case 1 : printf(unu); break;
case 2 : printf(doi); break;
case 3 : printf(trei); break;
case 4 : printf(patru); break;
default: printf(numar necunoscut);
}
}
Exemplul 2: Instruciunile switch sunt deseori folosite pentru a procesa comenzi meniu. De exemplu,
programul urmtor:
#include<stdio.h>
#include<conio.h>
void main()
{
float a,b;
char ch;
clrscr();
printf(Doriti :\n);
printf(Adunare,Scadere,Multiplicare,
Impartire?\n);
do{
printf(Introduceti prima litera : );
ch=getche();
printf(\n);
}while(ch!=A && ch!=S && ch!=M && ch!=I);
printf(Introduceti primul numar : );
scanf(%f,&a);
printf(Introduceti al doilea numar : );
scanf(%f,&b);
switch(ch)
{
case A: printf(%f,a+b);break;
case S: printf(%f,a-b);break;
case M: printf(%f,a*b);break;
case I: if(b) printf(%f,a/b);break;
}
getch();
}
Exemplul 3: Instruciunile asociate unui case pot s lipseasc. Aceasta permite ca dou sau mai
multe case s execute aceleai instruciuni fr s fie nevoie de duplicarea lor. Iat un program care
clasific literele n vocale i consoane:
#include<stdio.h>
#include<conio.h>
void main()
{ char ch;
clrscr();
printf(Introduceti o litera : );
ch=getche();
switch(ch)
{ case a:
case e:
case i:
case o:
case u: printf(\n este o vocala);break;
default : printf(\n este o consoana);
}
}

5.12 Instruciunea goto

Nu este o instruciune absolut necesar la scrierea programelor n limbajul C. Cu toate


acestea, ea se dovedete util n anumite cazuri, spre exemplu la ieirea din mai multe cicluri
imbricate. Astfel de situaii apar adesea la ntlnirea unei erori. n astfel de situaii, de obicei, se dorete
s se fac un salt n afara ciclurilor n care a intervenit eroarea, pentru a se ajunge la o secven
extern lor de tratare a erorii respective. nainte de a indica formatul instruciunii goto s precizm
noiunea de etichet.
Prin etichet se nelege un nume urmat de dou puncte nume: unde nume este numele
etichetei respective. Dup etichet urmeaz o instruciune. Se obinuiete s se spun c eticheta
prefixeaz instruciunea care urmeaz dup ea. Etichetele sunt locale n corpul funciei n care sunt
definite. Instruciunea goto are formatul : goto nume; unde nume este o etichet definit n corpul
aceleai funcii n care se afl eticheta goto. La ntlnirea instruciunii goto, se realizeaz salt la
instruciunea prefixat de eticheta al crei nume se afl dup cuvntul cheie goto.
Deoarece o etichet este local n corpul unei funcii, rezult c ea este nedefinit n afara
funciei respective. n felul acesta, o instruciune goto poate realiza un salt numai la o instruciune din
corpul aceleai funcii n care este utilizat. Deci, o instruciune goto nu poate face salt din corpul unei
funcii la o instruciune din corpul altei funcii.
Nu se justific utilizarea abuziv a acestei instruciuni. Se recomand a fi utilizat pentru a
simplifica ieirea din cicluri imbricate.
Exemplu : Presupunem c ntr-un punct al programului, aflat n interiorul mai multor cicluri, se
depisteaz o eroare i se dorete s se continue execuia programului cu o secven de tratare a erorii
respective. n acest caz vom folosi o instruciune goto ca mai jos.
for()
{..
while(.)
{ ..
do
{.
for(.)
{..
if(k==0)
goto divzero;
else x=y/k;

}
..
}while(..);
.
}
.
}

/* secvena de tratare a erorii */
divzero:
printf(..);
..
n absena instruciunii goto se poate realiza acelai lucru folosind un indicator i o serie de teste
realizate asupra lui.

5.13 Funciile standard sscanf i sprintf

Biblioteca standard a limbajelor C i C++ conine funciile sscanf i sprintf care sunt analoge
funciilor scanf i printf. Ele au un parametru n plus n apel i anume primul lor parametru este adresa
unei zone de memorie (ir de caractere) n care se pot pstra caractere ale codului ASCII. Ceilali
parametri sunt identici cu cei ntlnii n corespondentele lor, printf i scanf. Primul parametru al
acestor funcii poate fi numele unui ir de caractere, deoarece un astfel de nume are ca valoare chiar
adresa de nceput a zonei de memorie care i este alocat.
Funcia sprintf se folosete, ca i funcia printf, pentru a realiza conversii ale datelor de diferite
tipuri din formatele lor interne, n formate externe reprezentate prin succesiuni de caractere. Diferena
const n aceea c, de data aceasta caracterele citite nu se afieaz la terminal, ci se pstreaz n irul
de caractere definit ca prim parametru al funciei sprintf. Ele se pstreaz sub forma unui ir de
caractere i pot fi afiate ulterior din zona respectiv cu funcia puts. De aceea un apel al funciei printf
poate fi ntotdeauna nlocuit cu un apel al funciei sprintf, urmat de un apel al funciei puts. O astfel de
nlocuire este util cnd dorim s afim de mai multe ori aceleai date. n acest caz se apeleaz
funcia sprintf o singur dat pentru a face conversiile necesare din format intern n format extern,
rezultatul conversiilor pstrndu-se ntr-un ir de caractere. n continuare, se pot afia datele respective
apelnd funcia puts ori de cte ori este necesar afiarea lor. Funcia sprintf, ca i funcia printf
returneaz numrul octeilor irului de caractere rezultat n urma conversiilor efectuate.
Exemplu :
int zi,luna,an;
char data_calend[11];
.
sprintf(data_calend, %02d/%02d/%02d,zi,luna,an);
puts(data_calend);
.
puts(data_calend);

Funcia sscanf realizeaz, ca i funcia scanf, conversii din formatul extern n format intern.
Deosebirea const c de data aceasta caracterele nu sunt citite din zona tampon corespunztoare
tastaturii, ci ele provin dintr-un ir de caractere definit de primul parametru al funciei sscanf. Aceste
caractere pot ajunge n irul respectiv n urma apelului funciei gets. n felul acesta, apelul funciei
scanf poate fi nlocuit prin apelul funciei gets urmat de apelul funciei sscanf. Astfel de nlocuiri sunt
utile cnd dorim s eliminm eventualele erori aprute la tastarea datelor.
Funcia sscanf, ca i funcia scanf, returneaz numrul cmpurilor convertite corect conform
specificatorilor de format prezeni n sintax. La ntlnirea unei erori, ambele funcii i ntrerup execuia
i se revine din ele cu numrul de cmpuri tratate corect. Analiznd valoarea returnat, se poate stabili
dac au fost prelucrate corect toate cmpurile sau a survenit eroare. n caz de eroare se poate reveni
pentru a introduce corect datele respective. n acest scop este necesar s se elimine caracterele
ncepnd cu cel din poziia eronat. n cazul n care se utilizeaz secvena :
gets(....); sscanf(....);
abandonarea caracterelor respective se face automat reapelnd funcia gets. n cazul utilizrii funciei
scanf este necesar s se avanseze pn la caracterul linie nou aflat n zona tampon ataat
tastaturii sau s se videze zona respectiv prin funcii speciale.
n exerciiile urmtoare vom folosi secvenele formate din apelurile funciei gets urmate de
apelurile lui sscanf. O astfel de secven se apeleaz repetat n cazul n care se ntlnesc erori n
datele de intrare.
Exemplul :
char tab[255];
int zi,luna,an;
..
gets(tab);
sscanf(tab,%d %d %d,&zi,&luna,&an);
Amintim c funcia gets returneaz valoarea NULL la ntlnirea sfritului de fiier. Funciile sscanf i
sprintf au prototipurile n fiierul stdio.h.
Exemplul 1: S se scrie un program care citete un ntreg pozitiv de tip long, stabilete dac acesta
este prim i afieaz un mesaj corespunztor.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{ long n;
long i;
int j;
char tab[255];
clrscr();
do
{ printf("tastati un intreg pozitiv :");
if(gets(tab)==NULL)
{ printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(tab, "%ld", &n)!=1 || n<=0)
{ printf("nu s-a tastat un intreg pozitiv\n");
j=1;continue;
/* se va relua ciclul deoarece j este diferit de zero */
}
j=0; /* ciclul se ntrerupe deoarece s-a citit corect un ntreg pozitiv */
}while(j);
for(j=1,i=2;i*i<=n && j;i++)
if(!(n%i)) j=0; /* numrul nu este prim */
printf("numarul : %ld",n);
if(!j) printf(" nu");
printf(" este prim\n");
getch();
}
Observaii: Utilizarea instruciunii continue se poate omite folosind o instruciune if cu alternativa
else:
if(sscanf(.)!=1 || n<=0)
{ .
j=1;
}
else j=0;
Ciclul for continu att timp ct expresia i*i<=n&&j este adevrat. Aceast expresie se evalueaz de
la stnga spre dreapta i din aceast cauz i*i<=n se evalueaz i atunci cnd j=0. De aceea expresia
respectiv este mai eficient sub forma : j&&i*i<=n. n acest caz pentru j=0 nu se mai evalueaz restul
expresiei.
Exemplul 2: S se scrie un program care citete msurile a,b,c ale laturilor unui triunghi, calculeaz i
afieaz aria triunghiului respectiv folosind formula lui Heron.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
void main()
{ double a,b,c,p;
char tab[255];
clrscr();
do /* citete msurile laturilor triunghiului */
{ do /* citete pe a */
{ printf("a=");
if(gets(tab)==NULL)
{ printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(tab,"%lf",&a)==1 && a>0) break;
/* se iese din ciclul pentru citirea lui a */
printf("nu s-a tastat un numar pozitiv\n");
printf("se reia citirea lui a\n");
}while(1);
do /* citete pe b */
{ printf("b=");
if(gets(tab)==NULL)
{ printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(tab, "%lf", &b)==1 && b>0) break;
/* se iese din ciclul pentru citirea lui b */
printf("nu s-a tastat un numar pozitiv\n");
printf("se reia citirea lui a\n");
}while(1);
do /* citete pe c */
{ printf("c=");
if(gets(tab)==NULL)
{ printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(tab,"%lf",&c)==1 && c>0) break;
/* se iese din ciclul pentru citirea lui c */
printf("nu s-a tastat un numar pozitiv\n");
printf("se reia citirea lui a\n");
}while(1);
p=(a+b+c)/2;
if(p-a>0 && p-b>0 && p-c>0) break;
/* a,b,c pot fi laturile unui triunghi */
printf("a=%g\tb=%g\tc=%g\t",a,b,c);
printf("nu pot fi laturile unui triunghi\n");
}while(1);
printf("aria=%g\n",sqrt(p*(p-a)*(p-b)*(p-c)));
getch();
}

5.14 Header-ul ctype.h

Header-ul ctype.h este specializat pentru prelucrarea datelor de tip caracter. El conine numai
funcii i macrouri (secvene de cod asemntoare funciilor, la apelul crora se face substituia numelui
funciei cu codul asociat) de verificare i prelucrare a caracterelor. Astfel, pentru clasificarea
caracterelor, avem urmtoarele macrodefiniii :

Macro de verificare Valoarea 1 cnd caracterul este :


isalnum(c) o liter sau cifr
isalpha(c) o liter
isdigit(c) o cifr n baza 10
iscntrl(c) un caracter de control
isascii(c) un caracter valid ASCII
isprint(c) un caracter tipribil
isgraph(c) un caracter tipribil mai puin spaiul
islower(c) o liter mic
isupper(c) o liter mare
ispunct(c) un caracter de punctuaie
isspace(c) spaiu,tab,CR,LF,tab vertical,form-feed
isxdigit(c) o cifr n baza 16
Funcii conversie caractere Face conversia unui caracter :
int toupper(int ch) n liter mare. Spre deosebire de macroul
_toupper care modific orice caracter, dac
caracterul ch nu este liter mic, funcia l
ntoarce nemodificat
int tolower(int ch) n liter mic. Spre deosebire de macroul
_tolower care modific orice caracter, funcia
ntoarce caracter nemodificat dac nu este liter
mare.

Exemplul: Transformarea literelor unui ir n litere mari.


#include<stdio.h>
#include<ctype.h>
void main()
{ int i;
char t[255];
scanf(%s,t);
for(i=0;s[i];i++)
s[i]=toupper(s[i]);
printf(%s\n,t);
}

5.15 Funcii matematice uzuale


Funciile matematice sunt definite n header-ul math.h. De obicei, marea lor majoritate sunt
definite pentru valori reale de tip double putnd fi convertite fr probleme n alte tipuri.

Sintaxa funciei Valoarea returnat


int abs(int x); Macrouri care ntorc modulul unui numr
long int labs(long int x); ntreg de format normal, ntreg de format lung
double fabs(double x); i real de tip double.
double sqrt(double x); Calculeaz rdcina ptrat
double pow(double x, double y); Funcia putere xy. n cazul n care x este 0 i y
este negativ sau dac x este negativ i y nu
este ntreg se semnaleaz eroare.
double pow10(int p); Funcia putere cnd baza este 10.
double exp(double x); Funcia ex .
double log(double x); Funcia logaritm natural, ln(x) .
double log10(double x); Logaritmul n baza 10.
double ldexp(double x, int exp); Calculeaz x*2exp .
double fmod(double x, double y); Calculeaz x modulo y .
double poly(double x, int n, double Evalueaz o funcie polinomial, unde : x
coef[]); valoarea argumentului funciei , n gradul
funciei polinomiale, coef tabloul de
coeficieni ai funciei polinomiale, coef[0] este
termenul liber i coef[n] este termenul de
rang maxim
double floor(double x); Rotunjire inferioar. ntoarce cel mai mare
numr ntreg mai mic sau egal cu x.
double ceil(double x); Rotunjire superioar. ntoarce cel mai mic
ntreg mai mare sau egal cu x.

Exemplu: Calculul valorii unui polinom.


#include<stdio.h>
#include<math.h>
/* polinomul: x5-2x3-6x2+15x-1 */
void main()
{ double a[]={-1.0,15,-6.0,-2.0,0,1.0};
/* coeficienii polinomului in ordinea cresctoare a puterilor */
double x,rez;
printf(x=); scanf(%lf,&x);
rez=poly(x,5,a);
printf( val. polinomului pentru x=%lg este %lg\n,x,rez);
}
Funciile trigonometrice au argumente de tip real care trebuie specificate n radiani. Cele mai
utilizate funcii implementate sunt :

Sintaxa funciei Numele funciei Valoarea returnat


double sin(double x); Sinus Real ntre 1 i 1
double cos(double x); Cosinus Real ntre 1 i 1
double tan(double x); Tangent Real
double asin(double x); Arc sinus Real ntre - /2 i /2
double acos(double x); Arc cosinus Real ntre 0 i
double atan9double x); Arc tangent Real ntre - /2 i /2
double atan2(double y, double x); Arc tangenta lui y/x Real ntre 0 i
double sinh(double x); Sinusul hiperbolic Real
double cosh(double x); Cosinusul hiperbolic Real
double tanh(double x); Tangenta hiperbolic real

5.16 Exerciii i teste gril


1. Care dintre urmtoarele secvene de s=0; k=1;
instruciuni atribuie variabilei reale x cea mai while(k<=n)
mare dintre valorile variabilelor reale a i b sau {
valoarea lor comun, n cazul n care acestea s+=k;
sunt egale ? k+=2;
a) if(a<=b) x=b; else x=a; }
b) if(a<=b) x=a; else x=b; printf(s=%d, s);
c) if(a==b) x=a; else if(b>a) x=b; a) s=4 b) s=16 c) s=9
d) x=a; if(x<b) x=b; d) s=15 e)s=0
e) nici una dintre secvenele
5. Care dintre secvenele de program de mai
anterioare
jos calculeaz corect factorialul numrului
natural n ?
2. Fie variabilele a i b, ambele de tipul int, ale 1) p=1; for(i=1; i<=n; i++) p=p*i;
cror valori se presupun cunoscute. Scriei o 2) p=1; i=1; while(i<=n) p=p*i++;
secven de programul pentru enunul : dac 3) p=1; i=1;
numerele x i z sunt ambele impare, do{ p*=i; i=i+1; }while(i<=n);
atunci tiprete valoarea 1. a) numai 1) b) numai 2)
a) if((x%2!=0)&&(y%2!=0)) c) numai 3) d) 1) i 3)
puchar(1); e) toate
b) if(x%2==0||y%2==0) putchar(1);
c) if(x%2 && y%2) putchar(1); 6. Care trebuie s fie valoarea variabilei ntregi
d) if(!(x%2==0||y%2==0)) m, astfel nct urmtoarea secven de
putchar(1); program s afieze exact un caracter A ?
e) if(!(x%2==0)&&!(y%2==0)) x=5;
putchar(1); do{
putchar(A);
3. Ce va afia programul urmtor, dac de la x++;
tastatur se introduc n ordine numerele 5, 7 i }while(x>m);
8? a) 12 b)5 c)6
#include<stdio.h> d) 4 e)1
void main()
{ 7. Se consider secvena de program de mai
int x,y,z,m; jos, n care toate variabilele sunt ntregi. Pentru
scanf(%d %d %d,&x,&y,&z); n=3, care va fi valoarea variabilei p dup
m=(x+y+z)/3;
execuia secvenei ?
switch(m) { p=1;
case 1,2,3,4: for(i=1; i<=n; i++)
{ printf(Corigent); { s=0;
break; } for(j=1; j<=i; j++) s+=j;
case 5,6: p*=s;
{ printf(Mediocru); }
break; } a) 180 b) 18 c) 9
case 7,8,9: d) 216 e) 1
{ printf(Bine);
break; }
8. Precizai ce se va afia n urma execuiei
case 10:
programului urmtor pentru x=179 ?
{ printf(Foarte bine);
#include<stdio.h>
break; }
void main()
default:
{
printf(Eroare);
int c,s; long d,x;
} scanf(%ld, &x);
} d=x; s=0;
a) Corigent b) Mediocru
while(d)
c) Satisfctor d) Foarte bine
{ c=d%10; s+=c; d=d/10; }
e) Eroare
printf(%d, s);
}
4. Precizai ce se va afia n urma execuiei a) 16 b) 18 c)17
secvenei de program de mai jos pentru n=5 d) 0 e) 971
(s,n i k sunt variabile ntregi).
9. Considerm programul urmtor : a) va genera eroare la rulare
#include<stdio.h> b) j=4 c) j=0 d) j=10
void main()
{ 14.
short int m,x; A) for(exp1;exp2;exp3)
m=-1; instructiune;
while((scanf(%d,&x)==1)&& x) este echivalent cu
if(x>m) m=x; exp1;
printf(%d, m); while(exp2)
} { instructiune;
Precizai ce valoare va afia programul, dac exp3;}
irul de numere citit de la tastatur este 2, 5, B) for( ;exp; ) instructiune;
-32000, 33000, 0. este echivalent cu
a) 1 b) 0 c) 33000 while(exp) instructiune;
d) 2 e) 5 C) for( ; ; ) instructiune;
este echivalent cu
10. Pentru ce valoare a variabilei m, secvena while(1) instructiune;
de program de mai jos reprezint o bucl Care din echivalenele de mai sus sunt eronate:
infinit ? a) nici una b) A,B
int n=10, m; c) B,C d) A,C
do{
while(n>0) n--; 15. Fie secvena :
}while(n!=m); do{
a) 10 scanf(%c,&c);
b) orice valoare diferit de 10 if (c>=a && c<=z) i++;
c) 0 } while(c!=EOF);
d) orice valoare diferit de 0 Care din urmtoarele afirmaii este adevrat :
e) orice valoare ntreag a) se numr cte caractere litere
mici sunt citite
11. Ce valoare va afia programul urmtor b) se numr cte caractere sunt
pentru n=12 ? citite
#include<stdio.h> c) se numr cte caractere litere
void main() mari sunt citite
{ d) nici una
int i,n,s;
scanf(%d, &n); 16. Se d o secven de program n care toate
for(s=0,i=2; i<n/2; variabilele sunt de tip ntreg. n urma execuiei
!(n%i)?s+=i++: i++); programului ce conine aceast secven, ce
printf(%d,s); valori capt variabilele d i s ?
} a=8;
a) 0 b) 9 c) 12 d) 78 b=c=1; d=s=0;
e) programul conine erori i=3;
do{
12. Dac de la tastatur se introduc, n ordine, i++;
numerele 2,7,3,8,5,5, ce valoare va afia if(a>0)
secvena urmtoare ? if(b>1)
int a, b, nr=0; if(c>1) d=a;
do{ else d=a+b;
scanf(%d %d, &a, &b); else d=a+b+c;
}while((b!=a) ? ++nr : 0); s+=i+d;
printf(%d, nr); } while(i>5);
a) 0 b) 1 c) 2 a) d=8 s=12 b) d=9 s=12
d) 3 e) 4 c) d=10 s=13 d) d=10 s=14

13. int i=0; int j=6; 17. Se consider secvena de program :


if(i!=0) && (j/i!=1) void main(void)
j=i; i+=4; j+=i; { int x=1;
Pentru codul de mai sus alegei float z, y=0.96;
comportamentul corect : x+=y; z=sqrt(x);
printf(%f,z);
} ++ contor;
Valoarea afiat este : x--;
a) 1.46 b) 1.000000 c) 1 }
d) programul conine erori de a) 0 b) 1 c) 2 d) 3
sintax
22. Ce realizeaz urmtoarea secven :
18. Fie secvena de cod prezentat mai jos : scanf(%d,&x,&y,&z);
i=1; if(x<=y);
while(n) i=i*(n--); x=x+z;
atunci aceasta : y=y+z;
a) calculeaz n! else z=x+y;
a) citete trei numere i
b) calculeaz in calculeaz suma lor
c) calculeaz ni
b) citete trei numere i
d) se cicleaz la infinit
calculeaz produsul lor
c) este greit
19. Fie secvena de cod prezentat mai jos : d) z devine minimul dintre x si y
i=1;
while(n--) i=i*2;
23. Care secven de program realizeaz o
atunci aceasta :
repetiie la infinit :
a) calculeaz 2n b) calculeaz i2 I) do while(1);
c) calculeaz n2
II) do while(0);
d) se cicleaz la infinit
III) do while(i%1<2);
a) doar I b) doar II
20. Scriei o bucl care afieaz secvena : c) doar III d) doar I i III
1
22
24. Se d codul :
333
int x=4, a=2;
4444
int b=4, c=8;
55555
if(x==b) x=a;
a) for(loop==1;loop<=5;looop++)
else x=b;
{
if(x!=b) c=c+b;
for(loop1==1;loop1<=loop;loop1++)
else c=c+a;
printf(%d,loop1);
printf(c=%d\n,c);
printf(\n);
Ce se va afia dup execuia codului de mai
}
b) for(loop=1;loop<=5;loop++) sus ?
a) c=4 b) c=8 c) c=10 d) c=12
{ for(loop1=1;loop1<=loop;loop1+
+)
printf(%d,loop); 25. Se d urmtoarea secven de cod :
int i, j=0;
printf(\n);
for(i=1;i<11;i+=2)
}
{ j++; if(i==7) break; }
c) for(loop=1;loop<=5;loop++)
{ for(loop1=1;loop1<=loop;loop1+ Care va fi valoarea final a lui j ?
a) 3 b) 4 c) 5 d) 7
+)
printf(%d,loop1);
printf(\n); 26. Se d urmtoarea secven de cod :
int i, j, k; i=1; j=1; k=2;
}
while(i<6)
d) for(loop=5;loop>0;loop--)
{ k=k+i;i++;
{ for(loop1=1;loop1<=loop;loop1+
j=j+k;
+)
if(k==3) j--;
printf(%d,loop1);
else if(j==8) break;
printf(\n);
}
}
printf(%d--%d--%d,i,j,k);
Ce va afia codul de mai sus ?
21. Referitor la secvena de cod de mai jos, ce
a) 112 b) 233
valoare va avea variabila contor dup execuia
c) 385 d) 4168
ei ?
int x=3, contor=0;
while((x-1)) { 27. Se d codul :
int a=3, b=0;
while(a) e) a=4, b=2, c=3
{ b=b++; a=b; }
Ce valoare va avea b ? 32. Se consider programul urmtor:
a) 1 b) 3 c) 0 #include<stdio.h>
d) nedefinit pentru c va fi o void main()
bucl infinit {
int a,b,c,d,i;
28. Fie secvena de cod : scanf(%d %d, &a, &b);
#include<stdio.h> if(a>b)
void main(void) { c=a; a=b; b=c; }
{ int i,y,x=6; d=0;
y=x; for(i=a;i<=b;i++)
while(1) if(i%2==0) d++;
{ y--; x=x*y; printf(%d,d);
if(y==0) break; }
} Ce valoare se afieaz pentru a=33 i b=18 ?
printf(%d,x); a) 8 b) 7 c) 0 d) 16 e) 33
}
Ce numr va fi afiat pe ecran la terminarea 33. Fie urmtorul program:
execuiei acestui cod ? #include<stdio.h>
a) 720 void main()
b) programul va rula la infinit {
c) 0 d) 6 int x,y,m,n,a,b;
a=b=2; //(1)
29. Fie secvena de cod : m=(x=a+3,y=b-1,y++,y+x); //(2)
int x; if(a&&x>y) printf(%d,m);//(3)
int y=1; if(x-y>a&&x>y||!m) //(4)
for(x=0;x<=30;x++) putchar(1);
{ y=y+1; else putchar(0);
if(x<5) continue; if((n=x>y)==0)||(--x==4)) //(5)
if(x>5) break; printf(%d,x--);
y=y+x; }
} n timpul execuiei programului se pot spune
Dup execuia codului anterior, ce valoare va urmtoarele:
avea y ? a) atribuirea din linia (1) este
a) 486 b) 31 c) 13 d) 496 eronat
b) instruciunea din linia (2) este
30. Fie urmtorul program : eronat
int main() c) n urma execuiei liniei (3) nu
{ int i; se afieaz nici o valoare
for(i=1;i<65535;i++); d) n urma execuiei liniei (4) se
printf(i=%d\n,i); afieaz valoarea 1
} e) n urma execuiei liniei (5) se
a)valoarea afiat este i=65535 afieaz valoarea 4
b)valoarea afiat este i=65534
c)valoarea afiat este i=32766 34. Dac de la tastatur se introduce numrul
d)programul nu este corect deoarece 22, cte valori distincte va afia programul
este depit domeniul de valori urmtor?
#include<stdio.h>
31. n urma execuiei secvenei de program de #include<math.h>
mai jos, pentru care dintre tripletele de valori void main()
ale variabilelor a, b, c, date mai jos, se va afia {
valoarea 1? int x,n,i;
x=1; for(scanf(%d,&n),i=1;;x=sqrt(i),
if(!(a<=b)||!(a<=c)) printf(%d,x),i++)
{ if(b>=c) printf(%d\n,-x); } if(i>n) break;
else }
if(b<c) printf(%d\n,x); a) nici una
a) a=3, b=2, c=4 b) a=2, b=3, c=4 b) 1 c) 2 d) 3 e) 4
c) a=4, b=3, c=2 d) a=2, b=4, c=3
35.Precizai de cte ori se va afia valoarea 1 38. Precizai care dintre urmtoarele secvene
n timpul execuiei programului urmtor, dac de instruciuni atribuie variabilei ntregi x
a=3,b=4 i x=5. valoarea n2, cu n numr natural.
#include<stdio.h> a) x=1;
void main() for(j=1;j<3;j++) x*=n;
{ b) x=1;
int a,b,x; for(j=1;j<=n;j++) x*=2;
scanf(%d%d%d,7a,&b,&x); c) x=1; j=0;
if(!((x<=a)&&(x>=b))) while(j<2) x*=n; j++;
putchar(1); d) x=1; j=0;
if(!(x<=a||x>=b)) do{ j++; x*=n;}while(j<2);
putchar(1); e) x=n*n;
if(!(x<=a)&&!(x>=b))
putchar(1); 39. Precizai care dintre urmtoarele secvene
if(!(x<=a)||!(x>=b)) de instruciuni atribuie variabilei ntregi x
putchar(1); valoarea 10n, cu n numr natural.
} a) x=10;
a) nici o dat b) o dat for(j=1;j<=n;j++)x*=i;
c) de dou ori d) de trei ori b) x=1;
e) de patru ori for(j=n;j>0;j--) x*=10;
c) x=1; j=1;
36. Dac n timpul execuiei programului de mai do{ x*=10; j++; }while(j<n);
jos n va primi valoarea 232213, care vor fi n d) x=1; j=0;
final valorile variabilelor f1, f2 i f3 ? while(j<=n) { j++; x*=i;}
#include<stdio.h> e) nici una dintre variantele
void main() anterioare
{
long n; 40. Deducei ce valoare se va afia n urma
unsigned int f1,f2,f3,c; execuiei secvenei de program de mai jos,
scanf(%ld,&n); dac valorile variabilei x citite de la tastatur
f1=f2=f3=0; sunt n ordine 3,2,4,3,5,10,20,0.
do{ scanf(%d,&x);
c=n%10; n=n/10; nr=0;
switch(c) { do{
case 1: { f1++; break; } y=n;
case 2: { f2++; break; } scanf(%d,&x);
case 3: { f3++; break; } if(x==2*y) nr++;
} }while(x!=0);
}while(n!=0); printf(%d,nr);
printf(%u %u %u,f1,f2,f3); a) 0 b) 1 c) 2 d) 3 e) 4
}
a) f1=1,f2=1,f3=1 b) f1=1,f2=2,f3=2 41. Care dintre urmtoarele secvene de
c) f1=1,f2=2,f3=3 d) f1=2,f2=1,f3=3 nstruciuni atribuie variabilei ntregi u valoarea
e) f1=3,f2=2,f3=1 primei cifre a numrului natural reprezentat de
variabila x ?
37.Pentru n=7, care dintre secvenele de a) u=x;
program de mai jos trebuie executat astfel while(u>=10) u=u%10;
nct, la finele execuiei, valoarea variabilei p b) while(x>=10) x=x/10;
s fie 48 ? u=x;
a) p=1; i=2; c) u=x/10;
while(i<=n) { p*=i;i+=2;} d) u=x%10;
b) p=1; i=1; e) nici una din variantele
while(i<n/2){i++;p=p*(2*i+1); } anterioare
c) p=1; i=1;
while(i<=n/2) {p=p*(2*i);i++; } 42. Care dintre urmtoarele secvene de
d) p=1; i=0; instruciuni atribuie variabilei ntregi u valoarea
while(i<n) { i+=2;p*=i; } ultimei cifre a numrului natural reprezentat de
e) nici una dintre secvenele variabila x ?
anterioare a) while(x>=10) x=x/10; u=x;
b) u=x; while(u>=10) u=u%10;
c) u=x%10; 46. Considernd c toate variabilele sunt
d) u=x/10; ntregi, ce valoare se afieaz dup execuia
e) toate variantele anterioare secvenei de mai jos ?
s=0;t=0;x=3;i=1;y=1;z=1;
43. Fie secvena de program urmtoare, n do{
care ok este o variabil de tipul int, iar x este if(x>0)
un numr natural. if(y>1)
ok=0; if(z>2) t=x;
for(j=2;j<x;j++) else t=x+y;
if(x%j==0) ok=1; else t=x+y+z;
printf(%d,ok); s+=i+t; i++;
Secvena afieaz 1 dac: }while(i>7);
a) numrul x are cel puin un a) 1 b) 5 c) 6 d) 51 e) 63
divizor propriu
b) numrul x nu are nici-un 47. Care dintre irurile de valori date n
divizor propriu variantele de rspuns trebuie introduse de la
tastatur n timpul execuiei programului
c) toate numerele naturale mai urmtor, astfel nct s se declaneze un ciclu
mici ca n, fr 0 i 1, sunt infinit ?
divizori proprii ai lui x #include<stdio.h>
d) numrul x are cel mult un void main()
divizor propriu {
e) nici una dintre variantele de int x,y;
mai sus while(scanf(%d,&x)==1 &&
scanf(%d,&y)==1 && (x||y))
44. Se consider secvenele de program de do{
mai jos. Pentru n=4, precizai care dintre y--;
secvene afieaz, n urma execuiei, irul de printf(*%d *%d,x,y);
numere: 1,2,2,3,3,3,4,4,4,4 . }while(x!=y);
a) for(j=1;j<=n;j++) }
for(k=1;k<=n;k++) a) 2,7,3,8,0,0 b) 2,5,4,4,0,0
printf(%2d,j); c) 1,3,6,2,0,0 d) 2,4,5,8,0,0
b) for(j=1;j<=n;j++) e) 0,0
for(k=1;k<=j;k++)
printf(%2d,j); 48. Pentru programul urmtor, care dintre
c) for(j=1;j<=n;j++) afirmaiile de mai jos sunt adevrate ?
for(k=1;k<=n;k++) #include<stdio.h>
printf(%2d,k); void main()
d) for(j=1;j<=n;j++) {
for(k=1;k<=j;k++) int s,x;
printf(%2d,k); for(s=0,x=1;0;s+=x,scanf(%d,x)
e) for(k=1;k<=n; k++) if(!x) break;
for(j=1;j<=n;j++) printf(%d,s);
printf(%2d,j); }
a) dac de la tastatur se
45. Fie secvena de program urmtoare: introduc, n ordine, numerele 2,3,4
s=0; i 5, atunci programul va afia
for(j=3;j<=n;j+=3) s+=j; suma numerelor citite, adic 14
Se dau mai jos cinci triplete de numere, b) dac prima valoare introdus de
fiecare astfel de triplet reprezentnd un set de la tastatur este 0, atunci ciclul
valori pentru variabila de intrare n. Care dintre se ncheie i se afieaz valoarea
aceste triplete au proprietatea c pentru toate 1
cele trei valori ale lui n din triplet se obine c) ciclul este eronat: nu se poate
aceeai valoare a lui s ? face o citire n linia for
a) (3,5,6) b) (6,7,8) d) instruciunea if este eronat
c) (10,11,12) d) (6,9,12) e) din cauz c lipsete expresia
e) (15,16,17) care d condiia de continuare,
ciclul for se va executa la
infinit
49. Care dintre secvenele de mai jos afieaz do{
corect irul cifrelor impare 97531 n aceast printf(%d,10-j++);
ordine ? }while(j<=9?j++:0);
a) for(j=9;j>=1;j--)
printf(%d,j--);
b) for(j=0;j<=9;j++)
printf(%d,9-j++);
c) for(j=9;j-->=1;)
printf(%d%d,j,j--);
d) j=10;
while(j--) printf(%d,--j);
e) j=1;
Cap.6 Tablouri

6.1 Declararea tablourilor

Un tablou reprezint un tip structurat de date care ocup o zon de memorie continu,cu
elemente componente de acelai tip. n cadrul tabloului un element este n mod unic identificat prin
poziia ocupat n cadrul structurii. Aceast poziie este definit prin unul sau mai muli indici sau
indeci, din acest motiv tablourile numindu-se variabile indexate.
Declararea unui tabou se face cu sintaxa :
tip nume[dim_1][dim_2]..[dim_n];
unde :
- tip este tipul elementelor componente ale tabloului. Acesta poate fi un tip predefinit sau definit de
utilizator
- nume este numele variabilei tablou
- dim_1, dim_2,..,dim_n sunt numere ntregi pozitive care exprim dimensiunile tabloului
Pentru a utiliza un element din tablou se folosete sintaxa :
nume[index_1][index_2][index_n]
fiecare index respectnd condiia index_i {0,,dim_i-1}.
Un tablou unidimensional se numete vector, iar un tablou bidimensional se numete matrice .
Exemple:
char s[100];
int x[25];
long double a[10][15];
Observaii:
- primul element dintr-un vector va avea indexul 0, iar ultimul element stocat va avea indexul dim-1
- primul element dintr-o matrice va avea indexul (0,0), iar ultimul va avea indexul (dim_1-1,dim_2-1)
- dimensiunile tabloului trebuie s fie expresii constante
- compilatorul nu face verificri pentru depirea dimensiunii tabloului
- pentru alocarea unui tablou sunt necesari nr_elemente*sizeof(tip) octei, unde tip este tipul de
baz al tabloului
- atribuirea tablourilor nu poate fi fcut direct
Exemplu :
int x[10],y[10];
x=y; /*operaie ilegal*/

6.2 Iniializarea tablourilor

Declaraia unui tablou poate fi urmat de o secven de iniializare format din una sau mai
multe perechi de acolade ntre care se pun valori ale tipului de baz, separate prin virgul.
Pentru tablourile unidimensionale este permis omiterea numrului de elemente. El va fi egal
cu numrul de valori folosite la iniializare.
n cazul n care la iniializarea tablourilor de tip numeric sunt folosite mai puine elemente dect
dimensiunea tabloului, restul elementelor sunt iniializate cu 0.
Exemple:
float x[5]={1.2,3.4e3,-2,90.7E-8,-88.5e-7};
char s[100]=test tablou;
short y[]={0,1,2,3,4}; /* y are 5 elemente */
char s[]={t,e,s,t,\0}; /* char s[]=test; */
int x[5]={1,2}; /* x=(1, 2, 0, 0, 0) */

Iniializarea unui tablou multidimensional se face asemntor cu cea a unui vector. Se poate
face specificarea complet sau parial a datelor, cele nedefinite fiind iniializate cu 0. Este permis
doar omiterea primei dimensiuni (cea din stnga).
Exemple:
int a[3][2]={{1,2},{3,4},{5,6}};
echivalent cu :
int a[][2]={{1,2},{3,4},{5,6}};
sau chiar cu:
int a[3][2]={1,2,3,4,5,6};
iniializarea
int m[2][3]={{1},{2}};
care este echivalent cu :
int m[2][3]={{1,0,0} , {2,0,0}};

6.3 Prelucrri elementare ale vectorilor

Deoarece limbajul C nu verific depirea dimensiunilor maxime declarate pentru tablourile


utilizate n aplicaii, pentru a evita scrierea accidental a unor zone de memorie, programatorul trebuie
s asigure validarea dimensiunilor reale (implicit a numrului de elemente) citite de la intrare. Uzual, un
vector se declar n urmtoarea manier:
#define MAX 100 /* dimensiunea maxim admis */

int a[MAX];
int n; /* dimensiunea real citit la intrare */
Secvena tipic de validare a dimensiunii unui vector este urmtoarea:
do{
printf(n=);
scanf(%d,&n);
if(n<=0||n>MAX) printf(dimensiune incorecta\n);
}while(n<=0||n>MAX);

6.3.1 Citirea elementelor unui vector

Dup validarea dimensiunii, citirea elementelor unui vector se face n ordinea cresctoare a
indicilor, uzual cu o instruciune for :
for(int i=0; i<n; i++)
{ printf(a[%d]=,i);
scanf(%d,&a[i]);
}
Observaie: Dei tablourile sunt indexate n C ncepnd de la 0, se pot utiliza elementele numai de la
indexul 1 (ca n Pascal), elementul a[0] rmnnd liber. n aceast situaie secvena de citire (i toate
celelalte secvene de prelucrare) se vor modifica corespunztor, conform modelului de mai jos:
for(int i=1;i<=n;i++)
{ printf(a[%d]=,i);
scanf(%d,&a[i]);
}

6.3.2 Determinarea elementului minim/maxim

Metoda tipic de determinare a elementului minim/maxim dintr-un vector este urmtoarea : se


iniializeaz minimul/maximul cu primul element din vector apoi se compar cu celelalte elemente din
vector reinndu-se, pe rnd, valorile mai mici/mai mari.
minim=a[0]; /* maxim=a[0]; */
for(i=1; i<n; i++)
if(minim>a[i]) /* (maxim<a[i]) */
minim=a[i]; /* maxim=a[i]; */

6.3.3 Determinarea primului element cu o anumit proprietate

Pentru a determina primul element (de indice minim) cu o anumit proprietate, se parcurge
vectorul de la stnga la dreapta pn cnd gsim primul element cu proprietatea cerut sau pn cnd
epuizm elementele vectorului. De exemplu, determinarea primului element nul dintr-un vector se
realizeaz cu secvena:
f=-1;
for(j=0;j<n;j++)
if(!a[j])
{ f=j; break; }

Verificnd valoarea variabilei f decidem dac n vectorul exist cel puin un element cu proprietatea
cerut (f=indicele acestuia) sau nici unul (f =-1).

6.3.4 Determinarea ultimului element cu o anumit proprietate

Pentru a determina ultimul element (de indice maxim) cu o anumit proprietate, se parcurge
vectorul de la dreapta spre stnga (n ordinea descresctoare a indicilor) pn cnd gsim primul
element cu proprietatea cerut sau pn cnd epuizm elementele vectorului. De exemplu,
determinarea ultimului element par dintr-un vector se realizeaz cu secvena:
f=-1;
for(j=n-1;j>=0;j--)
if(!(a[j]%2))
{ f=j; break; }

6.3.5 Eliminarea tuturor elementelor cu o anumit proprietate

Cea mai simpl metod de a elimina dintr-un vector toate elementele cu o anumit proprietate
este s crem un nou vector n care se pstreaz elementele care nu au proprietatea respectiv. De
exemplu, pentru a elimina dintr-un vector toate elementele negative, putem utiliza secvena:
j=-1;
for(i=0;i<n;i++)
if(a[i]>=0) /* nu are proprietatea cerut */
b[++j]=a[i]; /* pstram elementul n vectorul b */
n=j; /* actualizm dimensiunea vectorului */
Metoda este ineficient datorit consumului de memorie necesar pentru vectorul b. O metod mult
mai eficient este s folosim acelai vector n care vom ngrmdi pe primele poziii elementele care
trebuie pstrate. Prin actualizarea dimensiunii vectorului, elementele de prisos nu vor mai fi luate n
consideraie n prelucrrile ulterioare. Secvena care realizeaz aceast operaie este urmtoarea:
j=-1;
for(i=0;i<n;i++)
if(a[i]>=0) /* nu are proprietatea cerut */
a[++j]=a[i]; /* mutm elementul la nceputul vectorului */
n=j; /* actualizm dimensiunea vectorului */

6.3.6 Eliminarea elementului din poziia k dat (1<=k<=n)

Prin eliminarea elementului din poziia k dat (elementul de indice k-1), se observ c primele
k-1 elemente rmn neschimbate, n timp ce elementele din poziiile k+1, k+2,.,n se deplaseaz
cu o poziie spre stnga pentru a umple golul rmas prin eliminarea elementului din poziia k.
Evident, dimensiunea vectorului scade cu o unitate :
for(j=k-1;j<=n-2;j++) a[j]=a[j+1]; /* deplasm elementele spre stnga */
n--; /* corectm dimensiunea */

6.3.7 Inserarea unui element y n poziia k dat (1<=k<=n)

Cum inserarea unui element se face fr a pierde vreun element din vectorul iniial, elementele
din poziiile k, k+1,.......n trebuie s se deplaseze cu o poziie spre dreapta pentru a face loc noii valori
y introdus n poziia k (indice k-1). Dimensiunea vectorului crete cu o unitate:
for(j=n;j>=k;j--) a[j]=a[j-1]; /* deplasm elementele spre dreapta */
a[k-1]=y; /* inserm elementul y */
n++; /* actualizm dimensiunea */

6.3.8 Permutarea circular cu o poziie spre stnga

Prin acest operaie, elementele din poziiile 2,3,..,n se deplaseaz cu o poziie spre
stnga i elementul din prima poziie ajunge n poziia n. Vectorul nu i modific dimensiunea:
aux=a[0]; /*salvm temporar primul element */
for(j=0;j<=n-2;j++) a[j]=a[j+1]; /* deplasm elementele spre stnga */
a[n-1]=aux; /* mutm elementul n ultima poziie */

6.3.9 Permutarea circular cu o poziie spre dreapta

Prin aceast operaie, elementele din poziiile 1,2,,n-1 se deplaseaz cu o poziie spre
dreapta, iar elementul din poziia n ajunge n poziia 1. Vectorul nu i modific dimensiunea:
aux=a[n-1]; /* salvm temporar ultimul element */
for(j=n-1;j>=1;j--) a[j]=a[j-1]; /*deplasm elementele spre dreapta */
a[0]=aux; /* mutm elementul n prima poziie */

6.3.10 Sortarea vectorilor


Prin sortare se nelege aranjarea elementelor unui vector n ordine cresctoare sau
descresctoare. Pentru rezolvarea acestei probleme au fost concepui diveri algoritmi, mai mult sau
mai puin rapizi, mai simpli sau extrem de complicai. n acest moment vom aborda dou dintre cele mai
simple metode de sortare de complexitate n2 .

A) Metoda bulelor (bubblesort)


Conform acestei metode, vectorul este parcurs de la stnga spre dreapta comparndu-se
perechi de elemente succesive (a[j] cu a[j+1]). Dac cele dou elemente nu sunt n ordinea cerut, se
interschimb i, o variabil iniial egal cu 0, se incrementeaz. n acest fel, la prima parcurgere a
vectorului, elementul maxim din ir (dac se face ordonare cresctoare) se deplaseaz spre dreapta
pn cnd ajunge n ultima poziie. La a doua parcurgere a vectorului , al doilea cel mai mare element
ajunge n penultima poziie etc. Parcurgerea vectorului se reia pn cnd nu mai gsim nici-o pereche
de elemente consecutive neordonate. La fiecare parcurgere, lungimea secvenei care se verific scade
cu o unitate:
k=n; /* iniial verificm tot vectorul */
do{
f=0; /* numr perechile neordonate */
for(j=0;j<k-1;j++)
if(a[j]>a[j+1]) /* pentru ordonare cresctoare */
{ aux=a[j]; a[j]=a[j+1];
a[j+1]=aux; /* interschimbm elementele */
f++; /* numrm in f */
}
k--; /* lungimea secvenei care se verific scade */
}while(f); /* repet ct timp mai sunt perechi neordonate */

B)Sortarea prin selecie direct


Conform acestei metode primul element (a[0]) se compar pe rnd cu toate elementele de
dup el i dac ordinea de sortare nu este respectat, cele dou elemente se interschimb. Dup
efectuarea tuturor comparaiilor, n prima poziie ajunge cel mai mic element din vector (n cazul
ordonrii cresctoare). Se compar apoi al doilea element cu toate elementele de dup el etc. La
ultimul pas se compar numai ultimele dou elemente. Secvena corespunztoare de program este :
for(i=0; i<n-1; i++) /* elementul care se compar */
for(j=i+1;j<n;j++) /* elem. de dup el cu care se compar */
if(a[i]>a[j]) /* pentru ordonare cresctoare */
{ aux=a[i]; a[i]=a[j];
a[j]=aux; /* interschimbm elementele */
}

6.3.11 Algoritmul de cutare binar

Se consider un vector oarecare A cu n elemente i o valoare x. Se cere s se verifice dac x


apare printre elementele vectorului sau nu. Dac lucrm cu un vector oarecare, se vor compara pe
rnd elementele acestuia cu valoarea cutat x. Sunt necesare cel mult n comparaii n caz de succes
(x apare n vector) i exact n comparaii n caz de eec (x nu apare n vector). n cazul n care vectorul
este ordonat cresctor sau descresctor se poate folosi un algoritm de cutare mult mai eficient avnd
complexitatea log2n. Acest algoritm se numete algoritmul de cutare binar i poate fi descris astfel :
iniial se consider tot vectorul A i se compar x cu elementul din mijlocul acestuia (fie el a[mij]). Dac
x=a[mij], algoritmul se ncheie cu succes; dac x<a[mij], vectorul fiind ordonat, cutarea va continua n
prima jumtate, iar dac x>a[mij] cutarea va continua n a doua jumtate. Procedeul se repet pn
cnd fie gsim valoarea x, fie nu mai avem secven valid de cutare, adic elemente neverificate.
Secvena curent n care se face cutarea elementului x este identificat prin indicele elementului din
extrema stng, respectiv indicele elementului din extrema dreapt. Secvena de program este
urmtoarea :
f=-1; /* x nu a fost gsit n vectorul A */
st=0; dr=n-1; /* secvena iniial de cutare este ntregul vector A */
while(st<=dr) /* secvena curent de cutare conine cel puin un element */
{ mij=(st+dr)/2; /* indicele elementului din mijlocul secvenei de cutare */
if(a[mij]==x)
{ f=mij; /* memorm poziia n care apare */
break; /* cutare ncheiat cu succes */
}
if(x<a[mij])
dr=mij-1; /* cutarea continu n prima jumtate */
else
st=mij+1; /* cutarea continu n a doua jumtate */
}

6.3.12 Interclasarea vectorilor

Se consider doi vectori, A cu m elemente i B cu n elemente, ambii ordonai cresctor sau


descresctor. A interclasa cei doi vectori nseamn a obine un vector C cu m+n elemente, care
conine toate elementele din A i din B, ordonate n acelai mod. Metoda de creare a vectorului rezultat
C este foarte simpl: se compar elementul curent din A cu elementul curent din B, n C se introduce
spre exemplu cel mai mic dintre ele (la ordonare cresctoare). Dac elementul introdus a fost din
vectorul A atunci se avanseaz la urmtorul element din A, altfel se avanseaz la urmtorul element
din vectorul B. n momentul n care elementele unui vector sunt epuizate, elementele rmase n cellalt
vector sunt copiate direct n vectorul C. Acest algoritm se simplific dac folosim dou santinele care
vor face ca cei doi vectori s se epuizeze simultan. O santinel este un element care nu influeneaz
valoarea unui rezultat, scopul utilizrii lui fiind numai obinerea unui algoritm mai simplu i mai eficient.
n cazul algoritmului de interclasare, vom aduga la sfritul vectorului A o santinel mai mare dect
cel mai mare element din B, iar la sfritul vectorului B o santinel mai mare dect cel mai mare
element din A. n acest caz, dac presupunem c toate elementele utile din vectorul A au fost deja
introduse n vectorul rezultat C, atunci, toate elementele utile din B care nu au fost nc verificate sunt
mai mici dect santinela rmas n A i vor fi copiate automat, fr nici-o verificare suplimentar, n
vectorul rezultat C. Secvena care realizeaz interclasarea cu santinele este:
a[m]=b[n-1]+1; /* santinela din A mai mare dect cel mai mare element din B */
b[n]=a[m-1]+1; /* santinela din B mai mare dect cel mai mare element din A */
i=0; /* indicele elementului curent din A */
j=0; /* indicele elementului curent din B */
for(k=0; k<m+n; k++) /* k este indicele elementului curent din C */
if(a[i]<b[j]) /* pentru ordonare cresctoare */
c[k]=a[i++]; /* avansez n vectorul A */
else
c[k]=b[j++]; /* avansez n vectorul B */

6.4 Prelucrri elementare ale matricilor

Ca i n cazul tablourilor unidimensionale, se pune problema depirii dimensiunilor maxime


specificate n declaraia unui tablou bidimensional (matrice). Matricile sunt de dou tipuri:
dreptunghiulare (numrul de linii diferit de numrul de coloane) i ptratice (numrul de linii egal cu
numrul de coloane).
Pentru matricile dreptunghiulare maniera uzual de declarare i validare a dimensiunilor este
urmtoarea :
#define MAXLIN 7 /* numrul maxim de linii */
#define MAXCOL 5 /* numrul maxim de coloane */
int a[MAXLIN][MAXCOL];
int m,n; /* numrul real de linii, respectiv coloane */

do{
printf(numarul de linii=);
scanf(%d,&m);
if(m<=0 || m>MAXLIN) printf(dimensiune eronata\n);
}while(m<=0 || m>MAXLIN);
do{
printf(numarul de coloane=);
scanf(%d,&n);
if(n<=0 || n>MAXCOL) printf(dimensiune eronata\n);
}while(n<=0 || n>MAXCOL);
Pentru o matrice ptratic maniera uzual de declarare i validare a dimensiunii este
urmtoarea:
#define DIM 8
int a[DIM][DIM];
int n; /* dimensiunea real a matricii */
..
do{
printf(dimensiunea matricii=);
scanf(%d,&n);
if(n<=0 || n>DIM) printf(dimensiune eronata\n);
}while(n<=0 || n>DIM);

Este bine de tiut c memorarea matricilor se face pe linii (ordine lexicografic), adic
compilatorul rezerv pentru matrice o zon contigu de memorie de dimensiune
MAXLIN*MAXCOL*sizeof(tip), unde tip este tipul de baz al matricii, adic tipul elementelor
componente. Primele MAXCOL locaii din aceast zon sunt pentru elementele din prima linie (de
indice 0), chiar dac nu toate sunt folosite, urmtoarele MAXCOL locaii sunt rezervate pentru
elementele din a doua linie (de indice 1) etc. Practic, n memorie, matricea este liniarizat sub forma
unui vector cu MAXLIN*MAXCOL elemente, unele din aceste elemente putnd fi neutilizate.
Raionamentul se aplic identic pentru matricile ptratice, numrul de elemente fiind DIM*DIM
(dimensiunea matricii).
n continuare, vom considera cazul general al matricilor dreptunghiulare, secvenele de
instruciuni trebuind modificate corespunztor pentru a lucra corect cu matricile ptratice
(m=n=dimensiunea matricii).
6.4.1 Citirea elementelor unei matrici

Deoarece memorarea matricilor se face pe linii, elementele se citesc pe linii, adic indicele de
coloan se modific mai rapid dect indicele de linie. Secvena corespunztoare de program este
urmtoarea:
for(i=0;i<m;i++) /* indicele de linie */
for(j=0;j<n;j++) /* indicele de coloan */
{ printf(a[%d,%d]=,i,j);
scanf(%d,&a[i][j]);
}

6.4.2 Tiprirea elementelor unei matrici

Dac dorim s tiprim matricea cu valorile de pe aceeai coloan aliniate spre exemplu la
dreapta, vom folosi facilitile de aliniere i de specificare a numrului de zecimale (pentru valori reale)
ale funciei printf. Spre exemplu, tiprirea unei matrici de numere reale cu valorile aliniate la dreapta i
trei zecimale exacte se poate realiza cu secvena:
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
printf(%8.3f,a[i][j]); /* tiprete elementele de pe o linie */
printf(\n); /* trece la o linie nou */
}

6.4.3 Determinarea elementului maxim/minim

Metoda uzual este urmtoarea: se iniializeaz maximul/minimul cu primul element din matrice
(a[0][0]), se compar apoi pe rnd cu toate elementele din matrice i se reine valoarea mai mare/mai
mic. Secvena de instruciuni care realizeaz acest lucru este urmtoarea:
maxim=a[0][0]; /* minim=a[0][0] */
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(maxim<a[i][j]) /* minim>a[i][j] */
maxim=a[i][j]; /* minim=a[i][j] */

6.4.4 Identificarea elementelor specifice unei matrici ptratice

n cazul matricilor ptratice se identific urmtoarele elemente specifice: diagonala principal


(DP), diagonala secundar (DS), jumtatea superioar (JS) i jumtatea inferioar (JI). Diagonalele
corespund (geometric) diagonalelor unui ptrat.
Diagonala principal cuprinde elementele din colul stnga sus pn n colul dreapta jos, adic
mulimea:
DP={aij| i=j, i=0,..n-1}={a00, a11, a22, .,an-1n-1} unde n este dimensiunea real a
matricii.
Diagonala secundar cuprinde elementele din colul dreapta sus pn n colul stnga jos,
adic mulimea:
DS={aij|i=0,1,n-1 , j=n-1,n-2,0, i+j=n-1}={a0n-1, a1n-2,..,an-10}
Jumtatea superioar cuprinde elementele de deasupra diagonalei principale (fr cele de pe DP),
adic mulimea:
JS={aij | i=0,1,n-2 , j=i+1,,n-1}
Jumtatea inferioar cuprinde elementele de sub diagonala principal (fr elementele de pe DP),
adic mulimea:
JI={aij | i=1,2,.n-1 , j=0,1,i-1}
Un element a[i][j] din JS are drept simetric elementul a[j][i] din JI. Astfel, transpusa unei matrici
ptratice (matricea care are liniile drept coloane i reciproc) se poate genera uor interschimbnd toate
elementele din JS cu simetricele lor din JI aa cum se vede n secvena de mai jos:
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
{ aux=a[i][j];
a[i][j]=a[j][i];
a[j][i]=aux;
}

6.5 Exerciii i teste gril

1. Care dintre variantele de mai jos reprezint o {


declaraie corect a unui vector v cu 20 de int v[]={0,1,2,0,4,5,6};
elemente numere ntregi ? int i=0,x=9;
a) v[20]:integer; b) v[20] int; do{
c) int v[20]; d) int :v[20]; v[i++]=x;
e) integer v[20]; }while(i<6 && v[i]);
}
2. Cte erori conine programul de mai jos? a) nici unul b) unul
void main() c) dou d) trei e) toate
{
int n,k; 6. Fie programul urmtor :
int v[n]; void main()
n=4 {
for(k=0;k<n;k++) v[k]= =0; int i,j,m,n,p,a[10][10],b[6];
} m=2; n=3; p=6; i=0;
a) 0 b) 1 c) 2 while(i<p) b[i++]=i;
d) 3 e) 4 for(i=0;i<m;i++)
for(j=0;j<n;j++)
3. Care dintre secvenele de program de mai a[i][j]=b[3*i+j];
jos calculeaz corect suma primelor n }
elemente ale unui vector s ? n urma execuiei sunt posibile urmtoarele
a) s=0; situaii:
for(i=0;i<n;i++) s+=v[i]; a) programul nu funcioneaz din
b) s=0; i=0; cauz c declaraia matricei
while(i<n) este eronat
{ s+=v[i]; i++;} b) valorile vectorului b sunt
c) s=0; i=0; 0,1,2,3,4,5
do{
c) valorile vectorului b sunt
s+=v[i]; i++; 1,2,3,4,5,6
}while(i<n-1);
d) toate e) nici una d) a[1][0] are valoarea 3
e) a[0][2] are valoarea 2
4. Deducei care vor fi elementele vectorului v
dup execuia secvenei de program 7. Se consider o matrice a cu n linii*n coloane
urmtoare: i un vector v cu n elemente. Precizai care vor
int n,k,x,v[7]={5,14,-3,8,-1}; fi elementele vectorului v, dup execuia
n=5; x=v[0]; secvenei urmtoare:
for(k=1;k<n;k++) v[k-1]=v[k]; int nr, n, i, j, x, b[20];
v[n-1]=x; int a[3][3]={{7,1,7},{-7,7,0},
a) (-1,5,14,-3,8,0,0) {2,4,11}};
b) (14,-3,8,-1,0,0,5) n=3; x=7;
c) (14,-3,8,-1,5,0,0) for(i=0;i<n;i++)
d) (0,0,5,-3,14,-1,8) { nr=0;
e) (0,0,-1,14,-3,8,5) for(j=0;j<n;j++)
if(a[i][j]==x) nr++;
5. Cte elemente ale vectorului v vor avea b[i]=nr;
valoarea 9 dup execuia programului de mai }
jos? a) nedefinite b) v=(0,0,0)
#include<stdio.h> c) v=(1,2,3) d) v=(2,0,1)
void main() e) v=(2,1,0)
8. Se consider secvena de program while(i<n)
urmtoare, n care a este o matrice cu n linii*n { printf(%d, v[i]); i++;}
coloane i elemente numere ntregi, iar x este o b) i=0;
variabil de tip ntreg. while(i<n)
x=1; { i++; printf(%d, v[i]); }
for(i=1;i<=n-1;i++) c) i=0;
for(j=0;j<=i-1;j++) do{ i++;
if(a[i][j]!=0) x=0; printf(%d, v[i]);
n urma execuiei secvenei, valoarea variabilei }while(i<n);
x va fi 1 dac: d) i=0;
a) deasupra diagonalei principale do{ printf(%d, v[i]);
exist cel puin un element egal i++
cu 0 }while(i<n);
b) toate elementele de deasupra e) nici una
diagonalei principale sunt 0
c) toate elementele de sub 11. Care dintre secvenele de mai jos afieaz
diagonala principal sunt corect produsul elementelor pare ale unui
diferite de 0 vector v[0],.......,v[n-1] cu n elemente ntregi ?
d) toate elementele de sub a) p=1;
diagonala principal sunt 0 for(j=1;j<=n;j++)
e) sub diagonala principal exist if(v[j]%2==) p=p*v[j];
cel puin un element diferit de b) p=1;
0 for(j=0;j<n;j++)
if(v[j]/2==0) p=p*v[j];
9. Fie urmtorul program: c) p=0;
#include<stdio.h> for(j=0;j<n;j++)
void main() if(v[j]%2!=0) p=p*v[j];
{ d) p=1;
int v[20], i, n, E; for(j=0;j<n;j++)
scanf(%d, &n); if(v[j]%2==0) p*=v[j];
for(i=0;i<n;i++) v[i]=i%2 ?i:-i; e) p=0;
for(E=1,i=0;i<n; E*=v[i++]); for(j=0;j<n;j++)
E++; if(v[j]%2==0) p*=v[j];
printf(%d,E);
} 12. Care dintre afirmaiile de mai jos sunt
n urma execuiei sale sunt posibile adevrate pentru secvena de program
urmtoarele situaii: urmtoare ?
p=0;
a) expresia condiional din primul for(k=1;k<6;k++)
ciclu for este eronat din punct
if(v[k]>v[p]) p=k;
de vedere sintactic
printf(%d, p);
b) dac variabila n primete prin a) secvena este corect din punct
citire valoarea 6, atunci de vedere sintactic
elementele vectorului v vor fi,
b) ciclul for are cinci pai
n ordine (0,1,-2,3,-4,5)
c) dac elementele vectorului sunt
c) prezena caracterului ; dup 5,4,-11,9,-12,1,atunci programul
al doilea ciclu for constituie o afieaz valoarea 4
eroare
d) dac elementele vectorului sunt
d) dac variabila n primete prin 3,-2,8,6,11,4, atunci programul
citire valoarea 5, atunci afieaz valoarea 4
programul afieaz 32 e) indiferent care ar fi elementele
e) programul funcioneaz corect vectorului, secvena dat nu
pentru orice valoare ntreag a poate afia valoarea 0
lui n mai mic sau egal cu
MAXINT 13. Pentru secvena de program urmtoare,
precizai care dintre afirmaiile de mai jos sunt
10. Care dintre secvenele de program de mai adevrate:
jos afieaz corect elementele v[0], ......v[n-1] int j=0 , v[5]={1,1,1,1,1};
ale unui vector de ntregi ? while(j<5&&v[j]&&!v[j])
a) i=0; {v[j]=0;j++;}
a) expresia din while este eronat }
sintactic a) 0 b) 1 c) 3
b) declaraia i iniializarea d) 5
vectorului sunt corecte e) programul intr n bucl
c) dup execuia secvenei toate infinit
elementele vectorului vor fi 1
d) dup execuia secvenei toate 17. Deducei care vor fi, n ordine, de la stnga
elementele vectorului vor fi 0 la dreapta, elementele nenule ale vectorului a
e) execuia secvenei va produce un la sfritul execuiei secvenei de program
ciclu infinit urmtoare:
int k, j=0;
int v[7]={0,2,7,3,4,8,5};
14. Precizai care va fi efectul secvenei de
int a[7]={0,0,0,0,0,0,0};
program urmtoare, n care v[0],.....,v[n-1] este for(k=0;k<7;k++)
un vector cu n elemente ntregi. if((v[k]%2==0)&&(k%2!=0))
x=v[n-1];
{ a[j]=v[k]; j++; }
for(k=n-1;k>0;k--) v[k]=v[k-1];
a) 2,4,8 b) 7,5 c) 2,8
v[0]=x;
d) 2,3,8 e) 7,3,5
a) deplaseaz toate elementele
vectorului cu o poziie la 18. Care parcurgere pe linii i coloane a unei
dreapta matrici n*m este corect ?
b) deplaseaz toate elementele I) for(i=0;i<n;i++)
vectorului cu o poziie la for(j=0;j<m;j++)
stnga printf(%d,a[i][j]);
c) terge un element din vector II) for(j=1;j<m;j++)
prin deplasarea celor aflate for(i=1;i<m;i++)
naintea lui printf(%d,a[i][j]);
d) rotete circular vectorul cu o III) for(i=0;i<n;i++)
poziie for(i=0;j<m;i++)
e) nici una din variantele printf(%d,a[i][j]);
anterioare a) doar I b)doar II
c) doar I si II
15. Fie secvena de program urmtoare, n d) doar I si III
care v este un vector cu n elemente ntregi, iar
p este o variabil ntreag: 19. Care din secvenele de calcul a mediei unui
for(p=1,k=1;k<n;k++) ir de n ntregi este corect ?
if(v[k]==v[k-1]) p=0; I) int i,n,s;
printf(%d, p); float med;
Secvena afieaz 0 dac: s=0;
a) toate elementele sunt distincte for(i=0;i<n;i++) s+=a[i];
dou cte dou med=s/n;
b) toate elementele sunt egale II) int i,n,s;
c) exist dou elemente consecutive float med;
distincte for(i=0,s=0;i<n;i++) s+=a[i];
d) exist dou elemente consecutive med=(float)s/n;
egale III) int i,n,;
e) nici una din variantele de mai float med, s;
sus s=0;
for(i=0;i<n;i++) s+=a[i];
16. Ce valoare va fi afiat n urma execuiei med=s/n;
programului urmtor? a) doar I b)doar II
#include<stdio.h> c) doar III d) doar II i III
void main()
{ 20. Calculul mediei geometrice a unui ir de n
int v[]={0,1,2,0,4,5,6}; ntregi este:
int j=0,nr=0; I) int i,n, pr;
do{ float med;
if(j==v[j]) nr++; for(pr=1,i=0;i<n;i++)
}while(j<6&&v[j++]); pr*=a[i];
printf(%d,nr); med=sqrt(pr);
II) int i,n, pr; c) inversarea ordinii tuturor
float med; elementelor n vector numai cnd
for(pr=1,i=0;i<n;i++) n este par
pr*=a[i]; d) nici una din variantele indicate
med=pow(pr, 1/n);
III) int i,n, pr; 25. Se consider matricea ptratic A(mxm) .
float med; Fie secvena de program :
for(pr=1,i=0;i<n;i++) x=a[0][m-1];
pr*=a[i]; for(i=0;i<m;i++)
med=pow(pr, 1./n); if x<a[i][m-i] x=a[i][m-i];
a) doar I b) doar II Variabila x calculat exprim :
c) doar III d) doar II i III a) valoarea maxim de pe diagonala
principal
21. Ce secven calculeaz corect maximul b) valoarea maxim de pe diagonala
unui ir cu n valori? secundar
I) for(max=0, i=0;i<n;i++;) c) valarea maxim din ntreaga
if(a[i]>max) max=a[i]; matrice
II) max=a[0]; d) alt valoare decat cele indicate
for(i=0;i<n;i++)
if(a[i]>a[i++]) max=a[i]; 26. Fie matricea ptratic A(mxm) i secvena
III) max=a[0]; de program :
for(i=0;i<n;i++) x=a[0][0];
if(a[i]>max) max=a[i]; for(i=0;i<m;i++)
a) doar I b) doar II { if(x<a[i][i]) x=a[i][i];
c) doar III d) doar I i II if(x<a[i][m-i-1])
x=a[i][m-i-1];
22. Fie X[1..n] si Y[1..n] vectori de ntregi. Care }
va fi valoarea lui Y[n] dup execuia secvenei: Variabila x calculat reflect :
Y[1]=x[1]; a) valoarea cea mai mare de pe
for (i=2;i<n;i++) y[i]=y[i-1]+x[i]; diagonale
a) x[n]+x[n-1] b) x[n] b) valoarea cea mai mare de pe
c) x[1]+x[2]+..+x[n] diagonala principal
d) nici una din valorile indicate c) valoarea cea mai mare de pe
diagonala secundar
23. Fie X[1..n] si Y[1..n] vectori de numere d) alt valoare decat cele indicate
reale. Dup execuia secvenei de program :
y[1]=-x[1]; 27. Fie matricea A(mxm) i secvena de
for(i=2;i<n;i++) y[i]=y[i-1]*x[i]; program:
elementul Y[n] exprim : s=1;
a) x[1]*x[2]**x[n] for(i=0;i<m;i++)
b) x[1]*x[2]*.*x[n] for(j=0;j<i;j++) s*=a[i][j];
c) (-1)n x[1]*..*x[n] Valoarea calculat s reflect :
d) nici una din valorile indicate a) produsul valorilor de sub
diagonala principal
24. Fie V[1..n] vector de intregi . Secvena de b) produsul valorilor de pe
program : diagonala secundar
i=1; c) produsul valorilor din ntreaga
for(i=1;i<=n/2;i++) matrice
{ j=n-i; d) alt valoare dect cele indicate
aux=v[i]; v[i]=v[j];
v[j]=aux; 28. Fie o matrice A(nxn) citit de la tastatur .
} Atunci secvena de cod :
are ca efect : i=0; m=a[0][0];
a) inversarea ordinii elementelor while(i<n) {
n vector for(j=0;j<n;j++)
b) inversarea ordinii tuturor if(m<a[i][j]) m=a[i][j];
elementelor n vector numai cnd i++;
n este impar }
a) calculeaz elementul maxim m
dintre elementele matricii
b) calculeaz elementul minim m 33. Ce realizeaz urmtoarea secven de
dintre elementele matricii program?
c) se cicleaz la infinit i=0;
do {
d) numr elementele matricii care i++;
sunt mai mari ca m
a[i]=nr%2;
nr/=2;
29. Fie secvena de cod de mai jos. Dac }while(nr);
considerm ca date de intrare tabloul V1 de n=i;
dimensiune n, atunci tabloul V0 va conine : for(i=n;i>0;i--) printf(%d,a[i]);
for(i=0;i<n;i++) v0[n-i-1]=v1[i];
a) convertirea b10->b2 a unui numr
a) elementele lui V1 n ordine fracionar
invers b) convertirea b10->b2 a unui numr
b) o parte din elementele lui V1 ntreg
c) numai elem. impare ale lui V1 c) convertirea b10->b3 a unui numr
d) algoritmul depune elementele lui ntreg
V1 n ordine invers numai dac n d) convertirea b10->b2 a unui numr
este impar ntreg pozitiv

30. Fie urmtoarea secven de cod care 34. Se d urmtoarea secven de cod :
primete o matrice M ptratic de dimensiune n int y[5]={3,4,5,6,0};
la intrare : Ce valoare conine y[3] ?
p=1; a) 3 b) 5 c) 6
for(i=0;i<n;i++) p=p*m[i][i]-2; d) codul nu compileaz pentru c nu
atunci aceasta realizeaz : sunt destule valori
a) produsul elementelor din matrice
b) produsul elementelor de pe 35. Se d codul :
diagonala principal a matricii m short testarray[4][3]=
c) o prelucrare a elementelor de pe {{1},{2,3},{4,5,6}};
diagonala principal a matricii m printf(%d\n,sizeof(testarray));
d) se cicleaz la infinit Presupunnd c tipul short este de lungime 2
octei, ce va afia codul de mai sus ?
31. Care este valoarea elementului tab[2][3] a) nu va compila pentru c nu sunt
dup execuia secvenei de cod : dai destui iniializatori
int i,j; b) 6 c) 12 d) 24
int ctr=0;
int tab[4][4]; 36. Fie secvena de cod :
for(i=0;i<4;i++) int x,i,t;
for(j=0;j<4;j++) int y[10]={3,6,9,5,7,2,8,10,0,3};
{ tab[i][j]:=ctr; ++ctr; } while(1)
a) 7 b) 9 c) 11 d) 14 { x=0;
for(i=0;i<9;i++)
32. Ce face urmtoarea secven ? if (y[i]>y[i+1])
scanf(%d,&n); { t=y[i];
for(i=0;i<n;i++) scanf(%d,&a[i]); y[i]=y[i+1];
printf(\n%d,a[0]); y[i+1]=t;
for(i=1;i<n;i++) x++;
{ ex=0; }
for(j=0;j<i;j++) if(x==0) break;
if(a[i]==a[j]) ex=1; }
if(!ex) printf(%d,a[i]); Cum va arta vectorul dup execuia acestui
} cod ?
a) afieaz numerele dintr-un ir a) programul va rula la infinit
care sunt n mai multe exemplare b) {0,2,3,3,5,6,7,8,9,10}
b) afieaz numerele cu apariie b) {10,9,8,7,6,5,3,3,2,0}
singular n ir c) {3,6,9,5,7,2,8,10,0,3}
c) afieaz numerele dintr-un ir
d) afieaz numerele impare dintr- 37. Exist greeli n secvena de calculare a
un ir mediei aritmetice?
#include<stdio.h>
#include<conio.h> }
void main(void) a) nu, secvena este corect
{ int a[30],i,n=20; b) da, deoarece nu au fost
int s=0; float ma; citite toate elementele
for(i=0;i<n;i++) tabloului
{ printf(\na[%d]=,i); c) da, deoarece va fi afiat
scanf(%d,&a[i]); doar partea ntreag a
} rezultatului
for(i=0;i<n;i++) s=s+a[i]; d) da, deoarece nu au fost
ma=s/n; citite corect toate elementele
printf(\nRezultatul=%f,ma); vectorului
getch();
Cap.7 Pointeri

7.1 Variabile pointer

n memoria intern, valorile variabilelor sunt stocate n locaii care sunt referite prin numere
numite adrese. O locaie de memorie are asociat o adres unic. Cea mai mic entitate de memorie
adresabil direct este bytul sau octetul. S presupunem variabila de tip ntreg a cu valoarea 7 ce ocup
n memorie doi octei. Valoarea variabilei a, care este 7, ocup o locaie de memorie care se poate
referi direct prin numele variabilei sau indirect prin adresa ei, adr(a).
O variabil capabil s stocheze adresa unei alte variabile se numeste pointer.
Limbajul C pune la dispoziie doi operatori pentru lucru cu adrese :
- operatorul & cu rol de extragere a adresei unei variabile
- operatorul * cu rol de extragere a coninutului zonei de memorie adresate de o variabil pointer
Variabila pointer se definete n concordan cu un tip de dat. De exemplu, declaraia int *px;
precizeaz c px este un pointer spre ntreg, adic variabila px este capabil s stocheze adresa unui
ntreg. Operatorul * , n declaraie, are rolul de a exprima faptul c nu px este de tip ntreg ci coninutul
de la adresa memorat n px este de tip ntreg. Deci px este un pointer la ntreg.
Fie programul :
#include<stdio.h>
void main()
{
int x=5,*px;
px=&x;
printf(\nx=%d,x);
printf(\nx=%d,*px);
}
n urma execuiei lui se va afia de dou ori valoarea variabilei x, adic 5. n primul caz s-a folosit
adresarea direct a variabilei folosindu-se numele ei. n al doilea caz s-a folosit adresarea indirect a
variabilei, mai precis, s-a extras coninutul de la adresa ei (*px). Se observ c, n prealabil, adresa
variabilei x a fost stocat n pointerul px.
Pe lng definirea de pointeri spre tipurile fundamentale cum ar fi :
float *py; - py este un pointer la float
char *pc; - pc este un pointer la caracter
exist posibilitatea definirii acestora i spre tipuri structurate de date. Astfel, declaraiile :
int (*px)[10]; exprim faptul c px este un pointer la un vector cu 10 elemente de tip
ntreg
int *pt[10]; exprim faptul c pt este un vectori de pointeri la ntregi.
Este important ca pointerul s stocheze adresa unei variabile ce are un tip bine definit, pentru ca
expresii de genul *pointer s se poat evalua corect Coninutul de la o adres poate fi de dimensiuni
diferite, minim un octet. Avnd bine precizat tipul de dat referit de pointer, coninutul de la acea adres
este extras n mod corect n funcie de mrimea n octei a tipului de dat respectiv. n exemplu, *px
refer doi octei de la adresa stocat n px considernd c un ntreg se memoreaz pe 2 octei. Exist
i pointerul generic, adic un pointer fr tip de dat asociat (spre void) ce se declar sub forma void
*p. Acest tip de pointer este folosit mai mult pentru transferul i stocarea adreselor n cadrul
programelor.
Un alt aspect important ce ine de lucrul cu variabile pointer, care genereaz erori n munca de
programare, se refer la faptul c se poate accesa coninutul unei variabile pointer numai dup ce
pointerul refer o zon de memorie ce a fost alocat n prealabil. Se mai spune c, n acest caz,
pointerul conine o adres valid .
Prezentm dou moduri de ncrcare a unui pointer :
a) cu adresa unei variabile anterior definit; n acest caz alocarea s-a fcut la momentul definirii
variabilei :
int a=30,*pa;
pa=&a;
b) prin alocare dinamic de memorie ce se face n momentul execuiei programului ; pentru realizarea
unei astfel de operaii se poate folosi operatorul new. Forma general este :
pointer=new tip;
unde : - pointer reprezint variabila pointer ce urmeaz a se ncrca
- tip reprezint un tip de date pentru care se face alocarea zonei de memorie; se folosete
pentru a determina mrimea n octei a zonei de memorie ce urmeaz a se aloca i care este egal cu
sizeof(tip) .
Exemplu:
int *pi;
pi=new int;
*pi=5;
printf(\n%d,*pi);
n cazul n care se dorete a se aloca o zon de memorie care s stocheze mai muli ntregi (nr) atunci
se va folosi operatorul new n forma :
pointer=new tip[nr];
unde : - tip este tipul de dat referit de pointer
- nr reprezint numrul de elemente de tipul tip
Mrimea n octei ce se va aloca se obine conform relaiei : nr*sizeof(tip) .
Legat de acest operator, limbajul C pune la dispoziie i operatorul delete pentru dealocarea unei zone
de memorie alocat n prealabil cu operatorul new. Forma de utilizare a operatorului este :
delete pointer sau delete [nr]pointer
unde : - pointer reprezint variabila pointer
- nr reprezint numrul de elemente cu tipul referit de variabila pointer
Exemplu: Se va aloca dinamic o zon de memorie capabil s stocheze n valori double, dup care
spaiul va fi dealocat.
double *p;
int n=5;
p=new double[n];
..
delete [n]p;
Memoria alocat dinamic i pstreaz coninutul pn cnd se dealoc n mod explicit n cadrul
programului.

7.2 Aritmetica pointerilor

Aritmetica pointerilor reprezint ansamblul operaiilor care se pot efectua cu o variabil


pointer. Acestea sunt :
1) Operaia de extragere a coninutului unei variabile pointer care a fost exemplificat anterior
(*pointer)
2) Operaia de extragere a adresei unei variabile pointer. Avnd n vedere c pointerul este la rndul
lui tot o variabil i acesteia i se poate extrage adresa. Variabila care memoreaz adresa unei alte
variabile pointer se numete pointer la pointer.
Exemplu :
int a=15,*pa,**ppa;
/* ppa este un pointer la pointer la ntreg */
pa=&a;
ppa=&pa;
printf(\na=%d,**ppa);
Variabila a a fost afiat folosindu-se o dubl indirectare .
3) Operaia de atribuire ntre pointeri este permis doar dac pointerii refer acelai tip. Fie secvena :
int a=7,*pa1,*pa2;
pa1=&a;
pa2=pa1;
/* ambele variabile pointer conin adresa lui a */
printf(\n a=%d a=%d,*pa1,*pa2);
Se va afia de dou ori valoarea 7 indirect, prin intermediul celor doi pointeri care conin aceeai
adres.
4) Operaia de incrementare, respectiv decrementare a unui pointer, presupune obinerea unei adrese
mai mari, respectiv mai mici, n funcie de dimensiunea tipului de dat referit de pointer.
Exemplu :
double a[]={5.3,2.1},*pa;
pa=&a[0];
/* adresa de nceput a tabloului , adic adresa elementului a[0] */
printf(\n Primul element=%lf,*pa);
pa++;
/* conine adresa urmtorului element din tablou , adic adresa lui a[1] */
printf(\n Al doilea element=%lf,*pa);
5) Operaia de adunare a unui ntreg la un pointer. Dac se adun variabila k la un pointer spre tipul
TIP se obine o dres mai mare cu k*sizeof(TIP).
Exemplu :
double a[]={5.3,2.1,8.9,10},*pa;
int i;
pa=&a[0];
i=2;
printf(\n %lf,*(pa+i));
/* se va afia al treilea element din vector adic 8.9 */
i=3;
print(\n %lf,*(pa+i));
/* se va afia al patrulea element din vector adic 10 */
6) Operaia de conversie ntre pointeri. Aceast operaie se face cu ajutorul operatorului de conversie
explicit (cast). Pentru exemplificare vom prezenta o funcie ce are ca scop alocarea dinamic de
memorie . Ea are prototipul : void *malloc(int); care se afl n header-ul alloc.h. Parametrul are
ca scop dimensionarea zonei de memorie n octei i funcia returneaz adresa la care s-a alocat
zona de memorie. Se observ c aceast funcie returneaz un pointer la void adic un pointer
generic care nu poate fi folosit n cele mai multe operaii uzuale asupra pointerilor. De aceea, el
trebuie convertit ntr-un pointer spre un tip de dat bine precizat. Pentru dealocarea zonei de
memorie ce a fost alocat anterior cu funcia malloc, biblioteca limbajului pune la dispoziie funcia
free care are prototipul : void free(void *);
Parametrul funciei reprezint pointerul ncrcat printr-un apel al funciei malloc. n secvena :
int *pa,n=5;
pa=(int*)malloc(n*sizeof(int)); /* conversie n pointer spre ntreg */

free(pa);
s-a alocat o zon de memorie capabil s stocheze 5 variabile de tip ntreg. Adresa zonei a fost
stocat n variabila pointer spre ntreg pa. Dup ce s-au efectuat prelucrrile necesare asupra
zonei de memorie i ea nu mai este necesar n program, atunci se elibereaz spaiul cu funcia
free.
7) Operaia de scdere a doi pointeri necesit ca pointerii s fie spre acelai tip. Rezultatul reprezint
numrul de elemente de tipul referit de pointer ce se afl ntre cele dou adrese. n cazul n care
tipul de dat referit de pointer este TIP atunci diferena dintre doi pointeri (p1 i p2) se calculeaz
dup relaia (p1-p2)/sizeof(TIP).
Ca exemplu, se va scrie secvena de program care determin lungimea unui ir de caractere :
char sir[50],*pc;
printf(\n Dati sirul : );gets(sir);
pc=&sir[0];
while(*pc++);
printf(\n Lungimea sirului este %d,pc-sir-1);
8) Operaia de comparaie dintre pointeri se realizeaz folosind operatorii de egalitate i cei relaionali.
Astfel, ca exemplu, se va prezenta secvena de traversare a unui vector n scopul afirii
elementelor sale:
int a[]={5,4,3,2,7};
int n=sizeof(a)/sizeof(int); /* numrul de elemente din vector*/
int *p1,*p2,*pc;
for(p1=pc=&a[0],p2=&a[n-1];pc<=p2;pc++)
printf(\n elementul %d,*pc);
7.3 Legtura pointer tablou

Tabloul, prin definiie, este o structur de date omogen cu un numr finit i cunoscut de
elemente. Fiind definit tabloul int a[50], numele lui reprezint adresa primului element din tablou
(a=&a[0]). Avnd stabilit aceast legtur se pot defini mai multe modaliti echivalente de accesare a
unui element din tablou. Astfel, elementul de rang i se acceseaz folosind una din relaiile :
a[i]; (1)
*(a+i); (2)
*(&a[0]+i); (3)
i[a]; (4)
c) relaia (1) este forma obinuit de accesare a elementului de rang i numit i adresare indexat
d) relaia (2) este forma de adresare a elementului de rang i indirect, pornind de la adresa acestuia
e) relaia (3) este derivat din relaia 2, doar c se pune n eviden n mod explicit c numele
tabloului este adresa primului element din vector
f) relaia (4) deriv din faptul c expresia a[b] este evaluat de compilator n forma *(a+b). Deoarece
adunarea este comutativ, pentru exemplul nostru a[i] *(a+i) *(i+a) i[a].
Acelai concept se aplic tablourilor cu dou sau mai multe dimensiuni. De exemplu,
presupunnd c a este un tablou de ntregi cu 10 linii i 10 coloane (a[10][10]), urmtoarele dou
expresii sunt echivalente: a i &a[0][0]. n continuare, elementul din linia 0 i coloana 4 poate fi
referit n dou moduri: fie prin aplicarea de indeci, a[0][4], fie prin intermediul unui pointer *(a+4). n
general, pentru orice tablou bidimensional, a[j][k] este echivalent cu una din formele :
*(a+(j*numar_coloane)+k)
*(a[j]+k)
*(*(a+j)+k)
Ca observaie, numele unui vector este un pointer constant. O consecin este c aritmetica de
pointeri ce se aplic acestui tip de pointer este mai restrns n sensul c, acest pointer nu-i poate
modifica valoarea. O alt particularitate const n faptul c operatorul sizeof aplicat unui vector ntoarce
numrul de octei al ntregii zone ocupat de vector.
Pn acum s-a evideniat legtura dintre pointer i tablou n sensul c s-a definit un tablou i a
fost exploatat prin intermediul pointerilor. Sensul este i reciproc, adic definind un pointer, zona de
memorie alocat poate fi utilizat ca i cum ar fi numele unui tablou. Ca exemplu, se va defini o zon
de memorie capabil a stoca n ntregi, apoi se va ncrca zona de memorie prin citire de la tastatur i
se va calcula suma elementelor introduse.
int *pa,n,s;
printf(\n Nr. de elemente=);
scanf(%d,&n);
pa=(int*)malloc(n*sizeof(int));
for(int i=0;i<n;i++)
{ printf(\n elem[%d]=,i+1);
scanf(%d,&pa[i]);
}
for(i=s=0;i<n;i++) s+=pa[i];
printf(\n suma=%d,s);
Se observ c elementele zonei de memorie referite de pointerul pa au fost accesate folosindu-se
adresarea indexat pa[i] care este specific lucrului cu tablouri.
n limbajul C, pointerii i tablourile sunt n strns legtur ei fiind de fapt interschimbabili. Dac
folosii numele unui tablou fr index, generai de fapt un pointer ctre primul element al tabloului. Iat
de ce nu este necesar nici un index atunci cnd are loc citirea unui ir folosind funcia gets(). Ceea ce
este transferat funciei gets() nu este un tablou, ci un pointer. De fapt, n C nu se poate transfera un
tablou unei funcii, ci numai un pointer ctre tablou. Funcia gets() folosete un pointer pentru a ncrca
tabloul de caractere introdus de la tastatur.
Exemplul 1: Deoarece numele unui tablou fr index este un pointer ctre primul element al tabloului,
aceast valoare poate fi asignat unui alt pointer i prin aceasta devine posibil accesarea elementelor
tabloului folosind pointerul aritmetic. S considerm urmtorul program:
#include<stdio.h>
int a[10]={1,2,3,4,5,6,7,8,9,10};
void main()
{ int *p;
p=a; /* asigneaz lui p adresa de nceput a tabloului a */
/* afiarea primelor trei elemente ale tabloului a */
printf(%d %d %d,*p,*(p+1),*(p+2));
/* afieaz acelai lucru */
printf(%d %d %d,a[0],a[1],a[2]);
}
n acest caz, ambele instruciuni printf() afieaz acest lucru. Parantezele din expresii ca *(p+2) sunt
necesare, deoarece operatorul * referitor la pointeri are o preceden mai mare dect operatorul +.
Dac folosii un pointer pentru a accesa un tablou bidimensional, trebuie s executai manual ceea ce
compilatorul face automat. De exemplu, n tabloul float balance[10][5];fiecare rnd are 5
elemente. Pentru a accesa balance[3][1] folosind un pointer de tip float, trebuie utilizat un fragment de
forma: *(p+(3*5)+1);
n general, la tablourile multidimensionale este mai uoar folosirea indexrii numelui dect folosirea
pointerului aritmetic.
Exemplul 2: Un pointer se poate indexa ca i cnd ar fi un tablou. Urmtorul program este valid:
#include<stdio.h>
char str[]=Pointerii sunt puternici;
void main()
{ char *p;
int j;
p=str;
for(j=0;p[j];j++) /* ciclare pn la ntlnirea caracterului NULL */
printf(%c,p[j]);
}
Exemplul 3: Un pointer poate fi indexat numai dac el puncteaz un tablou. Dei urmtorul program
este corect din punct de vedere sintactic, executarea lui va conduce probabil la blocarea calculatorului:
char *p,ch;
int i;
p=&ch;
for(i=0;i<10;i++) p[i]=A+i;
ntruct ch nu este un tablou, pointerul p nu poate fi indexat. Dei un pointer punctnd un tablou poate
fi indexat ca i cum ar fi un tablou, rareori se va proceda astfel, deoarece, n general, prin folosirea
pointerilor aritmetici se obin programe mai rapide.
Exemplul 4: n biblioteca ctype.h exist funciile toupper() i tolower() care transform literele mici n
litere mari i invers. Urmtorul program cere utilizatorului s introduc un ir de caractere i apoi
afieaz irul introdus mai nti cu litere mari i apoi cu litere mici. Versiunea urmtoare, pentru a
accesa caracterele din ir, indexeaz numele tabloului.
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
void main()
{ char str[80];
int i;
clrscr();
printf(Introduceti un sir : );
gets(sir);
for(i=0;str[i];i++) str[i]=toupper(str[i]);
puts(sir); /* afiarea cu litere mari */
for(i=0;sir[i];i++) str[i]=tolower(str[i]);
puts(sir); /* afisarea cu litere mici */
getch();
}
Exemplul 5: n varianta urmtoare este folosit un pointer pentru a accesa caracterele irului i este
preferat de programatorii profesioniti deoarece incrementarea unui pointer este mai rapid dect
indexarea unui vector.
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
void main()
{ char str[80], *p;
int i;
clrscr(); printf(introduceti sirul: ); gets(str);
p=str;
while(*p) *p++=toupper(*p);
puts(sir); /* afiarea cu litere mari */
p=str;
while(*p) *p++=tolower(*p);
puts(str); /* afiarea cu litere mici */
getch();
}
Exemplul 6: Un pointer poate fi i decrementat. Urmtorul program folosete un pointer pentru a copia
coninutul unui ir n alt ir, n ordine invers:
#include<stdio.h>
#include<string.h>
char str1[]=Pointerii sunt foarte utili;
void main()
{ char str2[80],*p1,*p2;
/* p1 va puncta sfritul irului str1 */
p1=str1+strlen(str1)-1;
p2=str2; /* nceputul irului str2 */
while(p1>=str1) *p2++=*p1--;
*p2=\0; /* caracterul null incheie sirul str2 */
printf(%s %s,str1,str2);
getch();
}
Exemplul 7: Limbajul C permite utilizarea irurilor constante (iruri de caractere scrise ntre ghilimele).
Cnd compilatorul ntlnete un astfel de ir, l depune n tabela de iruri a programului i genereaz un
pointer ctre el. De exemplu, programul urmtor citete iruri pn cnd este tastat irul stop :
#include<stdio.h>
#include<sting.h>
char *p=stop;
void main()
{
char str[80];
do{
printf(introduceti un sir : );
gets(str);
}while(strcmp(p,str));
}
Folosirea pointerilor ctre irurile constante poate fi foarte util cnd aceste constante sunt foarte lungi.
De exemplu, s presupunem c, n anumite puncte ale sale, un program afieaz un mesaj. Pentru a
tasta ct mai puin, trebuie aleas varianta de a iniializa un pointer ctre un ir constant i apoi, cnd
trebuie afiat mesajul, s fie folosit acest pointer.
char *p=Insert disk into drive A then press ENTER;
..
printf(p);

printf(p);
.
Un alt avantaj al acestei metode const n faptul c, dac mesajul trebuie modificat, schimbarea trebuie
fcut o singur dat i toate referirile la mesaj vor reflecta modificarea fcut.
Exemplul 8: Funcia gets() citete caracterele introduse de la tastatur pn cnd este apsat tasta
Enter. Dac operaia se termin cu succes, gets() returneaz un pointer ctre nceputul irului. n cazul
unei erori este returnat un pointer null. Programul urmtor arat cum poate fi folosit pointerul returnat
de gets() pentru a accesa un ir care conine informaii de intrare. nainte de a folosi irul, programul
verific dac nu au aprut erori de citire.
#include<stdio.h>
void main()
{ char str[80],*p;
printf(Introduceti un sir :);
p=gets(str);
/* dac p nu este null se afieaz irul */
if(p)printf(%s %s,p,str);
}
Dac dorii s fii siguri c funcia gets() nu a lucrat cu erori, o putei plasa direct n instruciunea if ca n
exemplul urmtor :
#include<stdio.h>
void main()
{ char str[80];
printf(Introduceti un sir : );
/* dac pointerul ctre nceputul irului nu este null se produce afiarea */
if(gets(str)) printf(%s,str);
}

7.4 Exerciii i teste gril

1. Fie declaraia: int var,*pointer;. { int *pi;


Verificai dac expresia: (&pointer) are for(pi=a;pi<a+10;)
aceeai semnificaie cu pointer i &(var) printf(\n%p:%d,pi,++*pi++);
are aceeai semnificaie cu var. Cum explicai }
aceasta ?
7. Fie declaraia : int a[10][10];
2. Fie declaraia: double d,*pd;. S se Care din expresiile urmtoare sunt
decid dac variabilele d i pd au aceeai echivalente?
a) *a[i] b) **(a+i) c) *(*a+i)
dimensiune.
d) a[0][i] e) a[i][0]
3. Considerm declaraiile :
int n, const int a=10 , *pci=&a; 8. Este corect secvena char*s;gets(s); ?
S se determine care dintre instruciuni sunt
corecte : 9. Explicai care din instruciuni sunt greite n
n=a; a=2; secvena urmtoare :
n=*pci; *pci=1; char *s=Test C;
pci++; *s=Ansi C;
s=Ansi C;
4. Fie declaraiile :
int n=10; const *cpi=&n; 10. Care dintre urmtoarele variante reprezint
S se determine corectitudinea instruciunilor o declaraie corect a unei variabile x de tipul
urmtoare : adres a unei variabile ntregi ?
*cpi=1; cpi=&n; a) int x*; b) int *x; c)
cpi++; n=cpi; int x;
d) int &x; e) int x&;
5. Precizai ce tiprete programul urmtor :
#include<stdio.h> 11. Se consider declaraia de variabile:
long int m, *x,*y;
a[10]={10,11,12,13,14,15,16,17, Care dintre urmtoarele atribuiri sunt corecte ?
18,19}; a) x=m; b) *x=*m; c) *y=*x;
void main() d) y=&m; e) y=x;
{ long *pi;
for(pi=&a[0]; pi<&a[10]; pi++) 12. Fie declaraiile de variabile:
printf(\n%p:%ld, pi, *pi); int a=2,b; int *x,*y;
} Precizai ce valori se vor afia, n ordine, n
urma execuiei secvenei de program de mai
6. Precizai ce face programul urmtor: jos:
#include<stdio.h> x=&a; a=5; printf(%d, *x);
int a[10]={10,11,12,13,14,15,16,17, b=a-2; y=&b; b+=(*y)+4;
18,19}; printf(%d, b);
void main() *y=*x; printf(%d, *y);
if(x==y) putchar(1); 17. Fie declaraiile de variabile:
else putchar(0); int a=2,b,c=5; int *x,*y;
a) 2,10,2,1 b) 2,10,2,0 c) 5,7,5,0 Precizai ce valori se vor afia, n ordine, n
d) 5,10,5,0 e) 5,10,5,1 urma execuiei secvenei de program de mai
jos:
13. Se consider urmtoarea secven de x=&c; a+=*x; printf(%d,a);
program: b=++a; y=&b; printf(%d,*y);
int *q,**p,a=5,b=3; x=y; printf(%d,(*x)++;
*p=&a; // (1) a) 7,7,7 b) 7,8,9 c) 7,8,8
q=*p; // (2) d) 7,7,8 e) 8,8,9
b+=*(&(**p)); // (3)
printf(%d %d,*q,b); 18. Fie un pointer x ctre ntreg. Care dintre
Ce putei spune despre atribuirile (1), (2) i (3)? instruciunile de ma jos realizeaz corect
a) nici una dintre atribuiri nu alocarea dinamic a memoriei ?
este corect a) x=(int)malloc(sizeof(int*));
b) numai atribuirea (1) este b) x=(int*)malloc(sizeof(int*));
`corect c) x=(int*)malloc(sizeof(int));
c) numai atribuirile (1) i (2) d) *x=(int*)malloc(sizeof(int));
sunt corecte e) *x=(int)malloc(sizeof(int*));
d) toate sunt corecte i secvena
afieaz de dou ori numrul 5 19. Fie urmtoarele declaraii de variabile:
e) toate atribuirile sunt corecte int **a,*b,c;
i secvena afieaz numerele 5 Care dintre expresiile de mai jos vor genera
i 8 eroare la execuie?
a) a=&(&c); b) b=&(**a);
14. Fie atribuirea : *y=&(*(&z)); Cum c) *a=&c; d) **a=&b;
trebuie scrise corect declaraiile de variabile, e) *b=**a+c;
astfel nct atribuirea s fie corect ?
a) int *y,z; b) int y,*z; 20. Considerm declaraia: int **p;
c) int y,**z d) int **y,z; i atribuirea p=&q; Alegei varianta potrivit
e) int **y,*z;
astfel nct atribuirea s aib sens.
a) int q; b) int *q;
15. Care dintre instruciunile (I),(II),(III),(IV) din c) int ***q; d) int &q;
programul urmtor sunt eronate? Precizai e) nici una
valorile obinute n cazul instruciunilor corecte.
#include<stdio.h>
21. Precizai valoarea variabilei a ca urmare a
void main()
execuiei programului urmtor:
{ void main()
const int x=3; int u,v; {
x=4; // (I) int a; char b=1;
*(int*)&x=8; // (II) a=*(int*)&b;
u=x; // (III) }
v=*(int*)&x; // (IV) a) 1 b) 97 c) neprecizat
} d) nici una e) programul este
a) I b) II c) III greit
d) IV e) nici una
22. Precizai care dintre instruciunile de
16. Alegei atribuirea corect din programul de atribuire de mai jos face ca x s primeasc
mai jos: valoarea 0:
void main() void main()
{ {
int a; void *p; int a=1,b=2; float x;
p=(int*)&a; // (I) x=a/ *&b; // (I)
p=&a; // (II) x=(float) a/b; // (II)
p=(float*)&a; // (III) }
p=&(int*)a; // (IV) a) I b) II c) ambele
} d) nici una e) programul este
a) I b) II c) III gresit
d) IV e) nici una
23. Care dintre instruciunile de tiprire vor printf(%d\n,*v[0]); //(2)
afia aceeai valoare ? *(v+1)=&b; //(3)
#include<stdio.h> printf(%d\n,*(*(v+1))); //(4)
void main() 2[v]=&c; //(5)
{ printf(%d\n,*v[2]); //(6)
int a=2,*p=&a; }
printf(%d\n,*p+1); a) declaraia vectorului este eronat
printf(%d\n,*&p+1); b) atribuirile (1), (3) i (5)
printf(%d\n,*(p+1)); sunt toate corecte
printf(%d\n,*(&p+1)); c) atribuirea (1) este corect, iar
} (3) i (5) sunt eronate
a) prima i a doua d) atribuirile (1) i (3) sunt
b) a doua i a treia corecte, iar (5) este eronat
c) a doua i a patra d) nici una e) programul este corect i
e) programul este eronat afieaz valorile 5, -12, 7

24. n programul urmtor, care dintre cele 27. Ce va afia programul urmtor?
patru instruciuni va tipri valoarea 11? #include<stdio.h>
#include<stdio.h> void main()
void main() {
{ int (*v)[3];
const int x=2,y=3; int u[]={10,11,12};
*(int*)&x=8; v=&u;
*(int*)&y=9; printf(%d,(*v)[1];
printf(%d\n,x+y); }
printf(%d\n,*(int*)&x+y; a) programul este eronat
printf(%d\n,x+*(int*)&y; b) o adres de memorie oarecare,
printf(%d\n,*(int*)&x+ fr nici-o semnificaie
*(int*)&y; c) valoarea ntreag 11
} d) adresa de memorie la care se
a) prima b) a doua c) a treia afl valoarea ntreag 11
d) a patra e) nici una e) adresa ncepnd cu care se
gsete vectorul v n memorie
25. Fie programul urmtor:
#include<stdio.h> 28. Se consider urmtoarea secven de
void main() program:
{ int a[9][11],i,j;
int m[9],i; for(i=0;i<9;i++)
for(i=0;i<9;i++) m[i]=i; for(j=0;j<11;j++)
while(i>0) if(i==j) (*(a+i)) [j]=0;
{ i--; *(m+i)=-i; } else *(*(a+i)+j)=i*j;
} Precizai care dintre afirmaiile de mai jos sunt
Care dintre afirmaiile de mai jos sunt false:
adevrate ? a) a[5][2] este 10
a) ambele cicluri sunt greite b) a[8][0] este 6
b) numai primul ciclu este corect c) *(*(a+3)+3) este 0
c) numai al doilea ciclu este d) programul conine erori de
corect sintax
d) ambele cicluri sunt corecte e) matricea a este simetric fa
e) n cele dou cicluri, de diagonala principal
elementele vectorului vor primi
valori egale n modul, dar de 29. Se consider urmtoarele declaraii de
semne opuse variabile:
int q=6,d[3][4],(e[3])[4],v[4];
26. Se consider programul urmtor: int *a[3][4],(*b)[3][4],
#include<stdio.h> (*c[3])[4];
void main() Care dintre atribuirile de mai jos sunt corecte?
{ a) d[0][2]=e[1][3];
int a=5,b=-12,c=7,*v[3]; b) a[2][3]=&q;
v[0]=&a; //(1) c) b=&d; d) c[2]=&v;
e) toate atribuirile anterioare
33. Fie urmtorul program:
30. Precizai ce valoare va afia programul #include<stdio.h>
urmtor: void main()
#include<stdio.h> {
void main() int x[4]={1,2,3},
{ y[4]={4,5,6,7},z[7];
int a[20][20],i,j,n=4; int i,j;
for(i=0;i<n;i++) for(i=0;i<4;i++)
for(j=0;j<n;j++) *(z+i)=*(y+i);
*(*(a+i)+j)=(i>j)? for(j=0;j<3;j++)
(j-i) : (j+i); *(z+i+j)=*(x+j);
int m=10; for(i=0;i<7;i++)
for(i=0;i<n;i++) printf(%d,*(z+i));
for(j=0;j<n;j++) }
if(m>(*(a+i))[j]) Care vor fi valorile afiate n urma execuiei
m=a[i][j]; sale?
printf(%d,m); a) 1,2,3,4,5,6,7 b) 7,6,5,4,3,2,1
} c) 3,2,1,7,6,5,4 d) 4,5,6,7,1,2,3
a) 10 b) 6 c) 3 d) 3 e) programul este eronat
e) programul este eronat
34. Fie secvena de instruciuni:
31. Fie vectorul y cu patru elemente numere int x[]={10,20,30,40,50};
ntregi: int*ptr=x;
int y[4]={0,1,2,3}; printf(%d\n,*(ptr+2));
Care dintre urmtoarele instruciuni declar i printf(%d\n,*(ptr)+2);
iniializeaz corect un pointer ptr ctre vectorul Ce se va tipri dup executarea codului de mai
y? sus?
a) int *(ptr[4])=&y; a) 30 30 b) 30 12
b) int (ptr*)[4]=&y; c) 12 12 d) 12 30
c) int (*ptr)[4]=&y;
d) int ptr*[4]=&y; 35. Fie secvena de instruciuni:
e) int *ptr[4]=&y; int *array[3];
int(*ptr)[]=array;
32. Fie urmtorul program: int x=2,y=3,z=4;
#include<stdio.h> Avnd n vedere codul de mai sus, cum vei
void main() realiza atribuirea celui de al doilea pointer din
{ irul ptr ca s pointeze la valoarea lui y ?
int u[4]={1,2,3,4}, a) ptr[2]=&y;
v[4]={5,6,7,8}, b) (*ptr)[1]=y;
w[4]={0,0,0,0}, i; c) (*ptr)[1]=&y;
int (*x)[4]=&u, (*y)[4]=&v, d) (*ptr)[2]=&y;
(*z)[4]=&w;
for(i=0;i<4;i++) 36. Fie urmtoarea declaraie de variabile :
printf(%3d,(*z)[i]= int *p; int x,y;
(*x)[i]+(*y)[i]); Atribuirea y=x+100; este echivalent cu
} secvena:
Care dintre afirmaiile de mai jos sunt a) p=&x; y=*p+100;
adevrate? b) y=*p+100; p=&x;
a) programul va afia patru adrese c) p=&y; y=*p+100;
de memorie d) p=&x; y=&p+100;
b) programul va afia, n ordine,
valorile 6,8,10,12
37. Fie urmtoarea declaraie de variabile :
c) valoarea lui (*x)[2] este 3 int *p; int x,y;
d) valoarea lui (*y)[4] este 8 Atribuirea x=y; este echivalent cu secvena :
e) instruciunea de afiare din a) p=&x; *p=y; b) p=&y; *p=x;
ciclu este eronat, din cauza c) *p=x; p=&y; d) *p=y; p=&x;
folosirii operatorului de
atribuire n funcia printf 38. Fie urmtoarea declaraie de variabile :
int *p; int x,y;
Instruciunea x++; este echivalent cu int *p; int x;
secvena : Atribuirea x=*(&t[0]+3); este echivalent
a) p=&x; (*p)++; b) p=*x; (&p)++; cu :
c) p=&x; *(p++); d) p=&x; *p++; a) x=t[3]; b) x=t[4];
c) x=*(&t[2]); d) x=*(t+4);
39. Fie urmtoarea declaraie de variabile :
int *p; int x,y; p=&x; 44. Se consider secvena de program :
Atribuirea y=x*(x+1); este echivalent cu void main(void)
secvena : { int *p, *q;
a) y=*p*((*p)++); b) y=*p*(*p++); p=(int*)malloc(sizeof(int));
c) y=*p**p++; d) y=(*p)*(*p++); q=(int*)malloc(sizeof(int));
*p=5; *q=3; *p=*q;
if(p==q) *p+=1;
40. Fie urmtoarea declaraie de variabile :
int *p; int x=100,y; p=&x; printf(%d,*p);
}
n urma atribuirii y=*p*((*p)++); y va avea
Care este valoarea afiat pentru p :
valoarea : a) 5 b) 3 c)6 d)4
a) 10100 b) 11000 c) 10001
d) 10000
45. Se d urmtoarea secvent de cod :
int a[5]={1,2,3,4,5};
41. Fie urmtoarea declaraie de variabile : int *aPtr;
int *p; int x=100, y; p=&x;
aPtr=a;
n urma atribuirii y=*p+((*p)++); y va avea printf(element=%d\n,*(aPtr+2));
valoarea : Ce va afia codul de mai sus dup execuie ?
a) 201 b) 102 c) 200 d) 202 a) element=1 b) element=2
c) element=3 d) element=4
42. Fie secvena :
int t[5]={20,30,40,50,10};
46. Se d codul:
int *p; int x; int *ptr; int y[10];
Atribuirea x=t[3]; este echivalent cu : int i;
a) p=t; x=*(p+3); for(i=0;i<10;i++) y[i]=i;
b) p=&t[0]; x=*(p+2); ptr=y; ptr+=8;
c) p=*t; x=*p+3; printf(ptr=%d\n, *ptr);
d) p=t; x=*p+3; Ce se va afia cnd codul este executat ?
a) ptr=0 b) ptr=9
43. Fie secvena : c) ptr=7 d) ptr=8
int t[5]={20,30,40,50,10};
Cap.8 iruri de caractere

8.1 Folosirea irurilor

Cea mai comun utilizare a tabloului unidimensional n limbajul C este irul (de caractere).
Spre deosebire de multe alte limbaje de programare, C nu conine tipul de dat string. n schimb, C
permite utilizarea irurilor folosind tablouri unidimensionale de tip char. irul este definit ca fiind un
tablou de caractere terminat prin caracterul null (\0, codul ASCII 0). Faptul c irul trebuie terminat prin
caracterul null nseamn c tabloul trebuie astfel definit nct s poat conine un ir cu un octet mai
lung dect cel mai lung ir ce va fi reprezentat vreodat n acest tablou, pentru a face loc caracterului
null. Un ir constant este automat terminat prin caracterul null de ctre compilator.
Pentru a citi un ir de la tastatur, trebuie apelat funcia gets(), care reclam includerea
header-ului stdio.h. Funcia gets() trebuie apelat folosind numele tabloului de caractere fr nici un
index. Funcia gets() citete caractere pn cnd este apsat tasta ENTER. Tasta ENTER este
nlocuit de compilator cu caracterul null care termin irul. De exemplu, programul urmtor citete i
afieaz un ir introdus de la tastatur :
#include<stdio.h>
void main()
{ char str[80];
int j;
printf(Introduceti un sir(<de 80 de caractere):\n);
gets(str);
for(j=0;str[j];j++)
printf(%c,str[j]);
}
S remarcm c programul, pentru a controla ciclul care afieaz irul, utilizeaz faptul c null este
false(0). Funcia gets() nu efectueaz verificri asupra limitelor n care variaz indexul tabloului, aa c
este posibil ca utilizatorul s introduc mai multe caractere dect poate conine irul. Deci trebuie s fii
siguri c ai apelat funcia gets() cu un tablou suficient de mare, care s poat conine i caracterele
neateptate. Exist un mod mult mai simplu de a afia irurile, folosind funcia printf() sau puts() .
Programul anterior, rescris cu ajutorul acestei funcii este :
#include<stdio.h>
void main()
{ char str[80];
int j;
printf(Introduceti un sir (< de 80 de caractere):\n);
gets(str);
printf(%s,str); /* puts(sir); */
}

Dac dup afiarea irului se dorete trecerea la o linie nou, se poate afia str dup cum urmeaz :
printf(%s\n,str);
Aceast metod folosete specificatorul de format %s urmat de caracterul linie nou i utilizeaz
tabloul de caractere ca al doilea argument al funciei printf().

8.2 Tablouri de iruri

Tablourile de iruri, numite deseori i tabele de iruri, sunt foarte des folosite n C. O tabel
bidimensional de iruri se poate crea ca oricare alt tablou bidimensional. Totui modul n care trebuie
gndit un tablou de iruri este puin diferit. Fie urmtoarea declaraie : char names[10][40];
Aceast declaraie specific o tabel care conine 10 iruri, fiecare avnd lungimea de pn la 40 de
caractere. Pentru a accesa un ir din tabel, trebuie specificat numai primul index. De exemplu, pentru
a citi de la tastatur al treilea ir al tabelei, trebuie folosit instruciunea : gets(names[2]);. Pentru a
afia primul ir al tabelei trebuie folosit instruciunea : printf(name[0]); .
8.3 Funcii standard pentru prelucrarea irurilor de caractere

n legtur cu irurile de caractere se au n vedere operaii de felul urmtor:


calculul lungimii irurilor de caractere
copierea irurilor de caractere
concatenarea irurilor de caractere
compararea irurilor de caractere
cutarea n iruri de caractere
Funciile standard prin care se realizeaz aceste operaii au fiecare un nume care ncepe cu
prefixul str i au prototipul n fiierul header string.h.

8.3.1 Lungimea unui ir de caractere

Lungimea unui ir de caractere se definete prin numrul de caractere proprii care intr n
compunerea irului respectiv. Caracterul NUL este un caracter impropriu i el nu este considerat la
determinarea lungimii unui ir de caractere. Prezena lui este ns necesar, deoarece la determinarea
lungimii unui ir se numr caracterele acestuia pn la ntlnirea caracterului NUL. Funcia pentru
determinarea lungimii unui ir de caractere are prototipul : unsigned strlen(const char *s);
Exemplul 1:
char *const p=Acesta este un sir;
unsigned n;
..
n=strlen(p);
Lui n i se atribuie valoarea 18, numrul caracterelor proprii ale irului spre care pointeaz p.
Exemplul 2:
char tab[]=Acesta este un sir;
int n;
n=strlen(tab);
Variabila n primeste aceeai valoare ca n exemplul precedent.
Exemplul 3:
int n;
n=strlen(Acesta este un sir);
Observaie : Parametrul funciei strlen este un pointer spre un ir constant deoarece funcia strlen nu
are voie s modifice caracterele irului pentru care determin lungimea.

8.3.2 Copierea unui ir de caractere

Adesea este nevoie s se copie un ir de caractere din zona de memorie n care se afl, n alt
zon. n acest scop se poate folosi funcia : char *strcpy(char *dest, const char *sursa);
Funcia copiaz irul de caractere spre care pointeaz sursa n zona de memorie a crei
adres de nceput este valoarea lui dest. Funcia copiaz att caracterele proprii irului, ct i
caracterul NUL de la sfritul irului respectiv. Se presupune c zona de memorie n care se face
copierea este destul de mare pentru a putea pstra caracterele copiate. n caz contrar se altereaz
datele pstrate imediat dup zona rezervat la adresa definit de parametrul dest. La revenire, funcia
returneaz adresa de nceput a zonei n care s-a transferat irul, adic chiar valoarea lui dest. Aceast
valoare este pointer spre caractere, deci tipul returnat de funcie este : char*. Se observ c
parametrul sursa, care definete zona n care se afl irul ce se copiaz, este declarat prin
modificatorul const. Aceasta deoarece funcia strcpy nu are voie s modifice irul care se copiaz. n
schimb, parametrul dest nu este declarat cu parametrul const deoarece funcia strcpy modific zona
spre care pointeaz dest (n ea se copiaz caracterele irului).
Exemplul 1:
char tab[]=Acest sir se copiaza;
char t[sizeof(tab)]; /* are acelai numr de elemente ca i tab */
..
strcpy(t,tab); /* irul din tab se copiaz n zona alocat lui t */
Exemplul 2:
char t[100];
strcpy(t,Acest sir se copiaza);
Exemplul 3:
char *p=Acest sir se copiaza;
char t[100];
char *q;
q=strcpy(t,p);
irul pstrat n zona spre care pointeaz p se transfer n zona spre care pointeaz t. Valoarea lui t se
atribuie lui q.
Pentru a copia cel mult n caractere ale unui ir dintr-o zon de memorie n alta, se va folosi
funcia de prototip : char *strncpy(char *dest , const char *sursa, unsigned n);
Dac n>lungimea irului spre care pointeaz sursa, atunci toate caracterele irului respectiv se
transfer n zona spre care pointeaz dest. Altfel se copiaz numai primele n caractere ale irului. n
rest, funcia strncpy are acelai efect ca i strcpy.
Exemplu:
char *p=Acest sir se copiaza trunchiat;
char t[10];
strncpy(t,p,sizeof(t)); /* se vor copia numai primele 10 caractere*/

Funcia strdup copiaz un ir ntr-o locaie nou creat i are prototipul : char *strdup(consr char *s);
Funcia strdup face copierea unui ir n spaiul obinut prin apelul funciilor calloc sau malloc. Nu este
deci necesar o apelare explicit a funciei de alocare. Dimensiunea spaiului alocat este egal cu
lungimea irului+1 (caracterul \0). Utilizatorul este responsabil pentru eliberarea spaiului atunci cnd
nu mai este nevoie de ir. Valoarea ntoars este pointerul la ir n caz de succes sau pointerul NULL
cnd spaiul nu s-a putut aloca.
Exemplu :
#include<stdio.h>
#include<string.h>
#include<malloc.h>
void main()
{ char *dup_str , *string=Acest sir se copie;
dup_str=strdup(string);
printf(%s\n,dup_str);
free(dup_str);
}
Observm c nu a fost necesar apelul unei funcii de alocare prealabil a memoriei. Apelul funciei de
eliberare, dup ce irul nu a mai fost utilizat, este necesar.

8.3.3 Concatenarea irurilor de caractere

Bibliotecile limbajelor C i C++ conin mai multe funcii care permit concatenarea unui ir de
caractere la sfritul unui alt ir de caractere. Una dintre ele are prototipul :
char *strcat(char *dest, const char *sursa);
Aceast funcie copiaz irul de caractere din zona spre care pointeaz sursa, n zona de memorie
spre care pointeaz dest, imediat dup ultimul caracter propriu al acestui ir. Se presupune c zona
spre care pointeaz dest este suficient pentru a pstra caracterele proprii celor dou iruri care se
concateneaz, plus caracterul NUL care termin irul rezultat n urma concatenrii. Funcia returneaz
valoarea lui dest.
Exemplu:
char tab1[100]=Limbajul C++;
char tab2[]=este C incrementat;
strcat(tab1, ); /* se adaug spaiu dup ultimul caracter + */
strcat(tab1,tab2);
Observaie : Funcia strcat, la fel ca funcia strcpy, nu trebuie s modifice irul de caractere spre care
pointeaz sursa.
O alt funcie de bibliotec utilizat la concatenarea de iruri este funcia strncat care are
prototipul : char *strncat(char *dest, const char *sursa, unsigned n);
n acest caz se concateneaz, la sfritul irului spre care pointeaz dest, cel mult n caractere ale
irului spre care pointeaz dest. Dac n >lungimea irului spre care pointeaz sursa, atunci se
concateneaz ntregul ir, altfel numai primele n caractere.
Exemplu:
char tab1[100]=Limbajul E este mai bun decat ;
char tab2[]=limbajul C++ care este un superset a lui C;
strncat(tab1,tab2,12);
Dup revenirea din funcie, tabloul tab1 conine succesiunea de caractere Limbajul E este mai bun
dect limbajul C++ .

8.3.4 Compararea irurilor de caractere

irurile de caractere se pot compara folosind codurile ASCII ale caracterelor din compunerea
lor. Fie s1 i s2 dou tablouri unidimensionale de tip caracter folosite pentru a pstra, fiecare, cte un
ir de caractere.
irurile pstrate n aceste tablouri sunt egale dac au lungimi egale i s1[j]=s2[j] pentru toate
valorile lui j.
irul s1 este mai mic dect s2, dac exist un indice j astfel nct s1[j]<s2[j] i s1[k]=s2[k]
pentru k=0,1,,j-1.
irul s1 este mai mare dect s2, dac exist un indice j astfel nct s1[j]>s2[j] i s1[k]=s2[k]
pentru k=0,1,,j-1.
Compararea irurilor de caractere se poate realiza folosind funcii standard de felul celor de
mai jos. O funcie utilizat frecvent n compararea irurilor este cea de prototip :
int strcmp(const char *s1, const char *s2);
Notm cu sir1 irul de caractere spre care pointeaz s1 i cu ir2 irul de caractere spre care
pointeaz s2. Funcia strcmp returneaz :
valoare negativ dac sir1<sir2
zero dac sir1=sir2
valoare pozitiv dac sir1>sir2
O alt funcie pentru compararea irurilor este funcia de prototip :
int strncmp(const char *s1, const char *s2, unsigned n);
Aceast funcie compar cele dou iruri spre care pointeaz s1 i s2 utiliznd cel mult primele n
caractere din fiecare ir. n cazul n care minimul dintre lungimile celor dou iruri este mai mic dect n,
funcia strncmp realizeaz aceeai comparaie ca i strcmp.
Adesea, la compararea irurilor de caractere dorim s nu se fac distincie ntre literele mici i
mari. Acest lucru este posibil dac folosim funcia de prototip :
int stricmp(const char *s1, const char *s2);
Aceast funcie returneaz aceleai valori ca i funcia strcmp, cu deosebirea c la compararea
literelor nu se face disticie ntre literele mari i mici.
Exemple:
char *sir1=ABC;
char *sir2=abc;
int j;
Apelul : j=strcmp(sir1, sir2); returneaz o valoare negativ, deoarece literele mari au codurile ASCII
mai mici dect literele mici.
Aplelul : j=stricmp(sir1, sir2); returneaz valoarea 0, deoarece ignorndu-se diferena dintre literele
mari i mici, cele dou iruri devin egale.
Pentru a limita compararea a dou iruri de caractere la primele cel mult n caractere ale lor, la
comparare ignorndu-se diferena dintre literele mici i mari, se va folosi funcia de prototip :
int strincmp(const char *s1, const char *s2, unsigned n);

8.3.5 Cutarea n iruri de caractere

Pentru cutarea unui caracter ntr-un ir de caractere sunt folosite funciile de prototip :
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
Cnd caracterul cutat nu se afl n ir este ntors pointerul NULL, altfel se ntoarce un pointer la prima
(strchr), respectiv ultima (strrchr) apariie a caracterului n irul s.
Pentru a cuta prima apariie a unui subir ntr-un ir se poate folosi funcia de prototip :
char *strstr(const char *s1, const char *s2);
Funcia caut prima apariie a subirului s2 n irul s1 i ntoarce un pointer la irul gsit sau pointerul
NULL cnd nu s-a gsit nici o apariie.
Pentru a cuta o secven de caractere ntr-un ir putem folosi funcia de prototip:
char *strpbrk(const char *s1, const char *s2);
Funcia caut n irul s1 prima apariie a unui caracter din irul s2. Valoarea ntoars este un pointer la
prima apariie sau pointerul NULL n cazul n care nici un caracter din s2 nu apare n s1.
Pentru a verifica apariia caracterelor unui ir n alt ir putem folosi funciile :
int strcspn(const char *s1, const char *s2);
int strspn(const char *s1, const char *s2);
Funcia strcspn determin lungimea secvenei de caractere de la nceputul irului s1 care nu conine
nici un caracter din s2. Funcia strspn determin lungimea secvenei de caractere de la nceputul
irului s1 care conine numai caractere din s2.
Funcia strtok caut prima parte din irul s1 care este diferit de orice subir din s2. Este pus
un caracter NULL la primul caracter din s1 comun irurilor i se ntoarce un pointer la subirul gsit. Se
poziioneaz implicit adresa de cutare la adresa urmtoare caracterului gsit n s1. Urmtoarele
apeluri cu primul parametru NULL vor continua cutarea de la adresa de cutare setat. Prototipul
funciei este :
char *strtok(char *s1, const char *s2);

8.4 Exemple de utilizare a funciilor standard

1. Fiind dat un cuvnt s se afieze toate sufixele acestuia. Literele fiecrui sufix vor fi separate prin
dou spaii.
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{ int n,i,j;
char si[100];
clrscr();
printf("Introduceti cuvantul : "); gets(si);
n=strlen(si);
for(i=0;i<n;i++)
{ for(j=i;j<n;j++)
printf("%c ",*(si+j));
puts("\n");
}
getch();
}
2. S se determine prima i ultima apariie a unui caracter ntr-un ir de caractere.
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{ char s[100],*ptr,c='e';
clrscr();
strcpy(s,"Test sir de caractere.");
ptr=strchr(s,c);
if(ptr)
{ printf("Prima aparitie a car. %c este in pozitia
%d\n",c, ptr-s);
printf("Ultima aparitie a car.%c este pe pozitia
%d\n",c, strrchr(s,c)-s);
}
else printf("Caracterul %c nu se afla in sir\n",c);
getch();
}
3. Programul urmtor ilustreaz modul de folosire a funciei strstr :
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{ char *str1="c:\\tc\\include ",*str2="\\include";
char *ptr;
clrscr();
ptr=strstr(str1,str2);
*ptr='\0';
printf("Directorul de baza este : %s\n",str1);
getch();
}
4. Exemplu de folosire a funciei strpbrk .
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{ char *string1="abcdefghijklmnopqrstuvwxyz";
char *string2="12fmcd";
char *ptr;
clrscr();
ptr=strpbrk(string1,string2);
if(ptr)
printf("strpbrk a gasit primul caracter : %c\n",
*ptr);
else
printf("strpbrk nu a gasit nici un caracter in
sir\n");
getch();
}
5. Programul urmtor citete o secven de caractere i determin prima fraz prin cutarea n irul
text a caracterelor din irul eop .
#include<stdio.h>
#include<string.h>
#include<conio.h>
void main()
{ char text[128];
char *eop=".!?";
int length;
clrscr();
printf("Introduceti un text : "); gets(text);
length=strcspn(text,eop);
text[length]='\0';
printf("Prima fraza este : %s\n",text);
getch();
}
6. Programul urmtor gsete toate cuvintele dintr-o linie. Presupunem c un cuvnt este delimitat de
unul din caracterele : !,.:;?-! .
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{ char in[100] , *p;
clrscr();
puts("Introduceti linia : "); gets(in);
/* strtok plaseaz terminatorul NULL la nceputul secvenei de cutare,
la poziia gsit */
p=strtok(in, ",.!:;-? ");
if(p)
printf("%s\n", p);
/* urmtoarele apeluri utilizeaz pointerul NULL ca prim parametru */
while(p)
{ p=strtok(NULL,",.!:;-? ");
if(p) printf("%s\n", p);
}
getch();
}

8.5 Funcii pentru conversii de date

Pentru conversia datelor din format numeric n format ir de caractere i invers se folosesc
dou seturi de funcii i macrouri. Primul set pentru conversii conine funcii i macrouri care convertesc
din format ir de caractere n format numeric (atoi, atof, atol) i funciile inverse acestora de conversie
i macrouri din format numeric n ir de caractere (itoa, ltoa, ultoa).Primele trei macrouri au sintaxa:
int atoi(const char *s);
long atol(const char *s);
double atof(const char *s);
Primul macrou convertete un ir ntr-un numr ntreg. El ntoarce valoarea obinut n urma
conversiei sau valoarea 0 dac irul nu poate fi convertit.Analog, macroul atol convertete un ir ntr-un
numr ntreg de tip long, iar atof ntr-un numr real de tip float. n cazul apariiei caracterelor
nepermise, conversia se va opri la primul caracter incorect i se va returna valoarea citit pn atunci.
Exemplu: Ca exemplu de utilizare a funciei atoi, se consider un ir care conine caractere neadmise
i valori depind dimensiunea tipului ntreg.
#include<stdlib.h>
#include<stdio.h>
void main()
{
int j,n;
char *s[]={12345,12345.67,123456.78,
123a45.67,a12345.67, 12345.a67};
for(j=0; j<6; j++)
{ n=atoi(s[j]);
printf(sir=%s\n val=%d,s[j],n);
}
}
Valorile numerice tiprite sunt, n ordine:
12345 - a fost transformat ntregul ir
12345 - partea zecimal nu a fost luat n consideraie
-7616 - numrul obinut a fost ntreg, dar nu s-a ncadrat n limitele impuse de tipul int
123 - s-a citit pn la primul caracter care nu era semn sau cifr
0 - primul caracter nu a fost cifr i conversia s-a oprit aici
12345 - caracterul a nu a avut nici o influen fiind dup punctul zecimal
Funciile de conversie invers, din numr n ir de caractere , au sintaxele:
char *itoa(int valoare, char *sir, int baza);
char *ltoa)long valoare, char *sir, int baza);
char *ultoa(unsigned long valoare, char *sir, int baza);
Funciile ntorc valoarea obinut ntr-un ir terminat cu \0 i stocheaz rezultatul n ir.
Parametrul valoare reprezint numrul ntreg care urmeaz a fi convertit. El poate avea att valori
pozitive ct i negative n cazul funciilor itoa sau ltoa i numai valori pozitive pentru funcia ultoa.
Parametrul sir reprezint adresa irului de caractere n care se va obine rezultatul conversiei.
Parametrul baza reprezint baza aleas pentru conversie. Funcia itoa poate ntoarce un ir de pn la
17 caractere, iar ltoa un ir de pn la 33 de caractere (dac baza are valoarea 2). n caz de succes,
funciile ntorc un pointer la irul obinut, n caz de eroare, este ntors irul vid.
Al doilea set de conversie ntre numere i iruri de caractere este mai performant n privina
detectrii erorilor dect primul. Funciile de conversie a unui numr real ntr-un ir de caractere au
sintaxa:
char *fcvt(double val, int nr_cif, int *dec, int *semn);
char *ecvt(double val, int nr_cif, int *dec, int *semn);
char *gcvt(double val, int ndec, char *buf);
Parametrul val i nr_cif reprezint valoarea iniial i numrul de cifre care se doresc a fi
obinute. Funciile vor ntoarce valoarea numrului n baza 10 stocat ca ir de caractere. Nu apare
punctul zecimal. Pentru a obine informaii suplimentare despre conversie, variabilele semn, care
reprezint semnul numrului, i dec, care reprezint numrul de cifre zecimale, vor fi transmise printr-o
referin la ntreg. Pentru ecvt, variabila nr_cif reprezint numrul total de cifre, n timp ce pentru fcvt
variabila nr_cif reprezint numrul de cifre ale prii zecimale. Funcia gcvt face suprimarea zerourilor
inutile. Valoarea ntoars de ctre cele trei funcii este un pointer spre irul de caractere.
Conversiile de la iruri de caractere la numere se fac cu funciile:
double strtod(const char *s, char **endptr);
long strtol(const char *s, char **endptr, int baza);
long strtoul(const char *s, char **endptr, int baza);
Funcia strtod convertete un ir ntr-un numr real dubl precizie. irul iniial s trebuie s aib
urmtoarea form: [ws] [s] [ddd] [.] [ddd] [fmt[s]ddd] n care ws reprezint spaii, s este semnul,
ddd sunt cifre zecimale, iar fmt este e sau E pentru forma exponenial. Al doilea parametru endptr
este un pointer la un ir de caractere i are rolul de a se poziiona la ultima poziie de citire corect din
ir, pentru detectarea erorilor la conversie.
Exemplu:
#include<stdio.h>
#include<stdlib.h>
void main()
{
char sir[80],*s; double valoare;
printf(numarul=); gets(sir);
valoare=strtod(sir, &s);
printf(sirul:%s numarul:%lf\n,sir,valoare);
}
Funciile strtol i strtoul convertesc un ir s care exprim un numr ntr-o baz precizat de al treilea
argument, baza, ntr-un numr ntreg de tip long, respectiv de tip unsigned long. Este folosit
deasemenea un pointer dublu la caractere pentru detectarea erorilor.

8.6 Exerciii i teste gril

1. n programul urmtor, care dintre secvenele void main()


de instruciuni (I), (II) realizeaz corect citirea {
unui ir de caractere de la tastatur i afiarea char b[11],
acestuia ? a[11]=abcdefghij;
#include<stdio.h> int i=0;
void main() while(a[i]%2) b[i++]=a[i];
{ b[i]=0;
char s1[10],s2[10]; }
scanf(%s,s1); a) programul are erori
printf(s1=%s,s1); //(I) b) irul b conine numai caracterul
scanf(%s,&s2); a
printf(%s,s2[10]); //(II) c) n urma execuiei irurile a i
} b concid
a) numai (I) b) numai (II) d) irul b conine numai
c) (I) i (II) d) nici una caracterele din irul a ale cror
coduri ASCII sunt numere pare
2. Analizai programul urmtor i alegei e) irul b conine numai
rspunsul corect: caracterele de rang par din a (al
#include<stdio.h> doilea, al patrulea etc.)
b) char a[2][2]={ab,cd};
3. Fie programul urmtor: c) char a[3][2]={ab,cd};
#include<stdio.h> d) char a[3][3]={ab,cd};
#include<string.h> e) char a[][3]={ab,cd};
void main()
{ 6. Care dintre variantele de mai jos reprezint o
char s1[10], s2[10], declaraie corect a unui ir de caractere?
s3[10]=SB; a) char s[2]; b) char *s[20];
gets(s1); gets(s2); c) char *s; d) char s;
puts(s1+s2); // (1) e) char s[];
if(strlen(s1)<strlen(s2))
putchar(1); // (2) 7. Pentru programul urmtor, analizai
if(s1>s3) putchar(1); corectitudinea afirmaiilor de mai jos:
else putchar(0); // (3) #include<stdlib.h>
} #include<stdio.h>
Presupunem c, n timpul execuiei progra- void main()
mului, se introduc de la tastatur irurile {
s1=BR i s2=122035. Precizai dac sunt char s1[4],s2[4]; long x;
adevrate situaiile de mai jos: gets(s1); gets(s2);
a) citirea de la tastatur este if(strcmp(s1,s2)<0)
eronat x=atol(s1);
b) instruciunea (1) va afia else if(!strcmp(s1,s2)) x=0;
textul BR122035 else x=atol(s2);
c) instruciunea (2) va afia printf(%ld, x);
valoarea 1 }
d) n linia (3) se compar irurile a) condiiile din cele dou linii
s1 i s3 din punct de vedere if sunt greite
alfabetic b) apelurile funciei atol sunt
e) nici una dintre afirmaiile corecte
anterioare c) dac de la tastatur se introduc
irurile 98 i 123, atunci
4. Pentru programul urmtor precizai care se va afia 98
dintre afirmaiile de mai jos sunt adevrate: d) dac de la tastatur se introduc
#include<stdio.h> irurile 123 i 135, atunci
#include<string.h> programul va afia irul 123
void main() e) dac de la tastatur se introduc
{ irurile ab i ac, atunci se
char s[10]=-2B.2A5; va semnala un mesaj de eroare
int j,nr=0;
for(j=0;j<strlen(s);j++) 8. tiind c, n conformitate cu standardul
if(!(s[j]>=0&& ASCII, codurile literelor mari sunt succesive
s[j]<=9)) ncepnd cu 65, ce va afia programul de mai
{ s[j]=0; nr++; } jos?
printf(%d%s,nr,s); #include<stdlib.h>
} #include<string.h>
a) declararea irului este corect #include<stdio.h>
b) n ciclul for sunt parcurse void main()
corect caracterele irului s {
c) n ciclul for sunt nlocuite cu int x=20,e;
0 cifrele din s char s[15]=ABC,t[15],u[15];
d) condiia din linia if este e=s[1]+s[2];
eronat itoa(e,t,10);
e) programul afieaz 40200205 strcpy(u,t);
strcat(s,u);
5. Ne propunem s definim un vector care s puts(s);
aib dou elemente, ambele de tip ir de }
caractere. Fiecare ir trebuie s conin dou a) nimic, irul s fiind vid
caractere, primul ab, iar al doilea cd. Scriei b) ABC13 c) AB13 d) ABC133
declaraia corect. e) ABC131
a) char a[2][3]={ab,cd};
9. Ce ir de caractere va afia secvena b) citirea irurilor din linia (2)
urmtoare? c) atribuirile din liniile (3) i
char *s=abcdefg,*ptr; (4)
ptr=s; ptr+=4; d) afiarea din linia (5)
puts(ptr); e) atribuirea din linia (6)
a) fg b) efg c) defg
d) cdefg e) secvena este 13. Precizai ce ir de caractere se va afia n
eronat urma execuiei programului urmtor:
#include<stdio.h>
10. Ce va afia programul urmtor? #include<string.h>
#include<stdio.h> void main()
void main() {
{ char s[20]=BorLanD C++ 3.1;
char *a[3]={abc,def, int j;
ghi}; for(j=0;j<strlen(s);j++)
char *p=&a[0][0]; if((s[j]>=A)&&
printf(%s%c%c,a[1],a[2][1], (s[j]<=Z))
*(p+5)); s[j]-=(A-a);
} puts(s);
a) abc d NULL b) abc d e }
c) def h NULL d) def h e a) BorLand C++ 3.1
e) programul va semnala eroare de b) bORlAND c++ 3.1
compilare d) BORLAND C++ 3.1
d) borland c++ 3.1
11. Ce va afia cea de-a doua instruciune de e) Borland C++ 3.1
tiprire din programul de mai jos:
#include<stdio.h> 14. Care dintre cele trei instruciuni printf de
void main() mai jos tipresc irul bd?
{ #include<stdio.h>
char a[12]=abcdefghij; void main()
char *p=a; int j; {
for(j=0;j<12;j++) char s[6][3]={ab,ac,
*(p+j)=a[j]^j; ad,bc,bd,cd};
printf(%s\n,p); printf(%c%c,s[3][0],
for(j=0;j<12;j++) s[2][1]);
*(a+j)=p[j]^j; printf(%s,s[3][0]+
printf(%s, p); s[2][1]);
} printf(%s,s[5]);
a) nimic b) textul abcdefghij }
c) textul jihgfedcba a) toate b) numai prima
d) o succesiune de caractere c) numai primele dou
imprevizibil d) numai prima i a treia
e) programul conine erori e) nici una

12. Care dintre instruciunile programului de 15. Ce va afia programul de mai jos?
mai jos sunt eronate? #include<stdio.h>
#include<stdio.h> void main()
#include<string.h> {
void main() char s[10]=AB6X92P3M,
{ b[10];
char a[10],b[10];int k; //(1) int j=0,k=0;
scanf(%s %s,a,b); //(2) while(s[j])
k=strlen(a)/2; //(3) if(j%2) b[k]=s[j++];
a[k]=*; //(4) b[k]=0; puts(b);
printf(%d,strlen(a)< }
strlen(b));//(5) a) BX23 b) A69PM c) B
b=a; //(6) d) 3 e) nimic
}
a) declaraia de variabile din 16. Considernd declaraiile:
linia (1) char s[4]=123,t[4]; int x=123,y;
Care din expresiile de mai jos au valoarea 0? printf(%s,s1+s2); //(4)
a) atoi(s)!=x; x=strlen(*s2); //(5)
b) itoa(x,t,10)==s; }
c) (y= =atoi(s))==x; a) 2,3 ,4 b) 2,3,4,5 c) 4,5
d) x= =(atoi(itoa(x,t,10))); d) 3,5 e) 3,4,5
e) !strcmp(itoa(x,t,10),s);
21. Fie programul:
17. Ce va afia programul urmtor? #include<stdio.h>
#include<stdlib.h> void main()
#include<stdio.h> {
#include<string.h> char *s,*t,*u;
void main() int j,x;
{ gets(s);
char s[12]=6789,t[12]=6, for(x=0,j=0;s[j];t=&s[j],
u[12]=89; u=t+1,u[0]==t[0]? x=1:0,j++);
long x=0; printf(%d, x);
strcat(t,u); }
if(strcmp(s,t)) x=atol(t); n urma execuiei programului, se va afia
else x=atol(s); valoarea 0, dac:
if(strcmp(s,u)>0) x=atol(u); a) toate caracterele irului s sunt
printf(%ld, x); identice
} b) n irul s exist cel puin dou
a) 0 b) 6 c) 89 caractere succesive diferite
d) 689 e) 6789 c) n irul s exist cel mult dou
caractere succesive identice
18. Ce afieaz programul urmtor? d) n irul s exist cel puin dou
#include<stdio.h> caractere succesive identice
void main() e) n irul s nu exist dou
{ caractere succesive identice
char *s1=EXEMPLU SIMPLU,
*s2=SIMPLU; 22. Considerm urmtoarele noiuni:
printf(\n%.8s%.6s,s1,s2); A)vector de doi pointeri ctre
} caracter
a) EXEMPLU b) EXEMPLU SIMPLU B)pointer ctre ir de dou
c) EXEMPLU SIMPLU SIMPLU caractere
d) EXEMPLUSIMPLU e) SIMPLU i urmtoarele declaraii de variabile:
I) char *a[2];
19. Ce afieaz programul urmtor? II) char (*b)[2];
#include<stdio.h> Precizai corespondenele corecte:
void main() a) A) cu I) i B) cu II)
{ b) A) cu II) i B) cu I)
char *s=123456789,*t,*u; c) nu exist corespondene
u=&s[4],s+=3,t=&s[1]; d) B) nu are corespondent
printf(%d%d%d,u==s,u==t, e) cele dou declaraii semnific
s==t); acelai lucru
}
a) 000 b) 001 c) 010 23. Ce afieaz programul de mai jos?
d) 100 e) 111 #include<stdio.h>
void main()
20. Care dintre instruciunile (1),.....(5) de mai {
jos sunt eronate? char *s[5]={012,345,
#include<stdio.h> 678,9AB,CDE};
#include<string.h> char *t,*u; int j;
void main() t=&s[1][0];
{ printf(%d,(*(t+5)==s[2][1]));
char *s1,*s2,*s3; u=&s[3][0]+1;
int x; j=0;
s1=test; //(1) while(u[j]) printf(%c,u[j++]);
scanf(%s,s2); //(2) }
s3=&s1; //(3) a) 178 b) 1AB c) 078
d) 0AB e) 067 N2. pointer ctre matrice de caractere de 4 linii
i 6 coloane
24. Ce afieaz programul de mai jos? N3. pointer ctre vector cu 4 elemente, fiecare
#include<stdio.h> fiind vector de 6 caractere
#include<string.h> N4. matrice de 4 linii i 6 coloane, fiecare
void main() element este pointer ctre caracter
{ Precizai corespondena direct:
char *s[10]={10,00,10, a) (A,N1), (B,N2), (C,N3), (D,N4)
10,01,11}; b) (A,N4), (B,N1), (C,N2), (D,N3)
char *t=10; c) (A,N4), (B,N1), (C,N3), (D,N2)
int i=0,j=i-1; d) (A,N2), (B,N3), (C,N4), (D,N1)
while(s[i])
if(!strcmp(s[i++],t)) j=i; 26. Cte erori conine programul urmtor ?
printf(%d, j); void main()
} {
a) 1 b) 0 c) 1 char *(a[4][6]);
d) 3 e) 4 char b;
a[2][3]=*(b+2);
25. Se dau urmtoarele declaraii a[3][2]=&b+3;
A)char *a[4][6]; *(4+a[2])=&b+1;
B)char (*b[4])[6]; *a[1][3]=b+3;
C)char (*c)[4][6]; }
D)char ((*d)[4])[6]; a) nici una b) una c) dou
i urmtoarele noiuni: d) trei e) patru
N1. vector de 4 elemente, fiecare element este
un pointer ctre un vector de 6 caractere
Cap.9 Structuri

9.1 Definirea tipurilor structur

Limbajul C ofer programatorului posibilitatea de a grupa datele, date de tipuri diferite putnd fi
prelucrate att individual ct i mpreun. Dac tabloul conine numai elemente de acelai tip, o
structur este format din mai multe elemente de tipuri diferite. La rndul lor, structurile definite
pot constitui elemente componente pentru formarea de noi tipuri de date (tablouri, structuri, uniuni) .
Elementele componente ale unei structuri se numesc membri sau cmpuri .
Sintaxa declarrii unei structuri este urmtoarea :
struct [nume_tip_structura]
{ tip_1 lista_campuri_tip_1;
tip_2 lista_campuri_tip_2;
.
tip_n lista_campuri_tip_n;
} [lista_variabile_structura];
n declaraie poate lipsi precizarea numelui pentru tipul structurii sau a listei de variabile ns nu ambele
simultan. n cazul n care lipsete numele tipului, spunem c variabilele au un tip anonim. Cmpurile
componente ale unei structuri pot fi oricare din tipurile :
- predefinite (ntreg, caracter, numr real)
- definite de utilizator : scalari (cmpuri de bii , enumerare) sau compuse (tablouri, structuri, uniuni)
Exemplul 1: Definirea datelor de baz pentru o persoan specificnd numele i vrsta.
struct pers
{ char nume[35];
int an;
};
S-a definit o structur de tip pers fr a fi folosit nici o variabil de tipul definit.
Exemplul 2: Definirea unei structuri de tip angajat specificnd pe lng datele de baz (un cmp de
tip structur pers) adresa, salariul i vechimea n munc.
struct angajat
{ struct pers p; /* structura pers a fost definit anterior */
char adresa[50];
long salariu;
int vechime;
} persoana , firma[100];
struct angajat p[50];
Observm modul cum poate fi o structur folosit la rndul ei drept cmp al altei structuri. n acest
caz, s-a definit o structur de tip angajat i variabilele de tip angajat :
- variabila persoana
- variabila firma de tip tablou de nregistrri
n a doua declaraie, s-a folosit tabloul p de 50 de nregistrri de tipul angajat.
Putem defini orice tip structur folosind typedef. Astfel, exemplul anterior se mai poate scrie :
typedef struct
{ struct pers p;
char adresa[50];
long salariu;
int vechime;
} ANGAJAT;
ANGAJAT persoana , firma[100];
Am definit un tip de structur cu aceleai componente ca mai sus i variabilele persoana i firma cu
aceeai semnificaie ca mai nainte. Se observ c nu mai este necesar precedarea tipului de
structur de cuvntul cheie struct.
Exemplul 3: Se definete o structur care grupeaz informaii, specificnd datele necesare fiei
medicale a unui bolnav.
typedef struct { int an , luna , zi} DATA;
struct
{ struct pers p;
DATA data_internarii;
char adresa[50];
char boli[10][30];
} pacient[200];
n ultimul caz, nu s-a mai definit numele tipului structurii, ci doar tabloul de nregistrri pacient care
conine 200 de nregistrri de tipul fielor medicale.
Exemplul 4: n cazul n care un tablou este definit ca ultim cmp al unei structuri este acceptat
omisiunea primei dimensiuni din tablou. Astfel, este acceptat declaraia :
struct vector
{ int n;
int dim[];
};
Exemplul 5: n implementrile limbajului C exist diferite structuri predefinite. Spre exemplu, pentru
utilizarea numerelor complexe este definit n header-ele math.h i complex.h urmtoarea structur :
struct complex
{ double x;
double y;
};

9.2 Iniializarea structurilor

Datele componente ale unei structuri se pot iniializa. n acest scop, la sfritul declaraiei sau
definiiei structurii se pune caracterul egal i se scriu ntre acolade, n ordine, valorile componentelor,
delimitate prin virgul. Iniializarea unei structuri se face enumernd valorile, pentru fiecare din membrii
si.
Exemplul 1: O iniializare corect este urmtoarea :
struct pers{ char nume[3];int varsta;}s={Marcel Dima, 35};
Se observ c valorile cmpurilor trebuie date n ordinea de definiie a acestora n cadrul structurii.
Exemplul 2:
struct pers s={30,Andronic Virgil};
Structura este incorect iniializat deoarece valorile nu sunt date n ordinea declarrii cmpurilor din
structur.
Exemplul 3: Ultimile valori ale componentelor pot lipsi. De exemplu, este corect urmtoarea
iniializare, chiar dac nu au fost iniializate toate componentele :
struct s
{ int inf;
char n[20];
float x;
};
struct s s1={1};
Pentru variabila structurat s1 de tip s, se va iniializa doar primul cmp inf cu valoarea 1. Celelalte
dou cmpuri vor fi iniializate automat astfel :
- cmpul n cu valoarea irului vid
- cmpul numeric x cu valoarea 0
Exemplul 4: n exemplul urmtor se iniializeaz o variabil de tipul struct persoana, precum i a unui
tablou cu elemente de acest tip.
struct persoana
{ char nume[32];
int varsta;
float salariu;
};
struct persoana pers={Alex,28,1200000.0};
struct persoana grup[]=
{ {Gigi , 32, 3000000.0} ,
{Mimi , 19 , 1500000.0} ,
{Fred, 33 , 2950000.0}
};
9.3 Operaii permise asupra structurilor

Operaia principal care poate fi efectuat asupra unei variabile de tip structur este selectarea
unui cmp, utiliznd operatorul de selecie . conform sintaxei :
variabila_structura.camp_selectat
Cmpul selectat se comport ca o variabil i i se pot aplica toate operaiile care se pot aplica
variabilelor de acel tip. Deoarece structurile se prelucreaz frecvent prin intermediul pointerilor, a fost
introdus un operator special, care combin operaiile de indirectare i selectare a unui cmp, anume
. Expresia pcamp_selectat este interpretat de compilator la fel ca expresia
(*p).camp_selectat. ntotdeauna, unei variabile de tip structur i se pot aplica operatorii & (calculul
adresei) i sizeof (calculul mrimii zonei de memorie ocupate de variabil).
n plus sunt permise urmtoarele operaii :
a) unei variabile de tip structur i se poate atribui valoarea altei variabile de tip structur
b) variabilele de tip structur pot fi transmise ca parametri funciilor
c) o funcie poate avea ca rezultat o valoare de tip structur

Exemplul 1: Fie structura :


struct pers
{ int ani;
char nume[30];
} x,y,*ps;
Tiprirea valorilor elementelor componente se face astfel :
a) n cazul accesrii cmpurilor pentru structura x care este de tip pers, se va folosi selecia
direct. O tiprire corect se poate face astfel :
printf(\nNumele:%s\nVarsta:%d\n,x.nume,x.ani);
b) n cazul accesrii cmpurilor structurii indicate de pointerul la pers numit ps, se va folosi
selecia indirect. O secven corect de tiprire este :
printf(\nNumele:%s\nVarsta:%d\n,ps->nume,ps->ani);
Pentru atribuirea coninutului structurii x la structura y se poate folosi una din secvenele :
a) atribuirea cmp cu cmp : y.ani=x.ani ; strcpy(y,nume,x.nume);
b) atribuirea direct ntre dou structuri de acelai tip : y=x;
Exemplul 2: Pentru structura de tip pers i variabilele definite anterior sunt corecte atribuirile :
a) se atribuie unui pointer adresa structurii
b) se atribuie unei structuri coninutul indicat de un pointer la o structur de acelai tip
ps=&x; /* adresa indicat de ps este egal cu adresa lui x */
y=*ps; /* coninutul lui y devine egal cu coninutul structurii de la adresa pointat de ps */
Atribuirea coninutului unui pointer la o structur cu o structur de acelai tip se poate face astfel :
*ps=y;
Aceast atribuire este echivalent cu secvena :
(*ps).inf=y.inf ;
strcpy((*ps).nume,y.nume);
Urmtoarele dou atribuiri sunt echivalente cu cele dou de dinainte :
ps->inf=y.inf;
strcpy(ps->nume,y.nume);
Folosirea expresiei de tipul (*ps).inf este corect dar greoaie i neuzual. n locul ei este recomandat
forma ps->inf .
Exemplul 3: Tablourile nu pot fi atribuite direct. Totui, dac tabloul este membru al unei structuri,
atunci atribuirea poate avea loc .
#include<stdio.h>
#include<stdlib.h>
struct tablou {int x[10]};
void main()
{ struct tablou a={{1,1,1,1,1,1,1,1,1,1}} ,
b={{2,2,2,2,2,2,2,2,2,2}};
struct tablou *a1 , *b1;
/* copierea direct a structurilor; are loc copierea direct a tabloului folosindu-l drept
cmp al unei structuri */
b=a;
/* se aloc spaiul necesar structurii i adresa spaiului alocat se stocheaz n pointerul
la structur */
a1=(struct tablou*)malloc(sizeof(struct tablou));
*a1=a;
b1=(struct tablou*)malloc(sizeof(struct tablou));
/* se copiaz coninutul structurii de la adresa indicat de pointerul a1 peste coninutul
structurii indicate de pinterul b1 */
*b1=*a1;
/* sau : *(struct tablou)b1=*(struct tablou)a1 */
}
Observm c s-au putut face atribuirile directe cu tablouri care sunt cmpuri ale unei structuri, att ntre
structuri, ct i ntre pointeri la structuri. n acest exemplu, toate structurile i coninutul pointerilor la
structuri primesc valoarea structurii a.
Exemplul 4: Se consider o grup de n studeni (n<=40), pentru fiecare dintre ei cunoscndu-se
numele i media anual. Se cere s se afieze studenii n ordinea descresctoare a mediilor.
#include<stdio.h>
#include<conio.h>
void main()
{ struct
{ char nume[30];
float media;
} aux , grupa[40];
int n,i,j;
float media;
clrscr();
/* citirea datelor */
printf("Numarul studentilor : ");scanf("%d",&n);
puts("\n Introduceti datele studentilor :\n");
for(i=0;i<n;i++)
{ getchar();
printf("Numele :");gets(grupa[i].nume);
printf("Media : ");scanf("%f",&media);
grupa[i].media=media;
}
/* sortarea tabloului grupa descrescator dupa medie */
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(grupa[i].media<grupa[j].media)
{ aux=grupa[i];
grupa[i]=grupa[j];
grupa[j]=aux;
}
/* afisarea rezultatelor */
clrscr();
puts("Studentii ordonati desc. dupa medii :\n");
for(i=0;i<n;i++)
printf("%30s%5.2f\n",grupa[i].nume, grupa[i].media);
getch();
}

9.4 Exerciii i teste gril

1. Fie structura : a) d.zi respectiv dl.zi


struct data { b) d->zi respectiv dl->zi
int zi, luna , an; c) d->zi respectiv dl.zi
} d, *dl; d) d.zi respectiv dl->zi
Cum se acceseaz membrul zi ?
2. Fie structura : a) char c=myComputer.cpuType(0);
struct data { b) char c=myComputer.cpuType;
int zi, luna , an; c) char c=myComputer[0].cpuType;
}*d; d) char c=myComputer.cpuType[0];
Care este expresia logic a crei valoare arat
c anul este sau nu bisect ? 7. Fie secvena :
a) an%4==0 && an%100!=0 typedef struct
b) d.an%4==0 && d.an%100!=0 { long cust_id;
c) d.an%4==0 && d.an%100!=0 || char custName[50];
d.an%400==0 double balance;
d) d->an%4==0 && d->an%100!=0 || } CUSTOMER_REC;
d->an%400==0 CUSTOMER_REC customer[50];
int i;
3. Linia de cod care declar o variabil /*mai jos in program*/
structur numit total de tip sample este : for(i=0;i<50;i++)
a) type total: sample; {
b) struct total; printf(%s\n,?????);
c) struct sample total; }
d) declare total as type sample; Ce ar trebui pus in locul ???? pentru a afia
fiecare element custName n codul anterior :
4. Linia de cod care asigneaz valoarea 10 a) customer[i]->custName;
cmpului loop din structura total (de tip b) customer.custName[i];
sample), este : c) customer[i].custName;
a) loop=10; d) customer->custName[i];
b) total.loop=10;
c) sample.total.loop=10; 8. Fie declaraia:
d) sample.loop=10; struct computer{
int cpuSpeed;
5. Linia de cod care afieaz valoarea cmpului char cpuType[10];
word din structura total (de tip sample), este : } comp[]=
a) printf(%s,total); {
b) printf(%s,word); {400,Pentium} ,
c) printf(%s,total-word); {266,PowerPC} ,
d) printf(%s,total.word); {333,Sparc},
};
6. Se d urmatoarea secven de cod : Se d irul de structuri de mai sus. Care dintre
struct computer { urmtoarele expresii va evalua numrul
int cpuSpeed; structurilor din ir (n cazul de fa este 3)?
char cpuType[10]; a) sizeof(*comp)/sizeof(comp)
}; b) sizeof(*comp)
struct computer myComputer; c) sizeof(comp)
Referindu-ne la codul de mai sus, cum accesai d) sizeof(comp)/sizeof(*comp)
primul caracter din cpuType ?
Cap.10 Exploatarea fiierelor

10.1 Noiunea de fiier

Prin fiier se nelege o structur de date, cu componente numite nregistrri, ce pot avea o
dimensiune fix sau variabil, cel de-al doilea caz impunnd existena unor marcaje speciale numite
separatori de nregistrri. Fiierele pot fi clasificate dup mai multe criterii. Din punct de vedere al
accesului la componente se mpart n:
- fiere cu acces secvenial ale cror nregistrri pot fi prelucrate numai n ordinea n care sunt
stocate n fiier
- fiiere cu acces direct ale cror componente pot fi prelucrate n orice ordine. n cazul n care
prelucrarea nu se face secvenial, nainte de fiecare operaie de citire/scriere trebuie furnizat
informaia necesar selectrii componentei ce urmeaz a fi prelucrat
Din punct de vedere al coninutului, fiierele se mpart n dou categorii:
- fiiere text care conin numai caractere structurate pe linii
- fiiere binare n care informaia este vzut ca o colecie de octei
Biblioteca de funcii stdio.h ofer posibilitatea operrii cu fiiere printr-o structur numit FILE.
Orice operaie cu fiiere necesit o asemenea structur, care se iniializeaz la deschiderea unui fiier
i al crei coninut devine nefolositor dup nchiderea sa.Gestionarea fiierelor se face printr-un pointer
la structura predefinit FILE. Declararea unui astfel de pointer se face conform sintaxei:
FILE *identificator_fisier;

10.2 Deschiderea unui fiier

Se realizeaz cu ajutorul funciei fopen care are sintaxa de mai jos:


FILE *fopen(nume_fisier, mod_deschidere);
n care : nume_fier este numele complet (calea pe disc) a fiierului care se deschide, iar
mod_deschidere precizeaz modul n care se deschide fiierul i poate avea urmtoarele valori:
- r pentru citirea unui fiier existent; se produce o eroare dac fiierul nu exist
- w deschide un fiier pentru scriere; dac fiierul exist, i distruge coninutul
- a se adaug informaie n fiier, la sfritul acestuia
- r+ n acelai timp citeste, respectiv scrie n fiier; acesta trebuie s existe
- w+ deschide un fiier pentru citire i scriere; dac acesta exist, coninutul este distrus
- a+ adugare; dac fiierul exist, coninutul este distrus
- t fiierul este de tip text
- b fiierul este binar
Se pot face combinaii cu opiunile de mai sus. De exemplu, deschiderea unui fiier text pentru
citire se face cu opiunea rt. Crearea unui fiier binar pentru scriere este posibil prin wb. Nu
conteaz ordinea n care sunt date literele n irul mod_deschidere.
n caz de succes, funcia fopen returneaz un pointer la noul flux de comunicare deschis; altfel
ntoarce pointerul NULL. Operaia de deschidere a unui fiier trebuie nsoit de verificarea reuitei
respectivei operaii conform modelului de mai jos:
if(identificator_fisier)
instructiuni_operatie_reusita
else
instructiune_eroare_la_deschidere;
Exemple: Fie declaraia FILE *f ; vom ncerca urmtoarele deschideri de fiiere:
1) f=fopen(test1.in,rt); Am deschis fiierul test1.in din directorul curent
pentru citire n mod text. Litera t nu era necesar, modul text fiind modul de deschidere
implicit al fiierelor n C. Dac fiierul nu exist, atunci funcia ntoarce NULL. O deschidere
mai riguroas ar fi:
if((f=fopen (test1.in,rt))==NULL)
{ printf(Eroare la deschiderea fisierului !); exit(1); }
2) f=fopen(test2.out,wb); Este deschis/creat fiierul test2.out din directorul
curent n mod binar pentru scriere.
3) f=fopen(c:\\tc\\test3.bin,ab+); Este deschis fiierul test3.bin din
directorul c:\tc n mod binar pentru citire/scriere fiind poziionat la sfritul fiierului.

10.3 nchiderea unui fiier

Se poate face cu ajutorul funciilor:


- int fclose(FILE *f); care nchide fiierul specificat i returneaz 0 n caz de succes sau EOF n
cazul apariiei unei erori
- int fcloseall(void); care nchide toate fiierele deschise i returneaz numrul total de fiiere pe
care le-a nchis sau EOF la apariia unei erori

10.4 Funcia de verificare a sfritului unui fiier

Pentru a verifica dac poziia curent de citire/scriere a ajuns la sfritul unui fiier se folosete
funcia int feof(FILE *f); care ntoarce valoarea 0 dac poziia curent nu este la sfritul fiierului i o
valoarea diferit de 0 dac poziia actual indic sfritul de fiier.

10.5 Funcii de citire/scriere caractere

Pentru citirea unui caracter dintr-un fiier text se folosete funcia


int fgetc(FILE *f);
Dac citirea a avut loc cu succes, se ntoarce valoarea caracterului citit, iar n caz de eroare este
ntoars valoarea EOF.
Pentru scrierea unui caracter ntr-un fiier text se folosete funcia
int fputc(int c,FILE *f);
Funcia ntoarce caracterul care s-a scris n caz de succes, respectiv EOF n caz de eroare.
Exemplul 1: Copierea unui fiier caracter cu caracter.
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *in,*out;
// se incearca deschiderea fisierului sursa
if((in=fopen(test.c,r))==NULL)
{ printf(fisierul nu poate fi deschis pentru citire);
exit(1);
}
// se incearca deschiderea fisierului destinatie
if((out=fopen(test2.bak,w))==NULL)
{ printf(fisierul nu poate fi deschis pentru scriere);
exit(1);
}
// se copie un caracter din sursa si se scrie in destinatie
while(!feof(in)) fputc(fgetc(in),out);
fclose(in); fclose(out);
}
Exemplul 2: Se numr cte caractere de fiecare tip (litere, cifre i neafiabile) sunt ntr-un fiier text.
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
void main()
{
FILE *f; int l,c,g; char ch;
l=c=g=0;
if((f=fopen(in.txt,r))==NULL)
{ printf(nu se poate deschide fisierul pentru citire);
exit(1);
}
do{
ch=fgetc(f);
if(isalpha(ch)) l++;
if(isdigit(ch)) c++;
if(!isprint(ch)) g++; // caracterul nu este afisabil
}while(ch!=EOF);
printf(\n numarul de litere este %d,l);
printf(\n numarul de cifre este %d,c);
printf(\n numarul de caractere neafisabil este %d,g);
fclose(f);
}

10.6 Funcii de citire/scriere pe iruri de caractere

Funcia char *fgets(char *s, int n, FILE *f); citete un ir de caractere dintr-un fiier oarecare.
Primul parametru, s, reprezint zona de memorie n care se stocheaz irul citit. Parametrul n indic
numrul maxim de caractere care se vor citi din fiier. Dac se detecteaz mai puine caractere rmase
pe linia curent din fiier, citirea se oprete la ntlnirea caracterului sfrit de linie \n. n cazul unei
citiri reuite, funcia ntoarce un pointer la irul citit, n caz de sfrit de fiier sau de eroare se ntoarce
pointerul NULL.
Observaie: Funcia fgets insereaz n linia citit i caracterul \n generat la apsarea tastei Enter.
Pentru o prelucrare corect a irului de caractere citit din fiier, acest caracter trebuie eliminat utiliznd
spre exemplu instruciunea linie[strlen(linie)-1]=0 care scrie terminatorul de ir \0 peste caracterul
\n (am considerat c irul citit din fiier s-a depus n variabila linie).
Funcia int fputs(const char *s, FILE *f); scrie irul de caractere s (care nu se modific) n
fiierul f. n caz de eroare, funcia ntoarce valoarea EOF.
Exemplul 1: Copierea a dou fiiere text, linie cu linie.
#include<stdio.h>
void main()
{
FILE *f1,*f2; char linie[80];
f1=fopen(in.txt,r);
f2=fopen(out.txt,w);
do{
if(feof(f1)) break;
fgets(linie,80,f1); fputs(linie,f2);
}while(1);
fcloseall();
}
Exemplul 2: Afiarea unui fiier text pe ecran. La fiecare afiare a 22 de linii se va face o pauz,
afiarea continund la apsarea unei taste.
#include<stdio.h>
void main()
{
FILE *f; char linie[80];
long n=0; // numara cate linii au fost citite
f=fopen(in.txt,r);
while(!feof(f))
{ fgets(linie,80,f); printf(%s,linie);
if(++n%22==0) getch();
}
fclose(f);
}
Exemplul 3: Fiind dat un fiier, s se determine numrul de linii, linia de lungime maxim i lungimea
fiierului (numrul de caractere utile).
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
{
FILE *f; char linie[120];
int l,max=0; // lungimea celei mai lungi linii din fisier
long nr=0,n=0; // nr-lungimea fisierului, n-numarul de linii
f=fopen(in.txt,r);
if(f==NULL) { printf(fisierul nu exista); exit(1); }
while(!feof(f))
{ n++;
fgets(linie,120,f);
l=strlen(linie);
if(max<l) max=l;
nr+=l;
}
printf(linia de lungime maxima :%d\n,max);
printf(numarul de linii :%ld\n,n);
printf(lungimea fisierului :%ld\n,nr);
fclose(f);
}
Exemplul 4: Programul urmtor numr apariiile unui cuvnt ntr-un fiier text. Citirea acestuia se face
linie cu linie.
#include<stdio.h>
#include<string.h>
void main()
{
typedef char STRING[256];
STRING cuv,linie,
FILE *f;
char *p;
int nr=0;
f=fopen(in.txt,r);
printf(cuvantul cautat : ); scaf(%s,cuv);
while(!foef(f))
{ fgets(linie,256,f);
p=linie;
while(p!=NULL) // mai sunt caractere in linie
{ p=strstr(p,cuv);
// cauta cuvantul in sirul curent de caractere
if(p) // cuvantul apare in sirul curent)
{ nr++; // numarul aparitia cuvantului
p++; // avansez la urmatorul caracter din sir
// pentru a repeta cautarea
}
}
}
printf(numarul de aparitii: %d,nr);
fclose(f);
}

10.7 Funcii de citire/scriere cu format

Pentru citirea valorilor unor variabile dintr-un fiier text se folosete funcia
int fscanf(FILE *f, specificatori_de_format, adrese_variabile);
Funcia fscanf realizeaz urmtoarele:
- citete o secven de cmpuri de intrare caractere cu caracter
- formateaz fiecare cmp conform specificatorului de format corespunztor
- valoarea obinut este stocat la adresa variabilei corespunztoare
Valoarea ntoars, n caz de succes, este numrul de cmpuri citite. Dac nu a fost citit nici-un cmp,
funcia ntoarce valoarea 0. Dac funcia citete sfritul de fiier, atunci valoarea ntoars este EOF.
Specificatorii de format pentru funcia fscanf sunt aceeai cu cei ai funciei scanf.
Pentru scrierea cu format a datelor ntr-un fiier text se folosete funcia:
int fprintf(FILE *f, specificatori_de_format, expresii);
Funcia fprintf realizeaz urmtoarele:
- accept o serie de argumente de tip expresie pe care le formateaz conform specificatorilor de
format corespunztori
- scrie datele formatate n fiierul specificat
Funcia fprintf folosete aceleai formate ca i funcia printf.

10.8 Funcii de citire/scriere a fiierelor pe blocuri de octei

Aceste funcii realizeaz citirea i scrierea datelor fr a face o interpretare sau conversie a
acestora. Se folosesc doar n modul de acces binar i sunt orientate pe zone compacte de octei.
Funciile pot fi folosite i pentru citirea/scrierea nregistrrilor.
Funcia fread citete n nregistrri dintr-un fiier, fiecare nregistrare avnd dim octei. Funcia
ntoarce numrul nregistrrilor citite i are sintaxa:
int fread(void *pointer, int dim, int n, FILE *f);
Funcia fwrite scrie ntr-un fiier n nregistrri a cte dim octei fiecare i ntoarce numrul total
de nregistrri scrise. Funcia are sintaxa:
int fwrite(void *pointer, int dim, int n, FILE *f);
Exemplul : Se arat modul n care trebuie scris o nregistrare ntr-un fiier binar.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pers
{ int ani;
char nume[20];
};
void main()
{
FILE *f; struct pers s;
f=fopen(test.bin,wb);
if(!f)
{ printf(fisierul nu se poate deschide); exit(1); }
s.ani=40;
strcpy(s.nume,Mihai Popescu);
fwrite(&s,sizeof(s),1,f); // scrie structura s in fisier
fclose(f);
}

10.9 Funcii pentru aflarea poziiei curente i schimbarea ei

Funcia cea mai folosit pentru determinarea poziiei curente de citire/scriere este
long ftell(FILE *f);
Pentru poziionarea n fiier se utilizeaz funciile :
- int fseek(FILE *f, long nr, int origine); care mut indicatorul de fiier cu un numr de nr octei
fa de punctul origine. Originea arat punctul fa de care este msurat deplasarea : 0 (sau
SEEK_SET) fa de nceputul fiierului, 1 (sau SEEK_CUR) fa de poziia curent, 2 (sau
SEEK_END) fa de sfritul fiierului.
- void rewind(FILE *f); mut poziia curent a fiierului la nceputul su
Exemplu: Determinarea lungimii unui fiier.
#include<stdio.h>
void main()
{
FILE *f; f=fopen(in.txt,r);
fseek(f,0L,SEEK_END); // fseek(f,0L,2);
printf(fisierul are %ld octeti,ftell(f));
fclose(f);
}

10.10 Exerciii i texte gril

1. Care dintre afirmaiile de mai jos sunt 3. n timpul execuiei programului urmtor sunt
adevrate ? posibile urmtoarele situaii :
a) instruciunea care deschide #include<stdio.h>
fiierul nr.txt pentru citire i void main()
returneaz un pointer ctre {
fiierul deschis este f=fopen(r, FILE *f; int x=1,s=0;
nr.txt); f=fopen(suma.txt,r);
b) pentru a putea citi din fiier while(!feof(f) && x)
folosim atribut r la deschidere, { fscanf(f,%d,&x);
iar pentru a scrie n fiier l if(x%2) s+=x;
deschidem cu atributul w }
c) pentru a testa dac nu s-a ajuns fclose(f);
la sfritul fiierului referit de printf(\ns=%d,s);
pointerul f, vom scrie !feof(f) }
d) pentru a nchide fiierul a) programul este corect sintactic
referit de pointerul f vom scrie b) pentru a funciona citirea din
close(f) fiier, acesta trebuie deschis n
e) nici una dintre afirmaiile de alt mod
mai sus nu este adevrat c) programul va intra ntr-un ciclu
infinit
2. Se consider un fiier definit prin pointerul f, d) dac n fiier se gsesc, pe
i care conine urmtoarele valori pe primele acelai rnd separate prin cte
dou rnduri : un spaiu, numerele 2 5 4 3
4 7 2.5 -6.23 6 1 0 7, atunci programul va
# 8 afia s=16
Fie urmtoarele declaraii de variabile: e) modul n care este nchis
FILE *f; fiierul nu corespunde cu modul
int x,y; float a,b,d; char c; n care a fost deschis
Care dintre secvenele de instruciuni de mai
jos trebuie executate astfel nct toate 4. Fie fiierul identificat prin descriptorul f,
variabilele declarate s primeasc valori citite avnd urmtorul coninut:
din fiierul f ? 5
a) fscanf(f,%d %f %d %f\n,&x, 2 3 4 6 7 8
&a,&y,&b); Care dintre secvenele urmtoare de program
fscanf(f,%c %f,&c,&d); S1, S2, S3 poate fi executat, astfel nct, n
b) fscanf(f,%d %d %f %f\n,&x, vectorul v s se citesc corect toate numerele
&y,&a,&b); din fiier ?
fscanf(f,%c %f,&c,&d); //secventa S1
c) fscanf(f,%d %d %f %f\n,&x, fscanf(f,%d,&n);
&y,&b,&a); for(i=0;i<n;i++)
fscanf(f,%f %c,&d,&c); fscanf(f,%d,&v[i]);
d) fscanf(%f %f %d %d\n,&b,&a, //secventa S2
&y,&x,f); j=0;
fsacnf(%c %f,&c,&d,f); while(!feof(f))
e) fscanf(%d %f %d %f\n,&x,&a, { fscanf(f,%d,&v[j]); j++; }
&y,&d,f); n=j;
fscanf(%f %c,&d,&c,f); //secventa S3
j=0;
do{
fscanf(f,%d,&v[j]);j++; 7. Precizai care va fi coninutul fiierului g
}while(!feof(f)); dup execuia programului urmtor, dac
n=j-1; fiierul f conine pe fiecare linie o zi a
a) toate b) nici una sptmnii (luni,..,duminica) :
c) numai S1 i S2 d) numai S2 i S3 #include<stdio.h>
e) numai S1 #include<math.h>
void main()
5. Ce numr se va gsi pe al patrulea rnd al {
fiierului 4.txt dup execuia programului FILE *f,*g; int j=1;
urmtor ? char s[11],c1,c2;
#include<stdio.h> f=fopen(7.txt,r);
void main() g=fopen(7_2.txt,w);
{ while(j++<4) fgets(s,10,f);
FILE *f; fprintf(g,%d ,j-1);
f=fopen(4.txt,w); fputs(s,g);
int n=8,j=0, fclose(f); fclose(g);
v[8]={1,3,8,5,0,6,7,4}; }
while(v[j]%2) j++; a) 3 Miercuri b) 3 Joi
while(j<n) c) 4 Miercuri d) 4 Joi e) 5 Joi
if(v[j++])
fprintf(f,%d\n,v[j]); 8. Fie programul urmtor:
fclose(f); #include<stdio.h>
} void main()
a) 5 b) 0 c) 6 {
d) 7 e) 4 FILE *f,*g; int a,x,s;
f=fopen(in.txt,r);
6. Fie programul: g=fopen(out.txt,w);
#include<stdio.h> scanf(%d,&a);
#include<math.h> while(!feof(f))
void main() { s=0;
{ while(s<a && !feof(f))
FILE *f,*g; int e; { fscanf(f,%d,&x);
char c1, c2; s+=x; }
f=fopen(1.txt,r); fprintf(g,%d,s);
g=fopen(2.txt,r); }
e=1; fclose(f); fclose(g);
do{ printf(\n s=%d,s);
c1=fgetc(f); }
c2=fgetc(g); Dac de la tastatur se introduce valoarea 10,
if(c1!=c2) e=0; iar coninutul fiierului in.txt este 4 6 3 2 6
}while(!(feof(f)||feof(g)) 15 1 (pe aceeai linie), cte numere va scrie
&&e); programul n fiierul out.txt ?
if(e) a) nici unul b) unul c) dou
if(!(feof(f)&&feof(g)))e=0; d) trei e) patru
fclose(f); fclose(g);
printf(%d,e); 9. Cte numere se vor gsi n fiierul nr.txt
} dup execuia programului urmtor ?
Programul de mai sus afieaz valoarea 1 #include<stdio.h>
dac: void main()
a) cele dou fiiere difer prin {
cel puin un caracter int v[9]={0,1,0,0,2,3,0,4,5},
b) cele dou fiiere sunt identice j;
c) n cele dou fiiere exist i FILE *f;
caractere identice f=fopen(nr.txt,w);
d) cele dou fiiere au acelai j=0;
numr de caractere while(j<9)
e) nici unul dintre cazurile de mai { while(v[j])
sus fprintf(f,%3d,v[j++];
fprintf(f,%3d,99);
j++;
} 3 3
fclose(f); 1 2 3
} 4 5 6
a) 4 b) 5 c) 8 7 8 9
d) 9 e) 10 #include<stdio.h>
void main()
10. Deducei ce valoare va afia programul {
urmtor, tiind c n fiierul f se gsesc pe un FILE *f;
rnd, separate prin spaii, numerele 1 3 0 0 2 int i,j,m,n,s=0,a[20][20];
-3 0 -4 -1 f=fopen(c.txt,r);
#include<stdio.h> fscanf(f, %d %d,&m,&n);
#include<math.h> for(i=0;i<m;i++)
void main() for(j=0;j<n;j++)
{ { fscanf(f,%d,&a[i][j]);
FILE *f; if((i+j)%2) s+=a[i][j];
int s=1,j=0,a[20]; }
f=fopen(nr.txt,r); fclose(f); printf(%d,s);
while(!feof(f)) }
{ j++; a) 0 b) 8 c) 20
fscanf(f,%d,&a[j]); d) 25 e) programul este
if(a[j]) s*=abs(a[j]); eronat
}
printf(\n%d,s); fclose(f); 13. Se d fiierul identificat prin descriptorul f,
} cu urmtorul coninut:
a) 1 b) 72 c) 72 33 1 -45 18 6
d) programul conine erori de Ce instruciune trebuie scris n loc de ..
sintax astfel nct programul urmtor s tipreasc
e) nu se pot citi corect numerele 85?
din fiier #include<stdio.h>
void main(()
11. Presupunnd c toate liniile fiierului g {
conin cel mult 100 de caractere, care este FILE *f;
aciunea programului urmtor ? int x, y;
#include<stdio.h> f=fopen(v.txt,r);
void main() fseek(f,-6,2);
{ fscanf(f,%d,&y);
FILE *f,*g; char s[101];
f=fopen(1.txt,a); fscanf(f,%d,&x);
g=fopen(2.txt,r); printf(\n%d%d,x,y);
while(!feof(g)) fclose(f);
{ fgets(s,100,g); }
fputs(s,f); } a) fseek(f,11,0); b)fseek(f,-2,2);
fclose(f); fclose(g); c) fseek(f,3,1); d)fseek(f,2,1);
} e) fseek(f,-3,2);
a) nlocuiete coninutul
fiierului g cu coninutul 14. Precizai ce nume se va gsi pe al cincilea
fiierului f rnd din fiierul p.txt dup execuia
b) nlocuiete coninutul programului de mai jos:
fiierului f cu coninutul #include<stdio.h>
fiirului g #include<string.h>
c) concateneaz fiierul g la void main()
sfritul fiierului f {
d) concateneaz fiierul f la FILE *f;
sfritul fiierului g int i=0,j,k; char *aux;
e) nici unul dintre cazurile char *a[9]={Marius,
anterioare Claudiu,3rei-Sud-Est,
Daniel,Vasile,Dan,
12. Deducei ce valoare va afia programul de Sinacdu,2Pac};
mai jos, dac fiierul text are urmtorul while(a[i]) i++;
coninut: for(j=0;j<i-1;j++)
for(k=j+1;k<i;k++) #include<math.h>
if(strcmp(a[j],a[k])>0) void main()
{ aux=a[j];a[j]=a[k]; {
a[k]=aux;} FILE *f,*g; int v[10];
k=0; f=fopen(p.txt,w); f=fopen(a.txt,r);
while(a[k]) g=fopen(b.txt,w);
fprintf(f,%s\n,a[k++]); fread(v,8,1,f);
fclose(f); fwrite(v,6,1,g);
} fclose(f); fclose(g);
a) 2Pac b) Claudiu c) Dan }
d) Daniel e) Marius a) 11 2 13 4 15 6
b) 1 2 2 4 1 6
15. Precizai care va fi coninutul fiierului c) 11 2 13
b.txt dup execuia programului urmtor, d) 11 2 1
tiind c fiierul a.txt are urmtorul coninut: e) un alt coninut dect cel
11 2 13 4 15 6 17 8 19 indicat
#include<stdio.h>
Rspunsuri la testele gril

1.5 Elemente de baz ale limbajului C


1)a 2)c 3)c 4)b 5)d 6)a 7)c 8)d

2.3 Tipuri fundamentale de date

1)b 2)a 3)d 4)b 5)b 6)c 7)c 8)c 9)a,b,c,d 10)e 11)a,b
12)c 13)b,c,d,e 14)a,c,d 15)d 16)c 17)b 18)c 19)c 20)a

3.8 Funcii de intrare/ieire standard

1)c 2)c 3)c 4)c 5)c 6)e 7)b 8)b 9)c 10)b 11)a,c 12)b
13)c 14)b,c 15)a 16)c 17)a 18)d 19)c 20)a 21)a 22)a 23)a 24)a
25)c 26)b 27)c 28)d 29)c 30)c 31)d 32)b 33)b 34)b 35)b 36)b
37)d 38)b

4.13 Operatorii limbajului C


1)b 2)a,d 3)b 4)a,c,d 5)b,c,e,g 7)a,c,f 10)b 11)a,b 13)c
14)a,b 19)c 20)b 21)d 22)b 23)d 24)d 25)a 26)d 27)b 28)a 29)b
30)c 31)b 32)c 33)b 34)d 35)c 36)c 37)a,d 38)d 39)b,c,e 40)c
41)c 42)b,c 43)b 44)b 45)d 46)a,e 47)b,e 48)e 49)e 50)c,e 51)a,c,e
52)a,e 53)c 54)c 55)c 56)a,c,d 57)a,e 58)e

5.16 Instruciunile limbajului C

1)a,d 2)a,c,d,e 3)b 4)c 5)e 6)a,c 7)b 8)c 9)e 10)d 11)b
12)c 13)d 14)a 15)a 16)d 17)b 18)a 19)a 20)b 21)c 22)c 23)d
24)d 25)b 26)c 27)d 28)c 29)c 30)d 31)b 32)a 33)d,e 34)e 35)c
36)c 37)a,c 38)a,d,e 39)b 40)d 41)b 42)b,c 43)a 44)b 45)b,e 46)c
47)b,c 48)b 49)a,b,e

6.5 Tablouri
1)c 2)d 3)a,b 4)c 5)d 6)b,d,e 7)e 8)d 9)b 10)a,d 11)d 12)a,b,d
13)b,c 14)d 15)b,d 16)b 17)c 18)a 19)d 20)c 21)c 22)c 23)b 24)d
25)d 26)a 27)a 28)a 29)a 30)c 31)c 32)b 33)d 34)c 35)d 36)b 37)c

7.4 Pointeri

7) b cu e, c cu d 10)b 11)c,d,e 12)d 13)e 14)d 15)a 16)a,b,c 17)c


18)c 19)a,d 20)b 21)c 22)a 23)d 24)b,c 25)d,e 26)b,e 27)c
28)a,c,e 29)e 30)d 31)c 32)b,c 33)d 34)b 35)b 36)a 37)a 38)a 39)a
40)a 41)a 42)a 43)a 44)b 45)c 46)d

8.6 iruri de caractere

1)c 2)b 3)c 4)a,b,e 5)a,d,e 6)a 7)b 8)d 9)b 10)d 11)b
12)e 13)d 14)b 15)e 16)a,b 17)d 18)b 19)c 20)e 21)d 22)a 23)b
24)d 25)b,c 26)b
9.4 Structuri

1)d 2)d 3)c 4)b 5)d 6)d 7)c 8)d

10.10 Exploatarea fiierelor

1)b,c 2)b 3)a 4)d 5)d 6)b 7)c 8)e 9)e 10)b 11)c 12)c
13)d,e 14)d 15)d
Bibliografie

1. Herbert Schildt
- C manual complet, Editura Teora, Bucureti, 1998
2. Liviu Negrescu
- Limbajul C,vol.I, II, Editura Albastr, Cluj-Napoca, 1997
3. Dorian Stoilescu
- Manual de C/C++, Editura Radial, Galai, 1998
4. Damian Costea
- Iniiere n limbajul C, Editura Teora, Bucureti, 1996
5. George-Daniel Mateescu, Pavel Florin Moraru
- Limbajul C++, probleme i teste gril pentru liceu i bacalaureat,
Editura Niculescu, Bucureti, 2001
6. Claudia Botez, Dumitru Ilinca
- Teste de informatic, Editura Universitii Tehnice Ghe. Asachi, Iai, 2001

S-ar putea să vă placă și