Sunteți pe pagina 1din 114

PR E FA

Algoritmul este un concept folosit pentru a desemna o mulime


finit de operaii, complet ordonat n timp, care pornind de la date de
intrare produce ntr-un timp finit date de ieire. Cu alte cuvinte, algoritmul
red metoda de rezolvare a unei probleme ntr-un numr finit de pai.
Programul este reprezentarea unui algoritm ntr-un limbaj de
programare. Sunt cunoscute mai multe limbaje de programare, dezvoltate
odat cu evoluia calculatoarelor. O anumit problem poate fi mai uor sau
mai dificil de codificat ntr-un anumit limbaj de programare, ntruct multe
din limbajele de programare de nivel nalt sunt orientate pe probleme.
Programarea este activitatea de elaborare a unui produs program.
Ea are dou ramuri importante:
a) descrierea algoritmilor;
b) codificarea algoritmilor ntr-un anumit limbaj de programare.
Descrierea unui algoritm pentru rezolvarea unei probleme se poate face prin
scheme logice sau ntr-un limbaj de descriere a algoritmilor, numit i
pseudocod.
La disciplina de Programarea calculatoarelor s-a adoptat descrierea
algoritmilor n pseudocod, iar ca limbaj de programare se utilizeaz C/C++.
In ntreaga activitate legat de aceast disciplin, se insist asupra
respectrii urmtoarelor etape de rezolvare a unei probleme:
a) Analiza problemei, care const n enunul clar, precis al problemei
de rezolvat, specificarea datelor de intrare i ieire.
b) Proiectarea programului, care const n stabilirea metodei de
rezolvare i ntocmirea proiectului logic.
c) Implementarea programului, care const n codificarea ntr-un
limbaj de programare, editarea fiierului surs, compilarea, editarea de
legturi, execuia i testarea.
d) ntocmirea documentaiei. In cadrul seminarului, fiecare student
primete o tem din domeniile generrii de submulimi, calculului numeric,
algoritmilor de sortare etc. Documentaia va conine urmtoarele piese:

enunul problemei;
- lista variabilelor de intrare i ieire i modul de
reprezentare a lor pe suportul extern;
- prezentarea n limbaj natural a metodei de rezolvare;
- proiectul logic;
- listingul programului surs;
- rezultatele testrii experimentale;
- instruciuni de operare.
e) ntreinerea programului.
Respectarea acestor etape conduce la obinerea unor performane
legate de productivitatea programrii i de calitatea produsului program.
De asemenea, att la curs, ct i la seminar i laborator, se urmrete
nsuirea unui stil de programare, caracterizat prin atribute care confer unui
program o anumit personalitate:
- evidenierea structurii programului;
- modularizarea programului;
- abstractizarea datelor;
- claritatea programului;
- posibilitatea de modificare ulterioar cu efort mic;
- tratarea erorilor;
- generalitatea soluiei.
n acest sens, la codificare, se recomand urmtoarele:
- alegerea unor nume simbolice care s reflecte
semnificaia obiectelor pe care le reprezint;
folosirea indentrii pentru scoaterea n relief a
structurilor de control;
- documentarea programului;
- scrierea unor funcii de nalt generalitate pentru utilizri
ulterioare;
- protecia la erori datorit depirii dimensiunii tablourilor,
a domeniului de valori pentru tipurile de date numerice etc.;
- folosirea variabilelor globale s se fac ct mai puin
posibil.
Prezentul ndrumtor conine 11 lucrri de laborator, n care sunt
tratate fundamentele limbajului C/C++. Fiecare lucrare conine prezentarea
unor noiuni teoretice cu exemple rulate n BORLAND C/C++ versiunea
4.5. i propuneri de probleme adecvate noiunilor tratate n lucrare.
ndrumtorul se adreseaz studenilor din anul I , secia tiina
sistemelor i calculatoarelor pentru pregtirea i efectuarea lucrrilor de
4

laborator la disciplina de Programarea calculatoarelor, dar este util i celor


interesai de perfecionarea n programare i obinerea unui stil de a scrie
programe n mod profesionist.
Disciplina de Programarea calculatoarelor st la baza
disciplinei Structuri de date i algoritmi, unde se trateaz listele, arborii,
grafurile, tabelele de dispersie i metodele generale de elaborare a
algoritmilor.
Menionm faptul c nsuirea gndirii algoritmice i obinerea
ndemnrii de a scrie programe performante necesit mult munc
individual. De aceea, se pretinde pregtirea teoretic a lucrrilor de
laborator i rezolvarea de ctre fiecare student acas a problemelor propuse,
iar la orele de laborator numai s se implementeze cteva programe
semnificative.
Autorul aduce mulumiri d-lui Mihai Vintiloiu, d-lui ing. Crian
Valer-Alin i d-lui ing. Coroian-Vlad Rzvan pentru ajutorul dat la editarea
lucrrilor de laborator. De asemenea, autorul mulumete editurii U.T.
PRESS pentru publicarea lucrrii ntr-o inut grafic corespunztoare.
Cluj-Napoca, 20 iulie 2001
Prof. dr. ing. IGNAT IOSIF

CUPRINS
1. FUNCII DE INTRARE/IEIRE STANDARD

2. EXPRESII

17

3. INSTRUCIUNI

22

4. FUNCII

35

5. PROGRAMAREA MODULAR

45

6. POINTERI

54

7. RECURSIVITATE

67

8. IRURI DE CARACTERE

74

9. TIPURILE DE DATE STRUCTUR, UNIUNE I


ENUMERARE

82

10. PRELUCRAREA FIIERELOR DE CTRE


NIVELUL INFERIOR AL S.G.F.

93

11. PRELUCRAREA FIIERELOR DE CTRE


NIVELUL SUPERIOR AL S.G.F.

105

BIBLIOGRAFIE

115

Lucrarea de laborator nr. 1

FUNCII DE INTRARE/IEIRE STANDARD

1. Coninutul lucrrii
n lucrare sunt prezentate funciile I/E standard, adic funciile din
biblioteca compilatorului C/C++, care realizeaz citirea/scrierea din/n
fiierele standard de I/E.

1. Consideraii teoretice
Terminalul standard este terminalul de la care s-a lansat programul.
Terminalului standard i sunt ataate dou fiiere: de intrare (stdin) i de
ieire (stdout). Ele sunt fiiere secveniale.
Funciile din biblioteca compilatorului C/C++ utilizate mai frecvent
pentru operaiile de I/E sunt:
- pentru intrare: getch, getche, gets, scanf, sscanf ;
- pentru ieire: putch, puts, printf, sprintf.
la care se mai adaug macrourile getchar pentru intrare i putchar pentru
ieire.
2.1.

Funciile getch, getche i putch

Funcia getch citete fr ecou un caracter prin apsarea unei taste.


Tasta poate avea un corespondent ASCII sau o funcie special. n primul
caz funcia returneaz codul ASCII al caracterului. n al doilea caz, funcia
se apeleaz de dou ori: prima dat returneaz valoarea zero, iar a doua oar
returneaz o valoare specific tastei acionate.
Funcia getche este analog cu funcia getch, realiznd ns citirea
cu ecou.

Apelul funciilor getch i getche conduce la ateptarea apsrii unei


taste.
Funcia putch afieaz pe ecranul terminalului un caracter
corespunztor codului ASCII transmis ca parametru. Caracterele
imprimabile au codul ASCII n intervalul [32,126]. Pentru coduri n afara
acestui interval se afieaz diferite imagini. Funcia returneaz valoarea
parametrului de la apel.
Prototipurile acestor trei funcii se gsesc n fiierul conio.h i sunt:
int getch(void);
int getche(void);
int putch(int ch);
Exemplu de utilizare:
/* Programul L1Ex1.cpp */
#include <conio.h>
main()
{
putch(getch());
getch();
}
2.2.

Funciile gets i puts

Funcia gets citete cu ecou de la terminalul standard un ir de


caractere ale codului ASCII, la adresa specificat drept parametru al
funciei. Din funcie se revine la:
- citirea caracterului \n (newline), caracter care este transformat
n caracterul \0 (null). n acest caz funcia returneaz adresa de
nceput a zonei de memorie n care se pstreaz caracterele;
- citirea sfritului de fiier (CTRL/Z), funcia returnnd valoarea
zero.
Funcia puts afieaz la terminalul standard un ir de caractere
corespunznd codului ASCII de la adresa transmis ca parametru. Caracterul

10

\0 este interpretat ca \n. Funcia returneaz codul ultimului caracter afiat


sau 1 n caz de eroare.
Prototipurile funciilor se gsesc n fiierul stdio.h i sunt:
char *gets (char *s);
int puts (const char *s);
Exemplu de utilizare:
/* Programul L1Ex2.cpp */
#include <stdio.h>
#include <conio.h>
main
{
char s{200];
printf(\nIntroducei un ir de caractere urmat de
ENTER\n);
gets(s);
printf(\nSirul de caractere introdus\n);
puts(s);
getch();
}
2.3. Funciile scanf i printf
Funcia scanf are rolul de a introduce date tastate de la terminalul
standard sub controlul unor formate. Datele introduse sunt convertite din
formatele lor externe n formate interne i sunt pstrate la adresele
specificate la apel. Datele introduse se termin cu apsarea tastei ENTER.
Prototipul funciei scanf se gsete n fiierul stdio.h i este:
int scanf(const char *format [,adresa,..]);
Ea returneaz numrul de cmpuri de la intrare introduse corect sau
valoarea EOF(-1) n cazul ntlnirii sfritului de fiier (CTRL/Z).

11

Formatul este specificat ca un ir de caractere. El conine


specificatorii de format, care definesc conversiile din formate externe n
formate interne. Un specificator de format este alctuit din:
- caracterul %;
- opional caracterul *, care indic faptul c data prezent la intrare
nu se atribuie nici unei variabile;
- opional un numr zecimal, care definete lungimea maxim a
cmpului controlat de format;
- 1 sau 2 litere, care definesc tipul conversiei.
Cmpul controlat de format ncepe cu primul caracter curent care nu
este alb i se termin, dup caz:
a) la caracterul dup care urmeaz un caracter alb;
b) la caracterul care nu corespunde tipului de conversie;
c) la caracterul la care se ajunge la lungimea maxim a cmpului.
Datele se citesc efectiv dup apsarea tastei ENTER. Adresa unei
variabile se specific prin &nume_variabil.
Literele care definesc tipul conversiei sunt:
Litera
c
s
d
o
x, X
u
f
ld, lo, lx, lX
lu
lf/ Lf

Tipul datei citite


char
ir de caractere
ntreg zecimal
ntreg octal
ntreg hexazecimal
unsigned
float
long
unsigned long
double/long double

Funcia printf este folosit pentru afiarea unor date pe ecranul


terminalului standard sub controlul unor formate. Datele sunt convertite din
format intern n formatul extern specificat.
Prototipul funciei printf se gsete n fiierul stdio.h i este:

12

int printf(const char *format [,expresie, ]);


Formatul este dat ca un ir de caractere. El are n structura sa
succesiuni de caractere (care se afieaz) i specificatori de format.
Un specificator de format conine:
- caracterul %;
- opional caracterul minus -, care specific cadrarea datei n
stnga cmpului (implicit cadrarea se face n dreapta);
- opional un numr zecimal, care definete dimensiunea minim a
cmpului n care se afieaz data;
- opional un punct urmat de un numr zecimal, care specific
precizia de afiare a datei;
- una sau dou litere, care definesc tipul conversiei. Fa de literele
prezentate la scanf apar literele e i E pentru afiarea datelor float
sau double sub form de exponent, g i G pentru afiarea datelor
sub forma de exponent sau nu, astfel ca data afiat s ocupe un
numr minim de caractere.
Funcia returneaz numrul de caractere (octei) afiate la terminal
sau 1 n caz de eroare.
Exemple de folosire:
/* Programul L1Ex3.cpp */
#include <stdio.h>
#include <conio.h>
main( )
{
int a;
float b,c;
printf(\nIntroducei o valoare ntreag a=);
scanf(%5d,&a);
printf(\nIntroducei o valoare real b=);
scanf(%5f,&b);
c=a+b;
13

printf(\nValoarea c=a+b este: %6.3f\n,c);


getch();
}
2.4. Funciile sscanf i sprintf
Fa de funciile scanf i printf, funciile sscanf i sprintf au n plus
ca prim parametru adresa unei zone de memorie care conine caractere
ASCII. Funcia sscanf citete caracterele din aceast zon de memorie n loc
de zona tampon corespunztoare fiierului standard de intrare (tastaturii).
Funcia sprintf depune caracterele n aceast zon de memorie n loc de a fi
afiate pe ecran.
Prototipurile acestor funcii se gsesc n fiierul stdio.h i sunt:
int scanf (const char *buffer, const char *format [,adresa, ..]);
int sprintf (char *buffer, const char *format [,adresa, );
Exemplu de folosire:
/* Programul L1Ex4.cpp */
#include <stdio.h>
#include <conio.h>
main ( )
{
char s[100], q[100];
int a,b;
float c,d;
printf (\nIntroduceti n acelai rnd valoarea\n\
lui a i b despite ntre ele prin blanc\n\
urmate de ENTER\n);
gets(s);
sscanf(s,%d %f, &a, &c);
printf(\n a=%4d c=%8.3f\n,a,c);
sprintf(q,%4d %8.3f\n,a,c);
sscanf(q,%d %f,&b,&d);
printf(\n b=%5d d=%9.4f\n,b,d);
getch();
}
14

2.5. Macrourile getchar i putchar


Macroul getchar permite citirea cu ecou a caracterelor codului
ASCII, deci nu a celor corespunztoare tastelor speciale. Caracterele tastate
se introduc ntr-o zon tampon pn la acionarea tastei ENTER. La
revenire, se returneaz codul ASCII al primului caracter introdus, iar la un
nou apel, al urmtorului caracter introdus .a.m.d. La ntlnirea sfritului de
fiier (CTRL/Z) se returneaz valoare EOF(-1).
Macroul putchar afieaz caracterul al crui cod ASCII s-a
transmis.
Macrourile getchar i putchar sunt definite n fiierul stdio.h i au
formatele:
int getchar(void);
int putchar (int c);
i se apeleaz exact ca funciile getch i putch.
Exemplu de utilizare:
/* Programul L1Ex5.cpp */
#include <stdio.h>
#include <conio.h>
main( )
{
putchar(getchar)() ;
putchar(\n);
getch();
}

3. Mersul lucrrii
3.1. Se vor executa programele date ca exemplu n lucrare i se vor
analiza rezultatele obinute.
3.2. Scriei un program pentru a verifica modul de execuie a funciei

15

getch cnd se apas o tast care corespunde unei funcii speciale.


3.3. Scriei un program pentru a verifica ce se afieaz de ctre
funcia putch atunci cnd parametrul su este o valoare n afara intervalului
[32,126].
3.4. Scriei un program care afieaz codurile ASCII ale caracterelor
corespunztoare tastaturii.
3.5. Scriei un program care afieaz caracterele corespunztoare
codurilor ASCII din intervalul [32,126].
3.6. Scriei un program care s conin apelul gets(s), unde s a fost
definit ca un tablou.
Verificai ce conine fiecare element al tabloului. De ce
caracterul \n a fost nlocuit cu \0?
3.7. Scriei un program care citete un ir de litere mici i le afieaz
sub form de litere mari.
3.8. Scriei un program care citete un ir de litere mari i le afieaz
sub form de litere mici.
3.9. Scriei un program care realizeaz suma, diferena, produsul i
mprirea a dou numere reale. Afiarea se va face sub form tabelar:
x

x+y

xy

x*y

x/y

3.10. Scriei un program pentru a verifica modul de afiare a valorii


lui = 3.14159265 cu diferii descriptori de format.
3.11. Scriei un program pentru afiarea unui ntreg citit de la
tastatur n octal i hexazecimal.

16

Lucrarea de laborator nr. 2

EXPRESII

1. Coninutul lucrrii
Scopul lucrrii este prezentarea noiunii de expresie n limbajul
C/C++, a operatorilor i a modului de evaluare a unei expresii.

2. Consideraii teoretice
2.1 Definirea expresiei
O expresie este format dintr-un operand sau mai muli operanzi
legai prin operatori.
Un operand poate fi:
- o constant;
- o constant simbolic;
- numele unei variabile simple;
- numele unui tablou;
- numele unei structuri;
- numele unui tip;
- o variabil indexat;
- numele unei funcii;
- referina la elementul unei structuri;
- apelul unei funcii;
- expresie inclus n paranteze rotunde.
Unui operand i corespunde o valoare i un tip.
Operatorii pot fi unari sau binari.
La evaluarea unei expresii trebuie s se in seama de:
- prioritile operatorilor;
- asociativitatea operatorilor de aceeai prioritate;
17

regula conversiilor implicite.

2.2 Operatori
Operatorii limbajului C/C++ sunt mprii n urmtoarele clase:
-

operatori aritmetici:
- operatori unari: +, - operatori binari multiplicativi: *, /, %
- operatori binari aditivi: +, operatori relaionali: <, <=, >, >=
operatori de egalitate: = =, !=
operatori logici: !, &&, ||
operatori logici pe bii: ~, <<, >>, &, ^, |
operatori de atribuire: =, /=, *=, %=, +=, -=, <<=, >>=, &=, ^=,
|=
operatori de incrementare: ++, -operatori de forare tip: (tip) operand
operatori dimensiune: sizeof
operatori adres: &
operatori parantez: ( ), [ ]
operatori condiionali: ?, :
operatorul virgul: ,
operatorul de derefereniere: *
operatorul de acces la componenta unei structuri: . , ->

Observaie: n limbajul C++ s-au mai introdus civa operatori:


-

operatorul de rezoluie: ::
operatorul pentru tipul referin: &
operatorul de alocare/dealocare dimensiune a memoriei heap:
new/delete

Prioritile operatorilor, n ordine descresctoare, sunt prezentate n


tabelul de mai jos:

18

Prioritile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Operatori
( ) [ ] ->
+(unar) -(unar) &(unar) *(unar) ++ -- (tip) sizeof
!~
*(binar) / %
+(binar) -(binar)
<< >>
< <= > >=
= = !=
&(binar)
^
|
&&
||
? :
= <<= >>= += -= *= /= %= &= ^= |=
,

Operatorii din aceeai linie au aceeai prioritate.


n ceea ce privete asociativitatea operatorilor, se precizeaz c ei se
asociaz de la stnga la dreapta cu excepia operatorilor unari, condiionali
i de atribuire, care se asociaz de la dreapta la stnga.
2.3. Regula conversiilor implicite
Regula conversiilor implicite const n urmtoarele:
-

dac un operator binar se aplic la operanzi de acelai tip, atunci


rezultatul va avea tipul comun al operanzilor;
dac un operator binar se aplic la doi operanzi de tipuri diferite,
atunci operandul de tip inferior se convertete implicit spre tipul
superior al celuilalt operand, iar rezultatul va avea tipul superior.
Ordinea descresctoare a prioritii tipurilor este urmtoarea:

long double;
19

double;
float;
unsigned long;
long;
int.

3. Mersul lucrrii
3.1. S se scrie un program pentru calculul valorii z= x**y, x i y
fiind de tipul double.
3.2. Explicai deosebirea ntre mprirea real i cea ntreag.
3.3. S se scrie un program care citete un unghi n grade
sexagesimale i calculeaz valoarea funciei sinus, cosinus i tangent.
3.4. S se scrie un program care citete un numr natural n
intervalul [1600, 4900] ce reprezint un an i verific dac este bisect sau
nu.
3.5. Folosind expresii condiionale, s se scrie un program care
citete valoarea real a lui x i calculeaz valoarea funciei:
x 2 4x 4

f ( x)
0
x 2 5x

daca x 2
daca x 0
daca x 2

3.6. S se scrie un program care citete un numr real x, ce


reprezint msura unui unghi n radiani, i l transform n grade, minute i
secunde sexagesimale.
3.7. S se scrie un program care simuleaz funcionarea unui
numrtor de tip ceas (se indic ora, minutul i secunda).
3.8. Scriei un program pentru a indica numrul de octei ocupai n
memorie de tipurile de date din limbajul C/C++.

20

3.9. Convertii n binar, prin calcul, anul naterii i anul curent.


Artai cum se reprezint ca o dat de tip int. Efectuai operaiile de
deplasare stnga cu 4 bii, dreapta cu 2 bii, complement fa de 1 asupra lor,
precum i operaiile pe bii &, ^, | , avnd ca operanzi cele dou date. Scriei
un program pentru a verifica corectitudinea calculelor dumneavoastr.
3.10. Scriei un program ce efectueaz operaii aritmetice asupra a
dou date de tip ntreg i real. Executai-l pentru valori care conduc la
rezultat n afara limitelor de reprezentare intern. Ce se ntmpl n acest
caz?

21

Lucrarea de laborator nr. 3

INSTRUCIUNI

1. Coninutul lucrrii
n lucrare sunt prezentate principalele instruciuni simple i
structurate din limbajul C/C++: instruciunea expresie, instruciunea vid,
instruciunea compus, instruciunea if, instruciunea switch i instruciunile
repetitive.

2. Consideraii teoretice
Programul structurat este un program care are o structur de control
realizat numai cu:
- structura secvenial;
- structura alternativ i selectiv;
- structura repetitiv.
n limbajul C/C++ mai exist instruciunile return, break, continue
i goto, care asigur o flexibilitate mare n scrierea de programe.
2.1.

Instruciunea expresie

Instruciunea expresie are formatul:


expresie;
adic dup expresie se scrie ;.
Ea se utilizeaz ca instruciune de atribuire sau ca instruciune de
apel a unei funcii.
Exemplu de utilizare:

22

/* Programul L3Ex1.cpp */
/* Programul afiseaza maximul dintre 2 intregi */
#include <conio.h>
#include <stdio.h>
main()
{
int a,b,c;
printf("\nIntroduceti doi intregi a si b\n");
scanf("%d %d",&a,&b);
c=a>b?a:b;
printf("\nMaximul dintre a=%d si b=%d este c=%d\n",a,b,c);
getch();
}
2.2.

Instruciunea vid

Instruciunea vid se reduce la punct i virgul, fr a avea vreun


efect. Ea se utilizeaz acolo unde se cere prezena unei instruciuni, dar de
fapt nu trebuie s se execute ceva (de exemplu n instruciunile repetitive).
Exemplu de utilizare:
for(i = 0, s = 0; i < n; s = s + a[i], ++i);
2.3.

Instruciunea compus

Instruciunea compus este o succesiune de instruciuni incluse ntre


acolade, eventual precedate de declaraii (valabile numai n acest loc):
{
declaraii;
instruciuni;
}
Instruciunea compus se utilizeaz acolo unde este nevoie conform
sintaxei de o singur instruciune, dar procesul de calcul necesit mai multe
instruciuni.
Exemplu de utilizare este dat n programul L3Ex2.cpp :

23

/* Programul L3Ex2.cpp */
/* Calculul radacinilor ecuatiei a*x^2 +b*x +c =0 */
#include <stdio.h>
#include <conio.h>
#include <math.h
main()
{
float a,b,c,delta,x1,x2;
printf("\nIntroduceti a,b,c\n");
scanf("%f %f %f",&a,&b,&c);
if (a!=0)
{
delta=b*b-4*a*c;
if (delta >= 0) {
x1=(-b-sqrt(delta))/(2*a);
x2=(-b+sqrt(delta))/(2*a);
printf("\nEcuatia are radacinile x1=%g si
x2=%g\n",x1,x2);
}
else {
x1=-b/(2*a);
x2=sqrt(-delta)/(2*a);
printf("\nEcuatia are radacinile complex conjugate:\
x1=%g - j*%g si x2= %g+ j*%g\n",x1,x2,x1,x2);
}
}
else printf("\nEcuatia nu este de ordinul 2 (a=0)\n");
getch();
}
2.4 Instruciunea if
Instruciunea if are dou formate:
a)

if ( expresie )
instruciune
24

b)

if ( expresie )
instruciune_1
else instruciune_2

Efectul ei este urmtorul:


Se evalueaz expresia expresie.
Dac rezultatul expresiei este true se execut n cazul a)
instruciunea instruciune i n cazul b) instruciune_1 i apoi se trece la
instruciunea imediat urmtoare instruciunii if.
Dac rezultatul expresiei este false se trece n cazul a) la
instruciunea imediat urmtoare instruciunii if, iar n cazul b) se trece la
execuia instruciune_2 i apoi se trece la instruciunea imediat urmtoare
instruciunii structurate if.
Observaii:
a)
instruciunile
instruciune,
instruciune_1,
instruciune_2 pot conine instruciuni de salt la alte instruciuni
dect cea urmtoare instruciunii if.
b)
instruciunea if poate conine alte instruciuni if. Trebuie
atenie la mbinarea lui else, n sensul de a ti la care if aparine.
Exemplu de utilizare: Programul L3Ex2.cpp (a se vedea punctul
2.3).
2.5 Instruciunea switch
Instruciunea switch are urmtoarea sintax:
switch ( expresie )
{
case C1: sir_instruciuni_1;
break;
case C2: sir_instruciuni_2;
break;
...........................................
case Cn: sir_instruciuni_n;
break;
default: sir_instruciuni
}

25

Efectul instruciunii switch este urmtorul:


a)
se evalueaz expresie;
b) se compar pe rnd rezultatul evalurii cu constantele C1, C2,
, Cn. Dac rezultatul evalurii coincide cu constanta Ci se executa
instruciunile sir_instruciuni_i i apoi se trece la instruciunea
imediat urmtoare switch-ului. Daca rezultatul evalurii nu coincide
cu nici una din constantele C1, C2, , Cn se execut instruciunile
sir_instruciuni aflate dup default.
Observaii:
a)
Alternativa default este opional. Dac nu este prezent, n
cazul n care rezultatul expresiei expresie nu coincide cu nici o
constant Ci, instruciunea switch nu are nici un efect.
b)
Dac break nu este prezent, atunci se execut i irurile de
instruciuni imediat urmtoare, pn la ntlnirea unei instruciuni
break sau pn la terminarea instruciunii switch.
c)
Instruciunea structurata switch poate fi nlocuit prin
instruciuni if imbricate.
Exemplu de utilizare:
/* Programul L3Ex3.cpp */
/* Operatii cu numere intregi de forma
OPERAND1operatorOPERAND2
*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define INFINIT 0x7fff
main()
{
int operand1,operand2,rezultat;
char operatie;
printf("\nScrieti expresia fara spatii intre operanzi i\
operator\n");
scanf("%d%c%d",&operand1,&operatie,&operand2);
switch(operatie)
{
case '+': rezultat=operand1+operand2;
break;
26

case '-': rezultat=operand1-operand2;


break;
case '*': rezultat=operand1*operand2;
break;
case '/': if (operand2!=0) rezultat =
operand1/operand2;
else if (operand1 >0) rezultat=INFINIT;
else rezultat=-INFINIT;
break;
default: exit(1);
};
printf("\n%d %c %d = %d\n", operand1, operatie,
operand2, rezultat);
getch();
}
2.6 Instruciunea while
Formatul instruciunii while este urmtorul:
while ( expresie )
instruciune
Efectul instruciunii while este urmtorul:
a) se evalueaz expresie;
b) dac rezultatul este true se execut corpul su (instruciune) i
se revine la pasul a). Daca rezultatul este false se trece la
execuia instruciunii imediat urmtoare instruciunii while.
Observaii:
a) n cazul n care expresie este false de la nceput, atunci
instruciune nu se execut niciodat.
b) n cadrul corpului instruciunii while este nevoie de existena
unor instruciuni de modificare a variabilelor care intr n
expresie.
Exemplu de utilizare:

27

/* Programul L3Ex4.cpp */
/* Calculul c.m.m.d.c. si a c.m.m.m.c
a doua numere naturale a si b */
#include <conio.h>
#include <stdio.h>
main()
{
int a,b,a1,b1,cmmdc,cmmmc,rest;
printf("Introduceti a=");
scanf("%d",&a);
printf("Introduceti b=");
scanf("%d",&b);
/* Aflarea c.m.m.d.c. */
a1=a;b1=b;
while ((rest=a1%b1)!=0)
{
a1=b1;
b1=rest;
};
cmmdc=b1;
cmmmc=a*b/cmmdc;
clrscr();
printf("a=%d b=%d cmmdc(a,b)=%d cmmmc=%d", a, b,
cmmdc, cmmmc);
getch();
}
2.7 Instruciunea for
Formatul instruciunii for este urmtorul:
for ( expr1; expr2; expr3 )
instruciune
unde:
- expr1, expr2, expr3 sunt expresii;
- instruciune este corpul instruciunii.
Descrierea efectului instruciunii for, cu ajutorul instruciunii while
este urmtorul:
28

expr1;
while ( expr2 ) {
instruciune;
expr3;
}
Observaie: expr1, expr2, expr3 pot fi vide, ns caracterele ; nu
pot lipsi.
Exemplu de utilizare:
/* Programul L3Ex5.cpp */
/* Calculul mediei aritmetice a n numere reale */
#include <conio.h>
#include <stdio.h>
main()
{
float a[100],media,suma;
int i,n;
printf("\nIntroduceti nr.de elemente n=");
scanf("%d",&n);
printf("\nIntroduceti elementele sirului\n");
for(i=0,suma=0;i<n;++i)
{
printf("a[%2d]=",i);
scanf( "%f",&a[i]);
suma+=a[i];
};
media=suma/n;
printf("\nMEDIA=%g\n",media);
getch();
}
2.8 Instruciunea do-while
Instruciunea do-while este instruciunea ciclic cu test final.
Formatul ei este urmtorul:
29

do
instruciune
while ( expresie );
Efectul ei este descris cu instruciunea while astfel:
instruciune;
while( expresie )
instruciune;
Se observ c corpul ciclului se execut cel puin o dat.
Exemplu de utilizare:
/* Programul L3Ex6.cpp */
/* Calculul c.m.m.d.c. si a c.m.m.m.c
a doua numere naturale a si b */
#include <conio.h>
#include <stdio.h>
main()
{
int a,b,a1,b1,cmmdc,cmmmc,rest;
printf("Introduceti a=");
scanf("%d",&a);
printf("Introduceti b=");
scanf("%d",&b);
/* Aflarea c.m.m.d.c. */
a1=a;b1=b;
do{
rest=a1%b1;
a1=b1;
b1=rest;
}
while (rest!=0);
cmmdc=a1;
cmmmc=a*b/cmmdc;
clrscr();
30

printf("a=%d b=%d cmmdc(a,b)=%d


cmmmc=%d",a,b,cmmdc,cmmmc);
getch();
}
2.9 Instruciunile continue i break
Instruciunile continue i break se pot utiliza numai n corpul unui
ciclu.
Instruciunea continue abandoneaz iteraia curent i se trece la
execuia pasului de reiniializare n cazul instruciunii for, respectiv la
revalidarea expresiei care stabilete continuarea sau terminarea ciclului n
cazul instruciunilor while i do-while.
Instruciunea break termin ciclul i se trece la instruciunea imediat
urmtoare celei repetitive (for, while, do-while).
2.10. Instruciunea goto
Instruciunea goto este utilizat pentru saltul dintr-un punct al unei
funcii (chiar i dintr-un ciclu) n alt punct al aceleai funcii, respectiv la o
instruciune etichetat.
Eticheta este un nume urmat de caracterul :
nume:
Formatul instruciunii goto este:
goto eticheta;
Exemplu:

goto alfa;

alfa: if ( )

2.11. Funcia standard exit


Prototipul funciei standard exit este descris n fiierele stdlib.h i
process.h i este:
31

void exit(int cod);


Funcia exit are ca scop terminarea forat a programului. Codul de
ieire folosit este zero pentru terminare normal i alte valori pentru
terminare datorat unor erori.

3. Mersul lucrrii
3.1. Se vor analiza i executa programele date ca exemplu n lucrare.
3.2. De la tastatur se citesc 4 perechi de numere reale, care
reprezint n coordonate rectangulare vrfurile unui patrulater. S se
stabileasc natura acestui patrulater.
3.3. De pe mediul de intrare sunt citite elementele reale ale unui ir
de dimensiunea n. S se gseasc valoarea minim i valoarea maxim
dintre elementele irului i poziia lor.
3.4. S se scrie un program pentru generarea tuturor numerelor prime
mai mici sau egale cu un numr natural n.
3.5. Se citete un numr natural n. S se gseasc cel mai mare
ptrat perfect mai mic sau egal cu n. Aceeai problem, dar s se indice
numrul prim cel mai mic, dar mai mare sau egal cu numrul citit.
De pe mediul de intrare se citete un numr natural n. S se
verifice dac numrul respectiv este palindrom.
3.6.

De pe mediul de intrare se citesc cifrele hexazecimale ale unui


3.7.
numr ntreg n baza 16. Sa se calculeze i s se afieze reprezentarea
numrului n baza 10.
Se citete gradul i coeficienii polinomului p(x)=a0
3.8.
+a1x1+......+ anxn S se calculeze valoarea polinomului n x= x 0 (x0 se
citete).
3.9.

S se scrie un program pentru efectuarea operaiilor de

32

adunare, scdere, nmulire i mprire ntre dou polinoame:


A(x)=a0 +a1x1+......+ anxn
B(x)=b0 +b1x1+......+ bmxm
Gradele i coeficienii reali ai polinoamelor se citesc de pe
mediul de intrare.
3.11.Se d un sistem de n ecuaii liniare cu n necunoscute. S se
scrie un program de rezolvare a sistemului, folosind o metoda numeric.
3.12. Sa se calculeze polinoamele P(x) i Q(x) din relaia:
n
ai
Q( X )

P ( X ) i 1 bi x ci
Valorile n, ai , bi , ci se citesc de la tastatur.

3.13. Se d un ir de n elemente reale ordonate cresctor. S se


verifice dac o valoare citit x se gsete n ir i s se indice poziia sa.
3.14. Se d un ir de n numere ntregi. S se extrag subirul de
dimensiune maxim, ordonat cresctor.
3.15. Pentru elaborarea unui test de aptitudini se dispune de un set de
n ntrebri, fiecare ntrebare i fiind cotat cu un numr de pi puncte. S se
elaboreze toate chestionarele avnd q ntrebri, fiecare chestionar totaliznd
ntre a i b puncte. ntrebrile sunt date prin numr i punctaj.
3.16. Se dau 2 iruri de n si respectiv m elemente de tip ntreg. S se
calculeze:
a) irul ce conine elementele comune ale celor dou iruri;
b
b) irul ce conine toate elementele celor dou iruri
luate o singura dat;
c
c) irul ce conine elementele primului ir din care au
fost
eliminate elementele comune.
d
3.17. Se d un numr real a n baza 10. S se scrie programul de
conversie a lui n baza B, B <= 16.

33

3.18. Se d un numr natural n.


a) S se gseasc numrul obinut prin eliminarea cifrelor care
apar de mai multe ori n numr.
b)S se gseasc numrul obinut prin interschimbarea ntre ele
a primei cifre cu ultima , a celei de a doua cu penultima .a.m.d.
c)S se gseasc cel mai mare numr ce se poate obine din
cifrele sale.
3.19. Se d o matrice de nxn elemente 0 i 1. S se stabileasc dac
matricea respectiv este simetric.
3.20. De pe mediul de intrare se citete o propoziie. S se indice
numrul cuvintelor i cuvntul cel mai lung din propoziie.

34

Lucrarea de laborator nr.4

FUNCII

1. Coninutul lucrrii
n lucrare se prezint structura unei funcii, apelul unei funcii prin
valoare i prin referin, prototipul unei funcii.

2. Consideraii teoretice
Un program conine una sau mai multe funcii, dintre care una este
funcia principal avnd numele main. Celelalte au un nume dat de
programator.
2.1.

Structura unei funcii

O funcie are urmtoarea structur:


tip nume (lista_parametrilor_formali)
{
declaraii
instruciuni
}
Primul rnd din definiia funciei se numete antet, iar restul se
numete corpul funciei.
n limbajul C/C++ exist dou categorii de funcii:

35

funcii care returneaz n punctul de apel o valoare prin


instruciunea return expresie; valoarea avnd tipul specificat n
antet prin tip;
funcii care nu returneaz nici o valoare n punctul de apel, tip
fiind nlocuit prin cuvntul cheie void.

Lista parametrilor formali poate conine:


- zero parametri, caz n care antetul funciei se reduce la:
tip nume ()
sau
tip nume (void)
- unul sau mai muli parametri formali, separai ntre ei prin
virgul. Un parametru formal se indic prin: tip nume.
Exemplu:
int rezolv_sistem (int n, double a [10] [10], double b[10], double x [10])
Prototipul unei funcii se obine scriind punct i virgul dup o
construcie identic cu antetul funciei respective sau obinut prin
eliminarea numelui parametrilor formali.
Exemplu:
int factorial (int n);
int factorial (int);
Funciile standard de bibliotec au prototipurile n diferite fiiere cu
extensia .h, cum ar fi stdio.h, conio.h, math.h etc. Funciile standard de
bibliotec se gsesc n format obiect (extensia .obj), i se adaug n
programe n faza de editare de legturi. Prototipurile funciilor standard se
includ n program nainte de apelul lor prin construcia #include.
1.1. Apelul unei funcii
O funcie care nu returneaz nici o valoare se apeleaz astfel:
nume (lista_parametrilor_efectivi);

36

Corespondena ntre parametrii formali i cei efectivi este


poziional.
-

O funcie care returneaz o valoare poate fi apelat


fie printr-o instruciune de apel ca mai sus, caz n care valoarea
returnat se pierde;
fie ca un operand al unei expresii, valoarea returnat folosindu-se la
evaluarea expresiei respective.

Tipul parametrilor formali i cei actuali se recomand s fie acelai.


n caz contrar, n limbajul C tipul parametrului efectiv este convertit
automat la tipul parametrului formal. n limbajul C++ se utilizeaz o
verificare mai complex pentru apelul funciilor. De aceea se recomand
utilizarea operatorului de conversie explicit (tip), adic expresiile cast.
Exemplu:
f((double)n)
Revenirea dintr-o funcie se face fie dup execuia ultimei
instruciuni din corpul funciei, fie la ntlnirea instruciunii return.
Instruciunea return are formatele:
return;
sau
return expresie;
Observaie:
a) Dac tipul expresiei din instruciune este cel din antetul funciei, se
face conversia automat spre cel al funciei.
b) Primul format al funciei return se folosete n funciile care nu
returneaz nici o valoare.
Transmiterea parametrilor efectivi (actuali) se poate face:
- prin valoare (call by value);
- prin referin (call by reference).
n cazul apelului prin valoare, unui parametru formal i se transfer
valoarea parametrului efectiv. n acest caz, funcia apelat nu poate modifica
parametrul efectiv din funcia care a fcut apelul, neavnd acces la el.
Programul L4Ex1.cpp ilustreaz acest lucru:
37

/*Programul L4Ex1.cpp */
#include <stdio.h>
#include <conio.h>
/* APEL PRIN VALOARE */
/*Procedura de interschimbare intre a si b */
void interschimbare(int a,int b)
{
int aux;
printf("\nIn functie la intrare a=%d b=%d\n",a,b);
aux=a;a=b;b=aux;
printf("\nIn functie la iesire a=%d b=%d\n",a,b);
}
void main()
{
int a,b;
a=2;b=3;
printf("\nIn main inaintea apelului functiei interschimbare\
a=%d b=%d\n",a,b);
interschimbare(a,b);
printf("\nIn main la revenirea din functia interschimbare\
a=%d b=%d\n",a,b);
getch();
}
Se va constata c a i b i pstreaz vechile valori.
Pentru ca interschimbarea s se produc, este necesar folosirea
pointerilor, ca mai jos:
/*Programul L4Ex2.cpp */
#include <stdio.h>
#include <conio.h>
/* APEL PRIN VALOARE FOLOSIND POINTERI*/
/*Procedura de interschimbare intre a si b */
void interschimbare(int *a,int *b)
{
int aux;
printf("\nIn functie la intrare a=%d b=%d\n",*a,*b);
38

aux=*a;*a=*b;*b=aux;
printf("\nIn functie la iesire a=%d b=%d\n",*a,*b);
}
void main()
{
int a,b;
a=2;b=3;
printf("\nIn main inaintea apelului functiei interschimbare\
a=%d b=%d\n",a,b);
interschimbare(&a,&b);
printf("\nIn main la revenirea din functia interschimbare\
a=%d b=%d\n",a,b);
getch();
}
Se va constata c valorile a i b au fost interschimbate ntre ele.
Acest mod de transmitere a parametrilor este tot prin valoare, adic unui
pointer i s-a transmis o adres.
n cazul apelului prin referin, se transmit adresele parametrilor, nu
valoarea lor. Acest mod de transmitere este valabil n C++. n acest caz,
parametrii formali sunt definii ca fiind de tip referin.
Acelai exemplu n acest caz devine:
/*Programul L4Ex3.cpp */
#include <stdio.h>
#include <conio.h>
/* APEL PRIN REFERINTA */
/*Procedura de interschimbare intre a si b */
void interschimbare(int& a,int& b)
{
int aux;
printf("\nIn functie la intrare a=%d b=%d\n",a,b);
aux=a;a=b;b=aux;
printf("\nIn functie la iesire a=%d b=%d\n",a,b);
}

39

void main()
{
int a,b;
a=2;b=3;
printf("\nIn main inaintea apelului functiei interschimbare\
a=%d b=%d\n",a,b);
interschimbare(a,b);
printf("\nIn main la revenirea din functia interschimbare\
a=%d b=%d\n",a,b);
getch();
}
Se va constata c valorile lui a i b au fost interschimbate ntre ele.
Observaie important: n cazul n care un parametru efectiv este
numele unui tablou, atunci acesta are ca valoare adresa primului element,
deci se transmite adresa ca valoare pentru parametrul formal corespunztor.
n acest caz, dei apelul s-a fcut prin valoare, funcia respectiv poate
modifica elementele tabloului al crui nume s-a folosit ca parametru efectiv.
Drept exemplu de folosire a funciilor, n continuare se prezint un
program care realizeaz cteva operaii asupra a dou polinoame.
/*Programul L4Ex4.cpp */
/* Operatii asupra polinoamelor
Un polinom are forma P(x)=p[0]+p[1]*x+ p[2]*x^2 +...p[n]* x^n */
#include <conio.h>
#include <stdio.h>
# define GRADMAX 20
void produs(int n,float a[], int m,float b[],
int *p,float c[])
{
int i,j;
*p=n+m;
for(i=0;i<=n+m;i++) c[i]=0.0;
for(i=0;i<=n;i++)
40

for(j=0;j<=m;j++)
c[i+j]+=a[i]*b[j];
}
void impartire(int n, float a[],int m,float b[],
int *grad_cat,float cat[], int *grad_rest, float rest[])
{
int i,j,k;
if (n<m) {
*grad_cat=0;cat[0]=0.0;
*grad_rest=m;rest=cat;
}
else {
*grad_cat=n-m;*grad_rest=m-1;
for(i=n-m,j=n;i>=0;i--,j--)
{
cat[i]=a[j]/b[m];
for (k=m;k>=0;k--)
a[i+k]=a[i+k]-cat[i]*b[k];
a[j]=0;
};
for(i=0;i<=m-1;i++)
rest[i]=a[i];
}
}
void citire_polinom(int *n,float a[])
{
int i;
printf("\nIntroduceti gradul polinomului ");
scanf("%d",n);
for(i=0;i<=*n;i++)
{
printf("\na[%d]=",i);
scanf("%f",&a[i]);
};
printf("\n");
}

41

float val_polinom(float x,int n,float a[])


{
int i;
float v;
v=0.0;
for(i=n;i>=0;i--)
v=v*x+a[i];
return v;
}
void afis_polinom(int n,float a[],char c)
{
int i;
printf("\n%c[x]=%g",c,a[0]);
for(i=1;i<=n;i++)
printf("+%g*x^%d",a[i],i);
printf("\n");
}
void main()
{
int n,m,grad_r,grad_cat,grad_rest;
float x, v,p[GRADMAX+1],q[GRADMAX+1],r[GRADMAX+1],
cat[GRADMAX+1],rest[GRADMAX+1];
clrscr;
citire_polinom(&n,p);afis_polinom(n,p,'P');
citire_polinom(&m,q);afis_polinom(m,q,'Q');
printf("\nIntroduceti x=");scanf("%f",&x);
v=val_polinom(x,n,p);
printf("Val.Polinomului p pentru x=%f este %f",x, v);
getch();
produs(n,p,m,q,&grad_r,r);
printf("\nR[x]=P[x]*Q[x]\n");
afis_polinom(grad_r,r,'R');
getch();
impartire(n,p,m,q,&grad_cat,cat,&grad_rest,rest);
printf("\nREZULTATUL IMPARTIRII P[x]/Q[x]=>catul C[x] i\
restul R[x]\n");
afis_polinom(grad_cat,cat,'C');
afis_polinom(grad_rest,rest,'R');
42

getch();
printf("\nATENTIE! Polinomul p este modificat\n");
afis_polinom(n,p,'P');
getch();
}

3.Mersul lucrrii
3.1. Se va analiza modul de transmitere a parametrilor efectivi n
programele din lucrare date ca exemplu.
n continuare se vor scrie programe pentru rezolvarea urmtoarelor
probleme, folosind funcii i diverse moduri de transmitere a parametrilor.
Se va evita folosirea variabilelor globale.
3.2. De pe mediul de intrare se citete gradul unui polinom i
coeficienii si, care sunt numere ntregi.
P ( x) p p1 x1 ... pn x n

n care p0 este nenul.


tiind c polinomul admite numai rdcini ntregi simple, s se
gseasc rdcinile polinomului.
3.3. De pe mediul de intrare se citete n i perechile de numere
ntregi ( xi , yi ), i 1, n reprezentnd o relaie binar R peste mulimea M.
a) Admind c fiecare element din mulimea M apare n cel puin o
pereche dintre cele citite, s se determine mulimea M.
b) S se verifice dac relaia R este o relaie de echivalen
(reflexiv, simetric i tranzitiv).
3.4. Se dau dou iruri de caractere care reprezint numere ntregi
zecimale foarte mari. S se scrie un program de efectuare a operaiilor
aritmetice asupra lor.
3.5. S se scrie funciile pentru adunarea, scderea i nmulirea a
dou matrice i apoi s se realizeze calculul A=B*C 2*(B+C), unde B i C
sunt dou matrice ptratice de ordinul n.
43

3.6. S se scrie funcia care realizeaz operaiile aritmetice asupra a


dou matrice rare (matricea rar este o matrice de dimensiune mare, care
are multe elemente nule).
3.7. Fiind date anul, luna, ziua, s se scrie o funcie care s returneze
a ctea zi din an este ziua respectiv i cte zile au mai rmas din anul
respectiv.
3.8.S se scrie o funcie care primind ca parametru un numr roman
sub forma unui ir de caractere, returneaz numrul respectiv ca numr arab
n baza 10.
S se scrie o funcie care primind ca parametru un numr
arab n baza 10, calculeaz irul de caractere ce reprezint numrul
respectiv sub form roman.
3.10.

De pe mediul de intrare se citete un numr ntreg, multiplu


de 100. S se gseasc numrul minim de bancnote romneti necesare
pentru plata sumei respective.
3.11.

44

Lucrarea de laborator nr.5

PROGRAMAREA MODULAR

1. Coninutul lucrrii
n lucrare sunt prezentate conceptele de modul, programare
modular i vizibilitate a variabilelor

2. Consideraii teoretice
2.1. Noiunea de modul
Modulul surs este o parte a textului surs al programului, care se
compileaz separat de restul textului surs a programului.
Modulul obiect este rezultatul compilrii unui modul surs.
Un modul surs conine funcii nrudite, n sensul ca ele concur la
rezolvarea unei subprobleme.
De fapt modulele corespund subproblemelor rezultate n urma
proiectrii top-down a unei probleme complexe.
Programarea modular este stilul de programare care are la baz
utilizarea de module. Prin acest stil de programare se poate pune n valoare
posibilitile de ascundere a datelor i procedurilor mpotriva unor accese
neautorizate din alte module. Astfel, datele statice declarate n afara
funciilor modulului, pot fi utilizate n comun de acestea, dar nu pot fi
accesate de ctre funciile din alte module.
Recomandarea care se face n scrierea unui program complex este
de a-l modulariza, permind lucrul n echip.
Modularizarea unui program duce la punerea la punct a programului
(implementarea i testarea) mai rapid.
Modulele puse la punct pot fi utilizate ulterior pentru rezolvarea
altor probleme.
n rezolvarea unor probleme complexe, programul executabil poate
fi obinut n urmtoarele moduri:
45

a) Se scriu mai multe fiiere surs, fiecare surs constituind un


modul surs. Evident, fiecare modul surs este pus la punct
separat. Cu ajutorul construciei
#include specificator de fiier
sunt incluse textele surs fie n modulul care conine funcia
principal main, fie ntr-un fiier care conine numai includerile
tuturor modulelor, inclusiv a modulului care conine funcia
principal main().
n felul acesta se obine de fapt un singur program surs, care va fi
compilat, linkeditat i executat.
b) Se scriu mai multe module surs. Se compileaz separat
obinndu-se mai multe module obiect (avnd extensia .obj). Se
linkediteaz aceste module obiect, obinndu-se fiierul executabil.
Modulele surs pot fi compilate separat i linkeditate folosind un
fiier de tip Project. Acesta se editeaz utiliznd meniul Project al
mediului Turbo C++.
2.2. Domeniul de valabilitate al variabilelor
2.2.1. Variabile globale
Variabilele globale sunt definite la nceputul unui fiier surs, deci
naintea primei funcii. Ele sunt variabile vizibile din locul respectiv pn la
sfritul fiierului surs respectiv. Dac programul are mai multe fiiere
surs, o variabil global definit ntr-un fiier surs poate fi utilizat n
celelalte, dac este declarat ca extern. Declararea unei variabile externe
se poate face:
-

dup antetul unei funcii, caz n care variabila global este valabil
numai n acea funcie;
la nceputul fiierului surs, adic naintea primei funcii, caz n care
este valabil pentru toate funciile din acel fiier.

46

Observaie:Se recomand ca variabilele externe s fie declarate n


fiecare funcie unde se utilizeaz, evitnd erorile care pot aprea prin
mutarea ulterioar a unei funcii n alt modul
Variabilele globale sunt alocate la compilare, ntr-o zon de memorie
special.
2.2.2.Variabilele locale
Variabilele declarate ntr-o funcie sau intr-o instruciune compus au
valabilitate numai n unitatea declarat.
Ele pot fi:
a) automatice care sunt alocate pe stiv la execuie. Ele i pierd
existena la revenirea din funcie sau la terminarea instruciunii
compuse. Declararea lor este cea obinuita (int a,b,c; double x;
etc.);
b) statice - care sunt alocate la compilare ntr-o zon special.
Declararea se face cu ajutorul cuvntului cheie static naintea tipului
variabilei. Exemplu:
static int x,y,z;
-

Declararea unei variabile statice poate fi fcut:


la nceputul fiierului surs (deci naintea primei funcii). n acest
caz variabila static respectiv este valabil n tot fiierul surs
respectiv, dar nu poate fi declarat ca extern n alte fiiere;
n corpul unei funcii, caz n care este valabil numai n ea sau n
instruciunea compus unde a fost declarat.
c) variabile registru care sunt alocate n registrele procesorului.
Ele pot fi numai variabile int, char i pointer. Se recomand
declararea ca variabile registru, variabilele des utilizate n funcia
respectiv. Numrul variabilelor registru este limitat. Dac s-au
declarat mai multe, cele care nu pot fi alocate n registre vor fi
alocate pe stiv ca variabile automatice.

Declararea variabilelor registru se face cu ajutorul cuvntului cheie


register:
47

register tip variabil;


Alocarea este valabil numai n funcia n care au fost declarate.

2.3. Exemplu de program modularizat


Urmtorul program calculeaz inversa i determinantul unei matrice
ptrate cu elemente double. Programul a fost modularizat astfel:
Fiierul L5Ex1_1.cpp conine funcia de citire a dimensiunilor i
elementelor unei matrice i funcia de afiare a unei matrice:
/* Afisarea si citirea unei matrice de n*m elemente de tip
double */
#include <stdio.h>
#include <conio.h>
#define NMAX 10
void afisare(int n,int m,double a[NMAX][NMAX],char ch)
{
int i,j;
printf("\n MATRICEA %c\n",ch);
for(i=0;i<n;i++)
{ for(j=0;j<m;j++)
printf("%8.2lf ",a[i][j]);
printf("\n");
}
}
void citire_matrice(int *n,int *m,double a[NMAX][NMAX])
{
int i,j;
printf("\nIntroduceti nr.linii n=");scanf("%d",n);
printf("\nIntroduceti nr.coloane m=");scanf("%d",m);
printf("\nIntroduceti elementele matricei\n");
for (i=0;i<*n;i++)
for(j=0;j<*m;j++)
48

{
printf("a[%d,%d]=",i,j);scanf("%lf",&a[i][j]);
}
printf("\n");
}
Fiierul L5Ex1_2.cpp conine funcia de nmulire a dou matrice;
/* Functia calculeaza produsul matricelor a[n][m]
si b[m][p] de tip double rezultand matricea c[n[][p] */
#define NMAX 10
void produs(int n,int m,int p,double a[NMAX][NMAX],
double b[NMAX][NMAX],double c[NMAX][NMAX])
/* Calculul produsului c=a*b) */
{
int i,j,k;
double s;
for(i=0;i<n;i++)
for(j=0;j<p;j++)
{
s=0.0;
for(k=0;k<m;k++)
s=s+a[i][k]*b[k][j];
c[i][j]=s;
};
}
Fiierul L5Ex1_3.cpp conine funcia de calcul a inversei unei
matrice ptrate i a determinatului afiat:
/*Program de calcul a inversei unei matrice si a determinantului
atasat */
#include <math.h>
#define NMAX 10

49

void invers(int n,double a[NMAX][NMAX],double eps,


double b[NMAX][NMAX],double *det_a,
int *err)
{
int i,j,k,pozmax;
double amax,aux;
/* Initializarea matricei b cu matricea unitatwe */
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==j) b[i][j]=1.0;
else b[i][j]=0.0;
/* Initializarea determinantului */
*det_a=1.0;
/* Se face 0sub diagonala principala si 1 pe ea */
k=0; /*k=nr.liniei */
*err=0;
while((k<n) && (*err==0))
{
/*Calcul element pivot*/
amax=fabs(a[k][k]);pozmax=k;
for(i=k+1;i<n;i++)
if (fabs(a[i][k]) >amax) {
amax=fabs(a[i][k]);
pozmax=i;
};
/*Interschimbarea liniei k cu pozmax in matr. a si b */
if( k!=pozmax) {
for(j=0;j<n;j++)
{
aux=a[k][j];
a[k][j]=a[pozmax][j];
a[pozmax][j]=aux;
aux=b[k][j];
b[k][j]=b[pozmax][j];
b[pozmax][j]=aux;
};
*det_a=-*det_a;
};
50

if( fabs(a[k][k]) <eps) *err=1;


else {
*det_a =*det_a*a[k][k];
aux=a[k][k];
for(j=0;j<n;j++)
{
a[k][j]=a[k][j] / aux;
b[k][j]=b[k][j] / aux;
};
for(i=0;i<n;i++)
if(i!=k) {
aux=a[i][k];
for(j=0;j<n;j++)
{
a[i][j]=a[i][j]-a[k][j]*aux;
b[i][j]=b[i][j]-b[k][j]*aux;
}
}
}
k++;
}
}
Fiierul L5Ex1_4.cpp conine funcia main;
/*Program de calcul a inversei unei matrice si a
determinantului atasat */
#include <stdio.h>
#include <conio.h>
#define NMAX 10
void citire_matrice(int *n,int *m,double a[NMAX][NMAX]);
void afisare(int n,int m,double a[NMAX][NMAX],char ch);
void produs(int n,int m,int p,double a[NMAX][NMAX],
double b[NMAX][NMAX],double c[NMAX][NMAX]);
void invers(int n,double a[NMAX][NMAX],double eps,
double b[NMAX][NMAX],double *det_a,int *err);

51

void main()
{
int i,j,n,m,err;
double eps,det_a,a[NMAX][NMAX],a1[NMAX][NMAX],
b[NMAX][NMAX],c[NMAX][NMAX];
clrscr;
citire_matrice(&n,&m,a);
afisare(n,m,a,'A');
getch();
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a1[i][j]=a[i][j];
eps=1.0e-6;
invers(n,a1,eps,b,&det_a,&err);
if(err==1) printf("\nMATRICEA A ESTE SINGULARA");
else { printf("\nMATRICEA INVERSA B=A^(-1)\n");
afisare(n,n,b,'B');
printf("\nDETERMINANTUL MATRICEI A ESTE
%8.4lf",det_a);
produs(n,n,n,a,b,c);
printf("\nVERIFICARE C=A*B REZULTA MATRICEA
UNITATE!");
afisare(n,n,c,'C');
getch();
}
}
Fiierul L5Ex1_5.cpp conine construciile de includere a fiierelor
de mai sus.
#include "d:\iosif\limbaj_C\L5Ex1_1.cpp"
#include "d:\iosif\limbaj_c\L5Ex1_2.cpp"
#include "d:\iosif\limbaj_c\L5Ex1_3.cpp"
#include "d:\iosif\limbaj_c\L5Ex1_4.cpp"

52

3. Mersul lucrrii
3.1. Se va compila, executa i analiza programul dat ca exemplu mai
sus.
3.2. Se vor compila separat modulele programului exemplificat i
apoi cu link-editorul se va obine programul executabil.
Se va construi un fiier de tip Project cu modulele programului
exemplificat.
n continuare se va scrie cte un program modularizat pentru
rezolvarea urmtoarelor probleme:
3.3. Dndu-se forma postfixat a unei expresii aritmetice care
conine numai numere ntregi i operatori +,-,*,/, s se scrie un program
pentru evaluarea sa.
3.4. S se scrie un program pentru calculul c.m.m.d.c. i a c.m.m.m.c
a dou polinoame.
3.5. S se implementeze noiunea de mulime i operaiile permise
asupra sa.
3.6. S se implementeze un editor de texte care s permit cteva
operaii definite de Dvs. (inserarea unui text, tergere, modificare
etc. ..)

53

Lucrarea de laborator nr. 6

POINTERI

1. Coninutul lucrrii
n lucrare se prezint tipul pointer, operaiile permise asupra
pointerilor, modul de alocare i eliberare dinamic a memoriei.
2. Consideraii teoretice
2.1. Tipul pointer
Un pointer este o variabil care are ca valori adrese. Dac pointerul p
are ca valoare adresa de memorie a variabilei x, se spune c p pointeaz spre
x.
p

Adresa din memorie

x
Adresa din memorie 2000
Un pointer este legat de un tip. Dac x este de tipul int, pointerul p
este legat de tipul int.
Declararea unui pointer se face la fel ca declararea unei variabile, cu
deosebirea c numele pointerului este precedat de caracterul *:
tip *nume;
Exemplu:
int *p;

54

Adresa unei variabile se obine cu ajutorul operatorului unar &,


numite operator de refereniere.
Exemplu: Fie declaraiile:
int x;
int *p;
Atunci p=&x; are ca efect atribuirea ca valoare pentru p a adresei
variabilei x. n desenul de mai sus, variabila x fiind localizat la adresa ,
valoarea lui p va fi .
Furnizarea valorii din zona de memorie a crei adres este coninut
n p se face cu ajutorul operatorului unar *, numit operator de
derefereniere.
Exemplu:
a) instruciunea x=y este echivalent cu una din secvenele:
p=&x;
*p=y;

sau

p=&y;
x=*p;

b) instruciunea x++ este echivalent cu secvena:


p=&x;
(*p)++;
n aceste exemple p trebuia s fie legat de tipul lui x,y. De exemplu:
int x,y;
int *p;
Exist cazuri cnd un pointer trebuie s nu fie legat de un tip de date.
n acest caz, se folosete declaraia urmtoare:
void *nume;
n acest caz, dac avem declaraiile:
int x;
float y;
55

void *p;
atunci este corect oricare din instruciunile:
p=&x;
p=&y;
ns este necesar folosirea expresiilor de tip cast, pentru a preciza tipul
datei spre care pointeaz p:
(tip *)p
Observaie: este necesar cunoaterea n fiecare moment a tipului valorii
ce se gsete la adresa atribuit pointerului de tip void *. Neinnd seama
de acest lucru se ajunge la erori.
Exemplu de utilizare a unui pointer de tip void:
int x;
void *p;
Instruciunea x=10 este echivalent cu secvena :
p=&x;
*(int *)p=10;
n esen, dac p este pointer declarat ca void *p, nu poate fi folosit
dereferenierea *p fr a preciza tipul datei referite printr-o expresie de tipul
cast.
2.2. Legtura dintre pointeri i tablouri
Numele unui tablou are drept valoare adresa primului su element.
Ca urmare, se spune c numele unui tablou este un pointer constant,
neputnd fi modificat n timpul execuiei.
Exemplu:

56

int tab[100];
int *p;
int x;
...
p=t; /* p primete ca valoare adresa elementului tab[0] */

n acest exemplu, atribuirea x=tab[0] este echivalent cu


x=*p;
Ca urmare a celor prezentate, rezult c dac un parametru efectiv este un
tablou unidimensional, atunci parametrul formal corespunztor poate fi
declarat n dou moduri:
a) ca tablou: tip nume_parametru_formal[];
b) ca pointer: tip *nume_parametru_formal;
Cele dou declaraii ale parametrului formal sunt echivalente, fiind
corect utilizarea n corpul funciei a construciei de variabil indexat:
nume_parametru_formal [indice];
Acest lucru este ilustrat n exemplul de mai jos, care are drept scop
gsirea maximului i minimului dintre elementele unui ir.
/* Programul L6Ex1.cpp */
/* Programul exemplifica transmiterea parametrului formal
tablou prin pointer */
#include <stdio.h>
#include <conio.h>
void Max_min1(int n,int a[],int *max,int* min)
{
int i;
*max=a[0];
*min=a[0];
for (i=1;i<n;i++)
{
if (a[i]>*max) *max=a[i];
else if (a[i]< *min) *min=a[i];
}
}
57

void Max_min2(int n,int *a,int *max,int *min)


{
int i;
*max=a[0];
*min=a[0];
for (i=1;i<n;i++)
{
if (a[i]>*max) *max=a[i];
else if (a[i]< *min) *min=a[i];
}
}
void main(void)
{
int i,n,maxim,minim;
int x[100];
/* Introducerea datelor */
printf("\nNumarul elementelor tabloului n=");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nx[%d]=",i);
scanf("%d",&x[i]);
};
/* Apelul primei proceduri */
Max_min1(n,x,&maxim,&minim);
printf("\nLa apelul functiei Max_min1 rezulta:\
maximul=%d
minimul=%d\n",maxim,minim);
/* Apelul celei de a doua proceduri */
Max_min2(n,x,&maxim,&minim);
printf("\nLa apelul functiei Max_min2 rezulta:\
maximul=%d minimul=%d\n",maxim,minim);
printf("\nApasati o tasta!\n");
getch();
}
2.3. Operaii asupra pointerilor
Asupra pointerilor sunt permise urmtoarele operaii:
58

a) Incrementare/decrementare cu 1. n acest caz valoarea


pointerului este incrementat/decrementat cu numrul de octei
necesari pentru a pstra o dat de tipul de care este legat
pointerul.
Operatorii folosii sunt ++ i --.
De exemplu:
int tab[100];
int *p;
..
p=&tab[10];
p++; /* Valoarea lui p este incrementat cu 2, avnd adresa
elementului tab[11]*/
b) Adunarea i scderea unui ntreg dintr-un pointer.
Operaia pn are drept efect creterea, respectiv scderea din
valoarea p a n*numrul de octei necesari pentru a pstra o dat de tipul de
care este legat pointerul.
Pentru exemplul de mai sus, dac x este de tipul int, atunci:
x=tab[i];
este echivalent cu:
x=*(tab+i);
c) Diferena a doi pointeri.
Dac 2 pointeri p i q pointeaz spre elementele i i j ale aceluiai
tablou (j>i), adic p=&tab[i] i q=&tab[j], atunci q-p = (j
i)*numrul de actei necesari pentru a pstra o dat de tipul de baz
al tabloului.
d) Compararea a doi pointeri
Doi pointeri care pointeaz spre elementele aceluiai tablou pot fi
comparai folosind operatorii de relaie i de egalitate:
<
<=
>
>=
==
!=
Mai jos este prezentat programul de la paragraful precedent, folosind
operaii asupra pointerilor.
59

/* Programul L6Ex2.cpp */
/* Programul exemplifica folosirea operatiilor
asupra pointerilor */
#include <stdio.h>
#include <conio.h>
void Max_min1(int n,int a[],int *max,int* min)
{
int i;
*max=a[0];
*min=a[0];
for (i=1;i<n;i++)
{
if (a[i]>*max) *max=a[i];
else if (a[i]< *min) *min=a[i];
}
}
void Max_min2(int n,int *a,int *max,int *min)
{
int i;
*max=*a;
*min=*a;
for (i=1;i<n;i++)
{
if (*(a+i)>*max) *max=*(a+i);
else if (*(a+i)< *min) *min=*(a+i);
}
}
void main(void)
{
int i,n,maxim,minim;
int x[100];
/* Introducerea datelor */
printf("\nNumarul elementelor tabloului n=");
scanf("%d",&n);
for(i=0;i<n;i++)
60

{
printf("\nx[%d]=",i);
scanf("%d",&x[i]);
};
/* Apelul primei proceduri */
Max_min1(n,x,&maxim,&minim);
printf("\nLa apelul functiei Max_min1 rezulta:\
maximul=%d minimul=%d\n",maxim,minim);
/* Apelul celei de a doua proceduri */
Max_min2(n,x,&maxim,&minim);
printf("\nLa apelul functiei Max_min2 rezulta:\
maximul=%d minimul=%d\n",maxim,minim);
printf("\nApasati o tasta!\n");
getch();
}
2.4. Alocarea/eliberarea dinamic a memoriei heap
Alocarea memoriei pentru variabilele globale i statice este static,
adic alocarea rmne pn la terminarea programului.
Alocarea memoriei pentru variabilele automatice este dinamic, n
sensul c stiva este curat la terminarea funciei.
Memoria heap este o zon de memorie dinamic, special, distinct
de stiv. Ea poate fi gestionat prin funcii, care au prototipurile n fiierul
alloc.h i stdlib.h
Alocarea unei zone de memorie heap se poate realiza cu ajutorul
funciilor de prototip:
void *malloc (unsigned n);
void *calloc(unsigned nr_elem, unsigned dim);
Funcia malloc aloc n heap o zon contigu de n octei, iar funcia
calloc o zon contigu de nr_elem * dim n octei.
Funciile returneaz:
- n caz de succes, adresa de nceput a zonei alocate
(pointerul fiind de tip void, este necesar conversia spre
tipul dorit);
- n caz de insucces, returneaz zero (pointerul NULL);
61

Eliberarea unei zone alocate cu malloc sau calloc se face cu ajutorul


funciei de prototip:
void free (void *p);
Observaie: Pentru alocri de blocuri mai mari de 64 koctei, este
necesar utilizarea pointerilor de tipul far. n acest caz, funciile de mai sus
au prototipurile:
void far *farmalloc (unsigned long n);
void far *farcalloc(unsigned long nr_elemente, unsigned long
dim);
void farfree (void far *p);
Mai jos se prezint un exemplu de utilizare a funciilor prezentate n
acest paragraf.
/* Programul L6Ex3.cpp */
#include <stdio.h>
#include <alloc.h>
#include <process.h>
#include <conio.h>
void main(void)
{
char *str1,*str2;
/* Aloca memorie pentru primul sir de caractere */
if ((str1 = (char *) malloc(100)) == NULL)
{
printf("Memorie insuficienta\n");
exit(1);
}
printf("\nIntroduceti primul sir de caractere terminat cu
ENTER\n");
gets(str1);
printf("\nSirul de caractere introdus este\n %s\n",str1);

62

/* Aloca memorie pentru al doilea sir de caractere */


if ((str2 = (char *) calloc(100,sizeof(char))) == NULL)
{
printf("Memorie insuficienta\n");
exit(2);
}
printf("\nIntroduceti al doilea sir de caractere terminat cu
ENTER\n");
gets(str2);
printf("\nSirul de caractere introdus este\n %s\n",str2);
printf("\nApasati o tasta\n");
getch();
/* Eliberarea memoriei */
free(str1);
free(str2);
}
2.5. Folosirea ca parametru a unei funcii
Numele unei funcii este un pointer spre funcia respectiv. De
aceea, numele unei funcii poate fi folosit ca parametru efectiv la apelul unei
funcii.
Fie f o funcie care va fi transmis ca parametru efectiv, avnd
antetul:
tipf f(lista_parametrilor_formali_f);
n acest caz, parametrul formal al unei funcii g care va fi apelat cu
parametrul efectiv f, este prezentat n antetul funciei g:
tipg g(, tipf(*p)(lista_parametrilor_formali_f), )
Apelul se va face astfel:
g(,f,..);
Programul L6Ex4.cpp prezint un exemplu n acest sens. Este vorba
de integrarea unei funcii prin metoda trapezului.

63

f (a ) f (b) n 1

f ( x)dx h
f ( a i * h)
2
i 1

unde, n este numrul de subintervale n care s-a mprit intervalul [a,b],


dimensiunea unui subinterval fiind h.
/* Programul L6Ex4.cpp */
/* Programul exemplifica modul de folosire
a unei functii ca parametru */
#include <stdio.h>
#include <conio.h>
#include <math.h>
double f(double x)
{
return (3*x*x +1);
}
double integrala(double a,double b,int n,double(*p)(double x))
/* Calculul integralei prin metoda trapezelor */
{
int i;
double h,s;
h=(b-a)/n;
s=((*p)(a)+(*p)(b))/2.0;
for(i=1;i<n;i++)
s=s+(*p)(a+i*h);
s=s*h;
return s;
}
void main()
{
double a,b;
int n;
char ch;
/* Citirea intervalului de integrare */
printf("\na=");scanf("%lf",&a);
printf("\nb=");scanf("%lf",&b);
ch='D';
64

while (ch=='D' || ch=='d')


{
printf("\nn=");scanf("%d",&n);
printf("\nPentru n=%d Valoarea integralei este %lf",n,
integrala(a,b,n,f));
printf("\nApasati o tasta\n");getch();
printf("\nIntroduceti alt n? DA=D/d NU=alt caracter ");
ch=getch();
}
}
3. Mersul lucrrii
3.1 Se vor executa exemplele din lucrare. Se vor analiza urmtoarele
lucruri:
- folosirea unei variabile indexate, atunci cnd numele tabloului a fost
definit ca pointer n antetul funciei (L6Ex1.cpp);
- operaiile permise asupra pointerilor. Ce avantaj prezint nlocuirea
unei variabile cu indici cu o expresie cu pointeri? (L6Ex2.cpp);
- cum se aloc n memoria heap spaiul de memorie pentru variabile
dinamice? (L6Ex3.cpp).
- care este avantajul transmiterii funciilor ca parametru efectiv
(L6Ex4.cpp).
n continuare se vor scrie programele pentru rezolvarea urmtoarelor
probleme:
3.2. Folosind numai pointeri i expresii cu pointeri se vor scrie
funcii de citire, afiare i nmulire a dou matrice.
3.3. Folosind numai pointeri i expresii cu pointeri se vor scrie
funcii de sortare a unui vector cu elemente reale.
3.4. Folosind numai pointeri i expresii cu pointeri se va scrie o
funcie de interclasare a doi vectori, care conin elemente de tip real
ordonate cresctor.

65

3.5. S se scrie o funcie care sorteaz n ordine cresctoare n iruri


de caractere.
3.6. S se scrie o funcie care determin rdcina unei funcii f(x), n
intervalul [a,b], tiind c admite o singur rdcin n acest interval.
Funcia f va fi transmis ca parametru efectiv.

66

Lucrarea de laborator nr. 7

RECURSIVITATE
1. Coninutul lucrrii
n lucrare este prezentat noiunea de recursivitate, avantajele i
dezavantajele funciilor recursive n raport cu cele nerecursive, pe baza unor
exemple simple.

2. Consideraii teoretice
2.1. Mecanismul recursivitii
Un obiect este recursiv dac este definit prin el nsui. O funcie este
recursiv dac ea se autoapeleaz.
Recursivitatea poate fi:
- direct
- cnd funcia conine un apel direct la ea
nsi;
- indirect - cnd funcia conine un apel al altei funcii,
care la rndul su o apeleaz pe prima.
La fiecare apel al unei funcii, parametrii i variabilele automatice
ale ei se aloc pe stiv ntr-o zon independent. Acest lucru se ntmpl la
fiecare apel sau autoapel al funciei. De aceea datele amintite au valori
distincte la fiecare reapelare Variabilele statice i cele globale ocup tot
timpul aceeai locaie de memorie. Ca urmare, orice modificare asupra lor
se face numai la adresa fixat n memorie, deci ele i pstreaz valoarea de
la un reapel la altul.
Revenirea dintr-o funcie se face n punctul urmtor celui din care
s-a fcut apelul. Adresa de revenire se pstreaz tot n stiv. La revenire,
stiva se reface la starea ei dinaintea apelului, deci variabilele automatice i
parametrii vor reveni la valorile lor dinaintea reapelului respectiv.
O problem important este stoparea autoapelului. De aceea trebuie
s existe o condiie de terminare, fr de care un apel recursiv ar conduce la
67

o bucl infinit. n aplicaiile practice este necesar nu numai ca adncimea


recursivitii sa fie finit, ci s fie relativ mic, deoarece fiecare apel
recursiv necesit alocarea pe stiv a zonei de memorie pentru:
- parametrii funciei;
- variabilele automatice locale funciei;
- adresa de return (revenire n punctul de apel).
Ca urmare, stiva poate crete foarte mult i repede se ajunge la
ocuparea ntregului spaiu de memorie alocat ei.
Un exemplu clasic de proces recursiv este calculul factorialului
definit astfel:
daca

n0

n * fact ( n 1) daca

n0

fact ( n )

Se observ c n definiia funciei fact exist o parte care nu se


definete prin ea nsi i anume fact(n)=1 dac n=0.
n limbajul C/C++, codul funciei corespunztoare este urmtoarea:
double fact(int n)
{
if (n==0) return 1.0;
else return n*fact(n-1)
}
Recursivitatea liniar se caracterizeaz prin faptul c nu pot aprea
pe ramuri diferite ale execuiei programului mai multe apeluri recursive,
adic pe un anumit nivel apare doar un singur apel recursiv.
Recursivitatea liniar ntotdeauna poate fi transformat n iteraie,
ducnd la economie de memorie i timp de calcul (se elimin operaiile de
salvare de context la autoapelurile funciei).
Avantajul principal al recursivitii este scrierea mai compact i mai
clar a funciilor care exprim procese de calcul recursive. n aceast clas
de procese intr cele generate de metodele de cutare cu revenire
(backtracking) i metodele de divizare (divide et impera).

68

2.2. Exemple
2.2.1. Citirea a n cuvinte (iruri de caractere), fiecare terminat
cu spaiu i tiprirea lor n oglind.
/* Programul L7Ex1.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul citeste n cuvinte separate cu spatiu;
(dupa ultimul cuvant va exista spatiu si <ENTER>)
si le afiseaza "in oglinda" */
void revers(void)
{
char c;
scanf("%c",&c);
if (c!='\40') {printf("%c",c);revers();};
printf("%c",c);
}
void main(void)
{
int n,i;
printf("\nNumarul de cuvinte=");
scanf("%d",&n);
for(i=1;i<=n;++i)
{
revers();
printf("\n");
};
printf("\nPROGRAMUL S-A TERMINAT!!!\n");
getch();
}
Funcia revers citete cte un caracter pe care l afieaz pn la
ntlnirea spaiului (terminatorul irului de caractere). Fiecare autoapel
69

conduce la pstrarea n stiv a variabilei locale c. Apariia spaiului conduce


la terminarea apelurilor recursive ale funciei, urmnd scrierea spaiului i a
caracterelor n ordinea invers introducerii lor.
2.2.2. Determinarea termenului minim al unui ir de n ntregi.
/* Programul L7Ex2.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul calculeaza minimul dintr-un sir
cu termeni intregi */
#define NMAX 100
#define MAXIM 32767
int sir[NMAX];
int minim(int x,int y)
{
if (x<=y) return x;
else return y;
}
int termen_minim(int dim_sir)
{
if (dim_sir>=0) return minim(sir[dim_sir],termen_minim(dim_sir-1));
else return MAXIM;
}
void main(void)
{
int i,n;
printf("\nIntroduceti nr de termeni ai sirului n=");
scanf("%d",&n);
printf("\nIntroduceti valorile termenilor\n");
for(i=0;i<n;++i)
{
printf("sir[%d]=",i);
scanf("%d",&sir[i]);
};
printf("\nSIRUL INTRODUS\n");
70

for(i=0;i<n;++i)
{
printf("%6d",sir[i]);
if ((i+1) % 10 == 0) printf("\n");
};
printf("\nCel mai mic termen este %d\n",termen_minim(n-1));
printf("\nApasati o tasta!");
getch();
}

2.2.3. Varianta recursiv i nerecursiv a gsirii valorii celui de al nlea termen al irului lui Fibonacci.
irul lui Fibonacci este definit astfel:
Fib(0)=0; Fib(1)=1;
Fib(n)=Fib(n-1)+Fib(n-2)
/* Programul L7Ex3.cpp */
#include <stdio.h>
#include <conio.h>
/* Numerele lui Fibonacci */
int fib1(int n)
/* VARIANTA RECURSIVA */
{
if (n==0) return 0;
else if (n==1) return 1;
else return (fib1(n-1)+fib1(n-2));
}
int fib2(int n)
/* VARIANTA NERECURSIVA */
{
int i,x,y,z;
if (n==0) return 0;
else if (n==1) return 1;
else {
x=1;y=0;
71

pentru n 2

for(i=2;i<=n;++i)
{
z=x;x=x+y;y=z;
};
return x;
}
}
void main(void)
{
int n;
char ch;
ch='D';
while ((ch=='d')|| (ch=='D'))
{
printf("\nIntroduceti n=");
scanf("%d",&n);
printf("\nCALCUL RECURSIV: fib(%d)=%d\n",n,fib1(n));
printf("\nCALCUL NERECURSIV: fib(%d)=%d\n",n,fib2(n));
printf("\nDoriti sa continuati ? Da=D/d");
ch=getch();
}
}
Apelul recursiv conduce la creterea rapid a stivei, de aceea este
preferabil implementarea nerecursiv.
3.

Mersul lucrrii

3.1. Se vor analiza i executa programele din exemplele de mai sus.


Pentru un caz concret, se va trasa starea stivei, urmrindu-se creterea pe
msura autoapelrii funciei i scderea ei la revenirea din autoapel.
3.2. S se scrie o funcie recursiv i una nerecursiv pentru calculul
valorii polinoamelor Hermite H(x) definite astfel:
H0(x)=1;
H1(x)=2x;
Hn(x)=2nHn-1(x)-2(n-1)Hn-2(x),
pentru n2
3.3. Problema turnurilor din Hanoi
72

Se consider trei tije verticale A,B,C i n discuri de diametre diferite. Iniial


toate discurile sunt puse n tija A, n ordinea descresctoare a diametrului
(discul cel mai mare la baz, iar cel mai mic n vrf). Se cere s se mute
discurile de pe tija A pe tija C folosind tija B ca intermediar, folosind
condiiile:
a) la o manevr se mut un singur disc i anume cel din
vrful unei tije;
b) nu se poate pune un disc de diametru mai mare peste unul
de diametru mai mic;
c) n final, pe tija C, discurile trebuie s fie n aceeai ordine
ca n starea iniial de pe tija A.
3.4.S se scrie un program recursiv care citete n cuvinte i le
afieaz n ordinea invers a introducerii lor.
3.5.S se scrie un program recursiv de generare a produsului
cartezian a n mulimi.
3.6.S se scrie un program de generare recursiv a submulimilor
de k elemente ale mulimii A cu n elemente (combinaiile de n elemente
luate cte k).
3.7. S se scrie un program de rezolvare a problemei celor 8
regine (determinarea tuturor aezrilor pe tabla de ah a celor 8 regine astfel
nct s nu se atace).
3.8.S se genereze recursiv permutrile mulimii A de n elemente.
3.9.Se consider o bar de lungime m i n repere de lungimi l 1,
l2, .... , ln. Din bar trebuie tiate buci de lungimea reperelor date, astfel
nct s rezulte din fiecare reper cel puin o bucat i pierderile s fie
minime.
3.10. Funcia lui Ackermann. S se scrie programul recursiv care
calculeaz funcia lui Ackermann definit astfel:
Ack(0,n)=n+1
Ack(m,0)=Ack(m-1,1)
Ack(m,n)=Ack(m-1,Ack(m,n-1))
73

pentru n N
pentru m N*
pentru m,n N*

74

Lucrarea de laborator nr. 8

IRURI DE CARACTERE

1. Coninutul lucrrii
n lucrare se prezint modul de reprezentare n memorie a unui ir de
caractere i unele funcii standard de prelucrare a irurilor de caracter.

2. Consideraii teoretice
2.1. Reprezentarea n memorie a unui ir de caractere
Un ir de caractere este pstrat ntr-un tablou unidimensional de tip
char. Fiecare caracter se pstreaz ntr-un octet prin codul ASCII al su.
Ultimul caracter al irului, deci terminatorul irului, este caracterul NULL
(\0).
Numele tabloului care pstreaz irul de caractere este un pointer
constant spre irul de caractere.
Exemplu:
char sir []=SIR DE CARACTERE;
n memorie reprezentarea sa va fi (n hexazecimal):
sir

0 1 2

10 11

12 13 14 15 16

53 49 52 20 44 45 20 43 41 52 41 43 54 45 52 45 00
sir are ca valoare adresa zonei de memorie care conine irul.
Avem urmtoarele relaii:
sir[i] unde i [0,16] reprezint codul ASCII al celui de al i-lea
caracter din irul de caractere;

75

sir + i unde i [0,16], reprezint adresa celui de al i-lea caracter din


irul de caractere;
*(sir+i) are acelai efect ca sir[i].
Tot ce s-a explicat mai sus, rmne valabil i n cazul declarrii n
felul urmtor:
char *const sir=SIR DE CARACTERE;
Declararea unui tablou de iruri de caractere se poate face astfel:
char *tab[]={sir_0,sir_1,,sir_n};
n acest caz, tab[i], pentru i [0,n], este un pointer spre irul de
caractere sir_i.
n cazul apelului
printf(%s\n, tab[i]);
se va afia textul sir_i.
2.2. Funcii standard de prelucrare a irurilor de caractere
Funciile standard de citire/scriere a irurilor de caractere:
- gets/puts;
- scanf/printf;
- sscanf/sprintf
au fost prezentate n lucrarea de laborator nr. 1.
n continuare sunt prezentate cteva funcii de prelucrare a irurilor
de caractere, al cror prototip se gsete n fiierul string.h
2.2.1. Lungimea unui ir de caractere
Lungimea unui ir de caractere, fr a fi luat n considerare
caracterul \0, este returnat de funcia strlen, care are prototipul:
unsigned strlen (const char *s);
76

Exemplu:
/* Programul L8Ex1.cpp */
/* Programul exemplifica utilizarea functiei strlen */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define alfa "Apasati o tasta!"
void main(void)
{
char sir1[]="SIR DE CARACTERE";
char *sir2="SIR DE CARACTERE";
int n1,n2,n3;
n1=strlen(sir1);
n2=strlen(sir2);
n3=strlen("SIR DE CARACTERE");
/* Atat n1,cat si n2 si n3 au ca valoare 16 */
printf("\n n1=%d n2=%d n3=%d\n",n1,n2,n3);
printf(%s\n,alfa);
getch();
}
2.2..2. Copierea unui ir de caractere
Copierea unui ir de caractere dintr-o zon de memorie de adres
surs ntr-o alt zon de memorie de adres dest se face cu ajutorul funciei
strcpy, al crei prototip este:
char *strcpy (char *dest, const char *surs);
Se menioneaz c are loc copierea inclusiv a caracterului
NULL(\0).
Funcia returneaz adresa unde a avut loc copierea, adic chiar
destinaia.
77

Pentru a copia cel mult n caractere, din zona de memorie de adres


surs n zona de memorie de adres dest, se va folosi funcia strncpy, al
crei prototip este urmtorul:
char *strncpy (char *dest, const char *surs, unsigned n);
Dup ultimul caracter transferat, trebuie pus caracterul \0.
Evident c dac n > lungimea irului de la adresa surs, atunci are
loc transferarea ntregului ir de caractere.
Exemplu:
/* Programul L8Ex2.cpp */
/* Programul exemplifica utilizarea functiei strcpy */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define alfa "\nApasati o tasta!"
void main(void)
{
char sir1[]="SIR DE CARACTERE";
char *sir2="SIR DE CARACTERE";
char sir3[100],sir4[100],sir5[100];
strcpy(sir3,sir1);
printf("\n sir3 contine: %s\n",sir3);
strcpy(sir4,"Functii standard de prelucrare siruri de caractere");
printf("\n sir4 contine: %s\n",sir4);
strncpy(sir5,sir2,6);/* sir5 contine SIR DE */
sir5[6]='\0';
printf("\n sir5 contine: %s\n",sir5);
printf(alfa);
getch();
}

78

2.2.3. Concatenarea a dou iruri de caractere


Adugarea irului de caractere de la adresa surs dup ultimul
caracter (cel care precede NULL) al irului de caractere de la adresa dest se
face cu ajutorul funciei strcat, care are prototipul:
char *strcat(char *dest, const char *surs);
Dup irul rezultat, se pune evident caracterul NULL (\0). Funcia
retuneaz valoarea adresei destinaie. Exist posibilitatea de a prelua din
irul de caractere de la adresa surs numai n caractere, cu ajutorul funciei
strncat, care are prototipul:
char *strncat (char *dest, const char *sursa, unsigned n);
La sfrit se pune automat caracterul NULL (\0).
Dac n> lungimea irului de la adresa surs, atunci funcia strncat
are acelai efect ca i funcia strcat.
Exemplu:
/* Programul L8Ex3.cpp */
/* Programul exemplifica utilizarea functiei strcat*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define alfa "\nApasati o tasta!"
void main(void)
{
char sir1[100]="SIR1 DE CARACTERE";
char *sir2="<SIR2 DE CARACTERE";
char sir3[100];
strcpy(sir3,sir1);
strcat(sir1,sir2);
printf("\n sir1 contine: %s\n",sir1);
strncat(sir3,sir2,5);
/* Dupa ultimul caracter din sr3 se pune implicit '\0' */
for (int i=0;i<=strlen(sir3)+1;++i) printf("%x",sir3[i]);
79

printf("\n sir3 contine: %s\n",sir3);


printf(alfa);
getch();
}
2.2.4. Compararea a dou iruri de caractere
Compararea a dou iruri de caractere se face caracter cu caracter
(pe baza codurilor ASCII) pn cnd:
- s-a ajuns la un caracter i din primul ir care difer de
caracterul i din al doilea ir;
- s-a ajuns la sfritul unuia din iruri sau a ambelor.
Compararea a dou iruri de caractere de la adresele sir1 i respectiv
sir2 se poate face cu funcia de prototip:
int strcmp(const char *sir1,const char *sir2);
Funcia returneaz:
- o valoare negativ dac irul de caractere de la adresa
sir1 este mai mic dect cel de la adresa sir2;
- zero dac irurile sunt egale;
- o valoare pozitiv, dac irul de la adresa sir1 este mai
mare dect cel de la adresa sir2.
Dac dorim s se compare numai primele n caractere din cele dou
iruri se folosete funcia de prototip:
int strncmp (const char *sir1, const char *sir2, unsigned n);
Dac dorim s nu se fac distincie ntre literele mici i cele mari,
atunci cele dou funcii au drept corespondene:
int stricmp (const char *sir1, const char *sir2);
int strnicmp (const char *sir1, const char *sir2, unsigned n);

80

Exemplu:
/* Programul L8Ex4.cpp */
/* Programul exemplifica utilizarea functiei strcmp*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define alfa "\nApasati o tasta!"
void main(void)
{
char sir1[100]="SIR DE CARACTERE";
char *sir2="SIR de caractere";
int i,j,k,l;
i=strcmp(sir1,sir2);/* i<0 , rezulta sir1<sir2 */
printf("\ni=%d\n",i);
j=strncmp(sir1,sir2,3);/*j=0 ,rezulta ca primele 3 caractere din sir1 si
sir2 sunt egale */
printf("\nj=%d\n",j);
k=stricmp(sir1,sir2); /* k=0, rezulta ca cele 2 siruri sunt egale */
printf("\nk=%d\n",k);
l=strnicmp(sir1,"SIR de 10 caractere",6); /*l=0 */
printf("\nl=%d\n",l);
printf(alfa);
getch();
}

3. Mersul lucrrii
3.1. Se vor analiza i executa programele din lucrare.
3.2. Se va scrie o funcie care s realizeze extragerea dintr-un ir de
caractere surs a unui subir specificat prin poziia n cadrul sursei i a
numrului de caractere extrase.

81

3.3. Se va scrie o funcie pentru inserarea unui ir de caractere surs


ntr-un ir de caractere destinaie, specificnd poziia din care ncepe
inserarea.
3.4. Se va scrie o funcie pentru tergerea unui subir dintr-un ir de
caractere dat. Subirul se va specifica prin poziie i numr de caractere.
3.5. Se va scrie o funcie pentru a verifica dac un ir dat este subir
al unui alt ir de caractere. n caz afirmativ, se va specifica poziia pe care se
regsete pentru prima dat.
3.6. S se scrie dou funcii, una care convertete un numr ntreg
sau real ntr-un ir de caractere, iar cealalt face operaia invers.
3.7. S se scrie un program care citete n iruri de caractere i
afieaz irul cel mai lung i irul cel mai mare alfanumeric.

82

Lucrarea de laborator nr. 9

TIPURILE DE DATE STRUCTUR,


UNIUNE I ENUMERARE

1. Coninutul lucrrii
n lucrare sunt prezentate tipurile definite de utilizator structur,
uniune i enumerare, accesul la componentele lor i asignarea de nume
pentru aceste tipuri.
2. Consideraii teoretice
2.1. Tipul de date "structur"
O structur conine mai multe componente de tipuri diferite
(predefinite sau definite de utilizator), grupate conform unei ierarhii.
Declaraia unei structuri se poate face astfel:
struct

nume

Identificator
variabil
,

83

Lista de
componente

Lista de
componente

tip

identificator

Observaie: n aceasta declaraie nu pot lipsi simultan "nume" i


identificator_variabil.
O variabil structur de tipul "nume" poate fi declarat i ulterior
conform diagramei de mai jos, cu meniunea c cuvntul cheie "struct"
poate lipsi n C++:

struct

nume

Identificator
variabil
,

Exemple echivalente:
a) struct material {
long cod;
char den [30];
char um [10];
real cantitate;
real pret_unit;
} stofa, hartie, motor;
b) struct material{
long cod;
char den [30];
char um [10];
real cantitate;
real pre_unitar;
};
struct material stofa, hartie, motor;
sau
84

material stofa, hartie, motor;


c) struct {
long cod;
char den [30]
char um [10];
real cantitate;
real pret_unitar;
} stofa, hartie, motor;
Accesul la componentele unei structuri se poate face prin procedeul
de calificare:
identificator_variabil.identificator_cmp;
Exemplu:

stofa.den
hartie.cantitate

Procedeul de calificare ptrunde din aproape n aproape n ierarhia structur.


n limbajul C, transmiterea ca parametru a unei structuri la apelul
unei funcii, se face numai prin adresa variabilei de tip structur. De
exemplu:
void f (struct material *p, ...);
Apelul se va face prin:
f(&stofa, ...)
n funcie, selectarea unui cmp se face astfel:
(*p).den
(*p).cantitate
sau nlocuind (*p). prin p-> , ca mai jos:
p->den
p->cantitate
n limbajul C++, o structur poate fi transferat prin parametri n 3
moduri:

85

- direct:
- pointer spre structur:
- referin la structur:

void f (material p, ..)


void f (material *p, ...)
void f (material &p, ...)

O structur de acelai tip se poate atribui direct una alteia:


material alfa, beta;
alfa=beta; {este corect}
2.2. Tipul de date "uniune"
n momente diferite ale execuiei, se pot pstra n aceeai zon de
memorie date de tipuri diferite pentru economisirea memoriei sau din
motive ale concepiei programului. Acest lucru se face grupnd toate datele
care se aloc n aceeai zon de memorie. Structura utilizator obinut se
numete uniune. Sintaxa uniunii este identic cu cea a structurii, singura
deosebire constnd n nlocuirea cuvntului cheie "struct" cu "union" n
diagramele de sintax de la punctul 2.1.
De menionat c zona de memorie rezervat are dimensiunea
componentei care necesit cea mai mult memorie pentru reprezentare.
Accesul la componente se face identic ca la structur.
De menionat c programatorul trebuie s cunoasc n fiecare
moment care dat este reprezentat.
Exemplu:
union alfa
{
char c[5]; /* reprezentare pe 5 octei */
int i;
/* reprezentare pe 2 octei */
long j;
/* reprezentare pe 4 octei */
};
union alfa x;
strcpy(x.c, ABCD);
Variabila x are reprezentarea n hexazecimal, astfel:
41

42

43

44

86

00

Daca se acceseaz componenta x.i, atunci aceasta va avea 4241 n


hexazecimal, adic 16961 n zecimal.
n schimb, aceeai zon de memorie interpretat ca x.j (long) va avea
valoarea 44434241 n hexazecimal, adic 1.145.258.561 n zecimal
2.3. Tipul de date "enumerare"
Tipul enumerare permite programatorului de a folosi nume
sugestive pentru valori numerice. Diagrama de sintax pentru tipul
enumerare este asemntoare cu tipurile structur i uniune. Deosebirea
const n faptul c lista de componente este format numai din identificatori
de valoare ntreag 0,1,2,...:

Tip
enumerare

enum

Identificator
valoare

nume

Identificator
variabil

Exemple echivalente:
a) enum spt {luni, mari, miercuri, joi, vineri, smbt, duminic};
enum spt spt_vacan;
b) enum spt {luni, mari, miercuri, joi, vineri, smbt, duminic}
spt_vacan;

87

c) enum {luni, mari, miercuri, joi, vineri, smbt, duminic} spt_vacan;


Atribuiri posibile:
spt_vacan=vineri;
Identificatorii luni, mari,, au valorile 0,1,.
2.4. Declararea tipurilor de date prin nume simbolice
n limbajul C/C++ se poate atribui un nume simbolic unui tip
predefinit sau unui tip utilizator. Diagrama de sintax pentru asignarea unui
nume simbolic "nume_tip" unui "tip" predefinit sau utilizator este
urmtoarea:

typedef

tip

Nume_tip

Exemplu:
a) typedef struct

{
int i;
float j;
double x;
} ALFA;

ALFA y, z;
b) typedef struct

{
float re;
float im;
} COMPLEX;

COMPLEX x, y;
c) typedef union

{
char x[10];
long cod;
88

} BETA;
BETA u, v;
d) typedef enum {false, true} BOOLEAN;
BOOLEAN k, l;
2.5. Exemple de programe
Programul urmtor prezint operaii asupra numerelor complexe,
folosind tipul structur. Sunt ilustrate toate posibilitile de transmiterea a
parametrilor de tip structur.
/*Programul L9Ex1.cpp */
#include <stdio.h>
#include <conio.h>
#include <process.h>
typedef struct {float re,im;}COMPLEX;
void aduna(COMPLEX *a,COMPLEX *b,COMPLEX *c)
/* transmiterea parametrilor prin pointeri */
{
c->re=a->re+b->re;
c->im=a->im+b->im;
};
void scade(COMPLEX a,COMPLEX b,COMPLEX *c)
/* transmiterea parametrilor prin valoare "posibil numai in C++"
si a rezultatului prin pointer */
{
c->re=a.re-b.re;
c->im=a.im-b.im;
};
void produs(COMPLEX a,COMPLEX b,COMPLEX &c)
/*transmiterea parametrilor prin valoare "posibil numai in C++"
si a rezultatului prin referinta */
{
c.re=a.re*b.re-a.im*b.im;
89

c.im=a.im*b.re+a.re*b.im;
};
void impartire(COMPLEX *a,COMPLEX *b,COMPLEX *c)
/*transmiterea parametrilor prin pointeri */
{
float x;
x=b->re*b->re+b->im*b->im;
if (x==0) {
printf("\nmpartire la zero!\n");
exit(1);
}
else{
c->re=(a->re*b->re+a->im*b->im)/x;
c->im=(a->im*b->re-a->re*b->im)/x;
}
};
void main(void)
/* Operaii asupra numerelor complexe */
{
COMPLEX a,b,c;
char ch,op;
ch='D';
while ((ch=='D')|| (ch=='d'))
{
printf("\nIntroduceti primul numr complex\n");
printf("a.re=");scanf("%f",&a.re);
printf("a.im=");scanf("%f",&a.im);
printf("\nIntroducei al doilea numr complex\n");
printf("b.re=");scanf("%f",&b.re);
printf("b.im=");scanf("%f",&b.im);
aduna(&a,&b,&c);
printf("\n(%f+j*%f)+(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
scade(a,b,&c);
printf("\n(%f+j*%f)-(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
90

produs(a,b,c);
printf("\n(%f+j*%f)*(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
impartire(&a,&b,&c);
printf("\n(%f+j*%f)+(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
printf("\nCONTINUAI?DA=D/d,Nu=alt caracter " );
scanf("%*c%c",&ch);
}
}
Programul urmtor prezint operaii asupra datelor de tipul "union":
/* Programul L9Ex2.cpp */
#include <stdio.h>
#include <conio.h>
#include <string.h>
/* Exemplu de folosire a tipului "union" */
void main()
{typedef union{
char ch[10];
int x;
long y;
float f;
} alfa;
alfa a;
strcpy(a.ch,"ABCDEFGHI");
printf("\nDimensiunea zonei de memorie rezervata =%d octeti\n",
sizeof a);
printf("\nCONTINUTUL ZONEI:\n");
printf("\n-sir de caractere: %s",a.ch);
printf("\n-intreg de tipul int: %d(%x in hexa)",a.x,a.x);
printf("\n-intreg de tipul long: %ld(%lx in hexa)",a.y,a.y);
printf("\n-real de tipul float: %g",a.f);
getch();
}
91

Programul urmator prezinta operatii asupra datelor de tipul "enum".


/* Programul L9Ex3.cpp */
#include <stdio.h>
#include <conio.h>
/* Exemplu de folosire a tipului "enum" */
void main()
{
typedef enum{zero,unu,doi,trei,patru,cinci} NR;
NR x,y;
int z,w;
x=doi; /* x=2 */
y=trei; /*x=3*/
z=x+y;
w=x*y;
printf("\nz=%d w=%d\n",z,w);
getch();
x=2;y=3;/* o astfel de atribuire indica "warning" */
z=x+y;w=x*y;
printf("\nz=%d w=%d\n",z,w);
getch();
}
3. Mersul lucrrii
3.1. Folosind tipul structur pentru o dat curent an, lun, zi, s se
scrie un program pentru a afia a ctea zi din an este ziua respectiv i cte
zile au mai rmas pn la sfritul anului.
3.2. Folosind tipul structur pentru data de natere a D-voastr i
tiind c n anul curent v aniversai ziua de natere n ziua de x [luni,
mari, ..., duminic], scriei un program pentru a afia ziua (din sptmn)
n care v-ai nscut.

92

3.3. S se scrie un program modularizat care citete datele legate de


studenii unei grupe: nume, data naterii, adresa i i afiseaz n ordine
cresctoare lexicografic.
3.4. S se scrie un program pentru calculul valorii unui polinom de
gradul n cu coeficieni compleci pentru o valoare complex. Calculul se va
face cu ajutorul unei funcii.
3.5. S se introduc tipul RAIONAL ca o structur formata din
numrtor i numitor. S se scrie funcii de simplificare, adunare, scdere,
nmulire, mprire, ridicare la putere.
3.6. Folosind tipul uniune, care conine cmpurile necesare pentru a
putea reprezenta un cerc, un dreptunghi, un ptrat, un triunghi, s se scrie o
funcie pentru a calcula aria figurii respective.
3.7. Folosind tipul enumerare, s se introduc tipul boolean. S se
scrie o funcie de ordonare cresctoare a unui ir folosind metoda bulelor i
un semafor de tipul boolean.
3.8. Se citete un ir de caractere format din litere i cifre. S se
indice frecvena de apariie a caracterelor ntlnite n ir folosind o list
ordonat alfabetic (nodul conine caracterul, frecvena i adresa urmtorului
nod).

93

Lucrarea de laborator nr. 10

PRELUCRAREA FIIERELOR
DE CTRE NIVELUL INFERIOR AL S.G.F.

1. Coninutul lucrrii
n lucrare sunt prezentate funciile de prelucrare a fiierelor la
nivelul inferior, adic acelea care fac apel la sistemul de operare. Exemplul
prezentat n lucrare ilustreaz principalele operaii asupra unui fiier:
crearea, adugarea, modificarea i citirea unui fiier.
2. Consideraii teoretice
Fiierul este o colecie ordonat de nregistrri, memorate pe un
suport extern.
Principalele operaii asupra unui fiier sunt:
- deschiderea unui fiier existent;
- crearea unui fiier;
- citirea/scrierea ntr-un fiier;
- poziionarea ntr-un fiier;
- tergerea unui fiier.
Prelucrarea unui fiier se poate face n dou moduri:
a) utiliznd funciile sistemului de operare (nivelul inferior);
b) utiliznd funciile specializate de gestiune a fiierelor (nivelul superior).
Modul de exploatare a unui fiier poate fi:
- secvenial;
- direct.

94

n lucrare sunt prezentate funciile de nivel inferior de prelucrare a


fiierelor.
2.1. Crearea unui fiier nou
Pentru a avea un fiier nou, se utilizeaz funcia creat, care are
urmtorul prototip:
int creat (const char *calea_nume, int mod);
unde:
- calea_nume - este un pointer spre un ir de caractere care definete calea
de nume (path_name) a fiierului care se creeaz;
- mod
- este un ntreg care poate fi definit prin combinarea cu "sau
pe bii" a urmtoarelor drepturi de acces:
S_IREAD
- dreptul de citire;
S_IWRITE - dreptul de scriere.
Funcia returneaz descriptorul de fiier n caz de succes sau -1 n
caz de eroare.
Funcia creat necesit includerile de fiiere:
#include <io.h>
#include <sys/stat.h>
Observaie important: deschiderea n creare a unui fiier existent conduce
la tergerea sa!
Fiierul creat este exploatat n mod text (O_TEXT) sau binar
(O_BINARY), dup valoarea variabilei globale _fmode (implicit are
valoarea O_TEXT).
Exemplu:
_fmode=O_BINARY;
df=creat ("a:\\FIS.BIN,S_IWRITE);

95

2.2. Deschiderea unui fiier existent


Deschiderea unui fiier existent se face cu ajutorul funciei open,
care are urmtorul prototip:
int open (const char *calea_nume, int acces);
unde:
calea_nume - este un pointer spre un ir de caractere care definete calea de
nume a fiierului existent;
acces - este un ntreg care este generat prin combinarea pe bii cu ajutorul
operatorului "sau pe bii " ntre urmtoarele constante:
O_RDONLY - deschiderea pentru READ;
O_WRONLY - deschiderea pentru WRITE;
O_RDWR
- deschiderea pentru READ i WRITE;
O_APPEND - pointerul n fiier va fi fixat pe sfritul de fiier naintea
fiecrei scrieri;
O_TRUNC - dac fiierul exist, el este trunchiat la zero. Drepturile de
acces la fiier rmn neschimbate;
O_BINARY - modul de lucru binar;
O_TEXT
- modul de lucru caracter (implicit).
Observaie: cu ajutorul funciei open, fiierul poate fi creat, caz n
care open are prototipul urmtor:
int open (const char *cale_nume, int acces, unsigned mod);
n acest caz, accesul este o combinaie ntre opiunile prezentate anterior i
urmtoarele:
O_CREAT
O_EXCL

- pentru crearea fiierului;


- pentru a returna eroare n caz c fiierul exist.

Opiunile pentru parametrul mod sunt identice cu cele de la creat.


Fiierele care trebuie incluse sunt:
#include <fcntl.h>
#include <io.h>
Funcia open returneaz descriptorul de fiier sau -1 n caz de eroare.
96

Exemplu:
df=open("C:\\limbaj_c\\FIS.DAT", O_RDWR);
Observaie: numrul fiierelor deschise la un moment dat este limitat de
obicei la 20.
2.3. Citirea dintr-un fiier
Citirea dintr-un fiier existent deschis cu open se face cu ajutorul
funciei read, care are urmtorul prototip:
int read (int df, void *buf, unsigned lungime);
unde:
df
- este descriptorul de fiier returnat de open la deschiderea
fiierului respectiv;
buf
- este pointerul spre zona de memorie n care se pstreaz
nregistrarea citit din fiier;
lungime
- este lungimea n octei a nregistrrii citite.
Fiierul este interpretat ca o succesiune de octei, ncepnd cu zero.
Dup fiecare citire, indicatorul din fiier indic octetul cu care ncepe citirea
urmtoare.

EOF
1 2 3 4

Sfrit de fiier

indicator

La deschidere cu O_RDONLY sau O_RDWR, indicatorul este


poziionat pe octetul 0.
Funcia read returneaz n caz de succes numrul de octei efectiv
citii, iar n caz de eroare returneaz -1, felul erorii fiind dat de variabila
97

extern errno. n caz de ntlnire a sfritului de fiier (CTRL/Z), funcia


read returneaz valoarea zero.
Fiierul standard de intrare are descriptorul de fiier zero.
Funcia read necesit includerea fiierului io.h.
Exemplu. Citirea a 20 de octei din fiierul FIS.DAT aflat in directorul
curent:
df=open ("FIS.DAT", O_RDONLY);
n=read (df, adr, 20);
2.4. Scrierea ntr-un fiier
Scrierea ntr-un fiier deschis cu open sau cu creat se face cu ajutorul
funciei write, care are ca prototip:
int write (int df, void *buf, unsigned lungime);
unde:
df
- este descriptorul de fiier returnat de funcia open sau creat;
buf
- este pointerul spre zona de memorie din care se preia
nregistrarea care se scrie n fiier;
lungime
- este numrul de octei de scris.
Funcia returneaz numrul de octei efectiv scrii sau -1 n caz de
eroare.
Funcia write implic includerea fiierului io.h.
Funcia write poate fi folosit pentru scrierea n fiierul standard,
care are df=1;
Exemplu: Scrierea n fiierul FIS.DAT din directorul curent a 20 de
octei de la adresa adr:
df=creat ("FIS.DAT", S_IWRITE);
n=write (df,adr,20);

98

2.5. Poziionarea ntr-un fiier


n cazul n care se dorete citirea sau scrierea de la o anumit poziie
dintr-un fiier pe suport magnetic, se utilizeaz funcia lseek, care are
prototipul:
long lseek (int df, long increment, int origine);
unde:
df
- este descriptorul de fiier deschis;
increment
- numrul de octei peste care se va poziiona indicatorul n
fiier, innd cont de parametrul origine;
origine
- are una din valorile:
0 - incrementul se consider fa de nceputul fiierului;
1 - incrementul se consider fa de poziia curent a indicatorului de
fiier;
2 - incrementul se consider fa de sfritul fiierului.
Funcia returneaz deplasamentul rezultat fa de nceputul fiierului sau -1
n caz de eroare. Utilizarea funciei necesit includerea fiierului io.h.
Exemple:
a) poziionarea indicatorului la nceputul fiierului:
lseek(df,0l,0);
b) poziionarea indicatorului la sfritul fiierului, caz utilizat pentru
adugarea de noi nregistrri n fiier :
lseek (df, 0l, 2)
2.6. nchiderea unui fiier
Dup terminarea prelucrrii unui fiier, acesta se nchide apelnd
funcia close, care are prototipul:
int close(int df);
df fiind descriptorul fiierului.
Funcia returneaz zero n caz de succes sau -1 n caz de eroare.
Folosirea funciei necesit includerea fiierului io.h.

99

2.7. Exemplu
n programul urmtor sunt ilustrate urmtoarele operaii asupra unui
fiier:
- crearea fiierului;
- adugarea de noi nregistrri;
- modificarea unor nregistrri. n acest caz se poziioneaz indicatorul n
fiier pe nceputul nregistrrii i se scrie noua nregistrare;
- citirea i afiarea coninutului fiierului;
- sortarea fiierului, avnd drept cheie media, un cmp din nregistrare.
ntruct numrul nregistrrilor unui fiier este mare, s-au citit iniial
nregistrrile din care s-au extras cheile de sortare, reinndu-se numrul de
ordine al nregistrrilor i se ordoneaz n memoria interna. Apoi se obine
fiierul sortat.
/* Programul L10Ex1.cpp */
#include <stdio.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <stdlib.h>
/* Exemplu de utilizare a fiierelor */
typedef struct{
char nume[32];
float media;
/*alte informaii */
} STUDENT;
typedef union {
STUDENT stud;
char st[sizeof(STUDENT)];
} BUF;
typedef struct {
int nr;
float med;
} ELEMENT;
100

void sortare(char nume_fis[],char nume_fis_sortat[])


{
ELEMENT el,t[100];
int k,j,n,i,df1,df2;
BUF stu;
j=0;
df1=open(nume_fis,O_RDONLY);
while (read(df1,stu.st,sizeof(STUDENT))>0)
{
t[j].nr=j;
t[j].med=stu.stud.media;
j=j+1;
};
/* Sortarea tabloului t dup medie */
n=j-1;/* Elementele tabloului t sunt 0,1,2,...,n */
j=0;
do
{
k=1;j=j+1; /*k=TRUE*/
for(i=0;i<=n-j;i++)
if (t[i].med > t[i+1].med)
{
el=t[i];t[i]=t[i+1];t[i+1]=el;
k=0;/*k=FALSE */
};
}
while(k==0);
close(df1);
/*Crearea fiierului sortat */
df2=creat(nume_fis_sortat,S_IWRITE|S_IREAD);
df1=open(nume_fis,O_RDONLY);
for(i=0;i<=n;i++)
{
lseek(df1,(long)(t[i].nr * sizeof(STUDENT)),0);
read(df1,stu.st,sizeof(STUDENT));
write(df2,stu.st,sizeof(STUDENT));
};
close(df1);
101

close(df2);
}
void afisare( char nume_fis[])
{
BUF stu;
int j,df1;
j=0;
df1=open(nume_fis,O_RDONLY);
while (read(df1,stu.st,sizeof(STUDENT))>0)
{
printf("\n%d %-32s %7.2f", j, stu.stud.nume,
stu.stud.media);
j=j+1;
};
close(df1);
}
void main()
{
int i,n,m,df1;long l;
char ch;
BUF stu;
char nume_fis[50]="c:\\ignat\\Limbaj_C\\grupa.dat";
char nume_fis_sortat[50]="c:\\ignat\\Limbaj_C\\grupasort.dat";
printf("\nNr.studentilor de introdus n=");
scanf("%d",&n);
/*crearea fiierului */
if ((df1=creat(nume_fis,S_IWRITE|S_IREAD))==-1)
{
printf("Nu se poate crea fiierul\n");
exit(1);
}
/* Introducerea datelor despre studenti */
for(i=1;i<=n;i++)
{
printf("\nNumele studentului: ");
scanf("%*c");
102

gets(stu.stud.nume);
printf("\nMedia=");
scanf("%f",&stu.stud.media);
write(df1,stu.st,sizeof(STUDENT));
};
close(df1); /* nchiderea fiierului */
/*Adugarea de noi articole in fiier */
printf("\nNr.studentilor de adaugat m=");
scanf("%d",&m);
df1=open(nume_fis,O_RDWR);
lseek(df1,0l,2);
for(i=1;i<=m;i++)
{
printf("\nNumele studentului adugat: ");
scanf("%*c");
gets(stu.stud.nume);
printf("\nMedia=");
scanf("%f",&stu.stud.media);
write(df1,stu.st,sizeof(STUDENT));
};
close(df1); /*nchiderea fiierului */
printf("\n FIIERUL DUPA CREARE\n");
afisare(nume_fis);
/* Modificarea datelor din fiier */
printf("\n Modificati? DA=D/d NU= alt caracter ");
scanf("%*c%c",&ch);
df1=open(nume_fis,O_RDWR);
while((ch=='D')||(ch=='d'))
{
printf("Nr.de ordine al studentului =");
scanf("%d%*c",&i);
l=lseek(df1,(long)(sizeof(STUDENT) *i),0);
printf("depl=%ld pentru i=%d\n",l,i);
read(df1,stu.st,sizeof(STUDENT));
printf("\nNumele vechi este:%s\n",stu.stud.nume);
printf("\nNumele modificat:");
gets(stu.stud.nume);
printf("\n Media veche este: %f",stu.stud.media);
103

printf("\nMedia modificat=");
scanf("%f",&stu.stud.media);
l=lseek(df1,(long)(sizeof(STUDENT) *i),0);
printf("depl=%ld pentru i=%d\n",l,i);
write(df1,stu.st,sizeof(STUDENT));
printf("\n Mai modificati? DA=D/d NU=alt caracter ");
scanf("%*c%c",&ch);
}
close(df1);
printf("\nCONINUTUL FISIERULUI NESORTAT\n");
afisare(nume_fis);
getch();
printf("\nCONINUTUL FISIERULUI SORTAT\n");
sortare(nume_fis,nume_fis_sortat);
afisare(nume_fis_sortat);
getch();
}
3. Mersul lucrarii
3.1. Se va executa i analiza programul L10Ex1.cpp
3.2. Se citete de la tastatur un text care se scrie ntr-un fiier
"text.dat". S se afieze apoi coninutul fiierului, fiecare linie fiind
precedat de numrul de ordine al ei.
3.3. De la tastatur se citesc partea real i partea imaginar pentru n
numere complexe. S se creeze un fiier care conine numerele complexe
citite, fiecare numr avnd partea real, partea imaginar, modulul i
argumentul su.
3.4. Dou firme i pstreaz informaiile referitoare la stocul de
mrfuri (cod produs, denumire, cantitate, pre unitar) n fiierele
"marfa1.dat" i respectiv "marfa2.dat", ordonate cresctor dup cod. Prin
fuzionarea celor dou firme, rezult un stoc comun care trebuie memorat n
fiierul "marfa.dat", ordonat dup cod.
a) S se creeze fiierele iniiale, pe baza datelor introduse de la
tastatur i apoi s se creeze fiierul de stoc comun "marfa.dat" Pentru
mrfuri cu cod comun, se consider c denumirea i preul unitar corespund.
104

b) Fiierul "marfa.dat" se va parcurge secvenial, tiprind pentru


fiecare component denumirea i cantitatea.
c)Pentru o component dorit dat prin numrul de ordine, se va
modifica direct preul su unitar.
3.5. S se scrie programul pentru concatenarea a dou sau mai multe
fiiere ce conin numere reale. Se va tipri informaia din fiierul rezultat.

105

Lucrarea de laborator nr. 11.

PRELUCRAREA FIIERELOR
DE CTRE NIVELUL SUPERIOR AL S.G.F.

1. Coninutul lucrrii
n lucrare sunt prezentate funciile de prelucrare a fiierelor de nivel
superior, utiliznd structuri speciale de tip FILE. Principalele operaii care
se pot efectua asupra fiierelor la acest nivel sunt: crearea, deschiderea,
citirea/scrierea unui caracter sau a unui ir de caractere, citirea/scrierea
binar a unui numr de articole, poziionarea ntr-un fiier, nchiderea unui
fiier, vidarea zonei tampon a unui fiier.
2. Consideraii teoretice
La acest nivel, fiecrui fiier i se ataeaz un pointer la o structur de
tip FILE:
FILE *p;
Tipul FILE i toate prototipurile funciilor de prelucrare se gsesc n
fiierul stdio.h
2.1.

Deschiderea unui fiier

Deschiderea unui fiier existent, precum i crearea unui fiier nou se


face cu ajutorul funciei fopen, care are urmtorul prototip:
FILE *fopen(const char *cale_nume, const char *mod);
unde:
o cale_nume este un pointer spre un ir de caractere care definete
calea de nume a fiierului;
106

o mod este un pointer spre un ir de caractere care definete modul


de prelucrare a fiierului deschis, dup cum urmeaz:
r - deschidere n citire (read);
w - deschidere n scriere (write);
a
- deschidere pentru adugare (append);
r+ - deschidere n citire/scriere (modificare);
rb - citire binar;
wb - scriere binar;
r+b - citire/scriere binar;
w+b - citire/scriere binar;
ab adugare de nregistrri n modul binar.
Coninutul unui fiier existent deschis n scriere w , va fi ters, el
considerndu-se deschis n creare.
Dac fiierul este deschis n modul a, se vor putea aduga noi
nregistrri dup ultima nregistrare existent n fiier.
Un fiier inexistent deschis n modul w sau a va fi creat.
Funcia fopen returneaz un pointer spre tipul FILE n caz de succes
sau pointerul nul n caz de eroare.
Fiierele standard de I/E sunt deschise automat la lansarea
programului; pentru ele, pointerii spre tipul FILE sunt:
stdin intrare standard;
stdout ieire standard;
stderr ieire standard erori;
stdprn ieire paralel (imprimant);
stdaux comunicaie serial.
2.2.

Prelucrarea pe caractere a unui fiier

Un fiier poate fi prelucrat, n citire sau scriere, caracter cu caracter,


folosind funciile getc i putc, ale cror prototipuri sunt:
int getc (FILE *pf);
int putc (int ch, FILE *pf);
n care:
pf este pointerul spre tipul FILE returnat de funcia fopen;
ch este codul ASCII al caracterului care se scrie.
107

Funcia getc returneaz codul ASCII al caracterului scris. n caz de


eroare ambele returneaz 1.
De exemplu, secvena de copiere a intrrii standard la ieirea standard
este:
while ((c=getc(stdin))!=EOF)
putc(c, stdout);
2.3.

Citirea/scrierea unui ir de caractere

Citirea dintr-un fiier a unui ir de caractere se face cu ajutorul


funciei fgets, care are prototipul:
char *fgets(char *s, int n, FILE *pf);
n care:
s este pointerul spre zona din memorie unde are loc pstrarea
irului de caractere;
n este numrul de octei a zonei n care se citesc caracterele din
fiier. Citirea se oprete la ntlnirea caracterului \n sau citirea a cel mult
n-1 caractere. Ultimul caracter n ambele cazuri va fi \0.
pf este pointerul spre tipul FILE.
Funcia returneaz valoarea pointerului s. La ntlnirea sfritului de
fiier funcia returneaz valoarea zero.
Scrierea unui ir de caractere (inclusiv caracterul \0) se face cu
funcia fputs, care are prototipul:
int fputs (const char *s, file *pf);
unde s este pointerul spre nceputul zonei de memorie care conine irul de
caractere care se scrie n fiier.
Funcia fputs returneaz codul ASCII al ultimului caracter scris n
fiier sau 1 n caz de eroare.
2.4.

Citirea/scrierea cu format

Citirea/scrierea cu format se poate face cu ajutorul funciilor


fscanf/fprintf, similare cu funciile sscanf/sprintf, prezentate n lucrarea

108

L1., deosebirea constnd n faptul c n cadrul funciilor sscanf/sprintf se


precizeaz ca prim parametru pointerul zonei unde se pstreaz irul de
caractere, iar n cadrul funciilor fscanf/fprintf se precizeaz ca prim
parametru pointerul spre tipul FILE, aa cum reiese din prototipurile lor:
int fscanf(FILE *pf, const char *format,[adresa,]);
int fprintf(FILE *pf, const char *format,[adresa,]);
Funcia fscanf returneaz numrul de cmpuri citite corect; la
ntlnirea sfritului de fiier funcia returneaz valoarea EOF.
Funcia fprintf returneaz numrul caracterelor scrise n fiier sau 1
n caz de eroare.
2.5.

Vidarea zonei tampon a unui fiier

Vidarea zonei tampon a unui fiier se face cu ajutorul funciei fflush,


avnd prototipul urmtor:
int fflush(FILE *pf);
unde pf este pointerul spre tipul file.
Dac fiierul e deschis n scriere, coninutul zonei tampon se scrie n
fiierul respectiv.
Dac fiierul e deschis n citire, caracterele necitite se pierd.
Funcia returneaz zero n caz de succes i 1 n caz de eroare.
2.6.

Poziionarea ntr-un fiier

Poziionarea ntr-un fiier pe un anumit octet se poate face cu ajutorul


funciei fseek, care are prototipul:
int fseek (FILE *pf, long increment, int origine);
Aceast funcie este similar cu lseek, deosebirea constnd n faptul
c la fseek se precizeaz pointerul spre tipul FILE, iar la lseek se precizeaz
descriptorul de fiier.
Poziia curent a indicatorului intr-un fiier dat prin deplasamentul n
octei fa de nceputul su este returnat de ctre funcia ftell de prototip:

109

long ftell(FILE *pf);


2.7.

Prelucrarea fiierelor binare

n acest caz, fiierele sunt considerate ca o succesiune de nregistrri,


fiecare nregistrare coninnd un numr de articole, ca n figura urmtoare:
ARTICOL

ARTICOL

.......

ARTICOL

ARTICOL

nregistrare

ARTICOL

ARTICOL

EOF

nregistrare

Articolele sunt de lungime fix. Un articol este o dat de un tip


predefinit sau definit de utilizator.
Citirea, respectiv scrierea unei nregistrri se face cu ajutorul funciilor
fread i fwrite, care au prototipurile:
unsigned fread(void *buf, unsigned dim, unsigned nrart, FILE *pf);
unsigned fwrite(void *buf, unsigned dim, unsigned nrart, FILE *pf);
unde:
buf este pointerul spre zona tampon care conine articolele
citite, respectiv cele care se scriu;
dim este dimensiunea unui articol n octei;
nrart numrul articolelor dintr-o nregistrare;
pf este pointerul spre tipul FILE.
Funciile returneaz numrul articolelor citite, respectiv scrise n caz
de succes, sau 1 n caz de eroare.
2.8.

nchiderea unui fiier

nchiderea unui fiier se realizeaz cu ajutorul funciei fclose, care are


prototipul:
int fclose(FILE *pf);
unde pf este pointerul spre tipul FILE returnat de fopen.
Funcia returneaz 0 n caz de succes i 1 n caz de eroare.

110

2.9.

tergerea unui fiier

Un fiier nchis poate fi ters cu ajutorul funciei unlink, care are


prototipul:
int unlink (const char *cale_nume);
unde cale_nume este un pointer spre un ir de caractere care red calea de
nume a fiierului.
Funcia returneaz 0 n caz de succes i 1 in caz de eroare.
2.10. Exemple
Exemplul 1
n programul L11Ex1.cpp este creat un fiier caracter cu caracter,
citite de la tastatur. Apoi este ilustrat modul de adugare la sfritul
fiierului ,de data aceasta, a unor iruri de caractere. La sfrit fiierul este
listat linie cu linie, cu numerotarea lor.
/* Programul L11Ex1.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul ilustreaz prelucrarea fisierului
pe caractere si siruri de caractere */
void main(void)
{
char ch,s[100],nume_fis[50]="c:\\fis1.txt";
int i;
FILE *pf;
/* crearea fiierului; scrierea caracterelor inclusiv
'/n'introduse de la tastatura */
pf=fopen(nume_fis,"w");
printf("\nIntroduceti textul!\n");
while ((ch=getc(stdin))!=EOF)
{
putc(ch,pf);
}
fclose(pf);
/*Adaugarea de siruri de caractere*/
111

pf=fopen(nume_fis,"r+");
fseek(pf,0l,2);
printf("\nINTRODUCETI sirurile de caractere care se
adauga terminate cu ENTER \n");
while(fgets(s,100,stdin)!=(char*)0)
{
fputs(s,pf);
}
fclose(pf);
/*Afisarea continutului */
printf("\nCONTINUTUL FISIERULUI cu NUMEROTAREA
LINIILOR\n");
i=0;
pf=fopen(nume_fis,"r");
while(fgets(s,100,pf)!=(char *)0)
{printf("%d %s",i,s);
i++;
}
fclose(pf);
getch();
unlink(nume_fis);
}
Exemplul 2
Programul L11Ex2.cpp ilustreaz modul de prelucrare binar a unui
fiier. Programul conine crearea fiierului i afiarea coninutului
su.
/* Programul L11Ex2.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul ilustreaza prelucrarea binara a unui fisier */
typedef struct {
char nume[40];
long suma;
/*alte componente */
} ARTICOL;
void afisare(char *nume_fis)
112

{
FILE *pf;
ARTICOL buf;
int i;
pf=fopen(nume_fis,"rb");
printf("\nNR.CRT. SUMA NUMELE-PRENUMELE\n");
i=0;
while(fread(&buf,sizeof(ARTICOL),1,pf)>0)
{
printf("\n%6d %10ld
%-40s",i,buf.suma,buf.nume);
i++;
}
fclose(pf);
}
void main(void)
{
FILE *pf;
ARTICOL buf;
int i,n;
char s[40],nume_fis[40]="c:\\fis.dat";
/*Crearea fisierului */
printf("\nIntroduceti nr persoanelor n=");
scanf("%d",&n);
pf=fopen(nume_fis,"wb");
for(i=1;i<=n;i++)
{
fflush(stdin);
printf("Numele persoanei: ");
fgets(buf.nume,40,stdin);
printf("Suma = ");
scanf(" %ld",&buf.suma);
fwrite(&buf,sizeof(ARTICOL),1,pf);
}
fclose(pf);
printf("\nCONTINUTUL FISIERULUI\n");
afisare(nume_fis);
getch();
}
113

3. Mersul lucrrii
e
f

3.1. Se vor analiza i executa exemplele L11Ex1.cpp i L11Ex2.cpp.

3.2 S se creeze un fiier care s conin produsele unui magazin.


Un produs este reprezentat printr-o structur ce conine codul produsului,
denumirea, unitatea de msur, cantitatea, preul unitar.
Plecnd de la acest fiier, s se obin un fiier sortat dup cod.
3.3. Avnd creat fiierul sortat la punctul 3.2. se vor scrie funcii de
intrare i de ieire a produselor magazinului
3.4. Se va scrie un program pentru admiterea la facultate n anul I.
Programul va cuprinde crearea fiierului cu candidaii nscrii. n final
trebuie s se obin fiierele cu candidaii admii pe secii i cei respini pe
baza mediei obinute ((bacalaureat + 2 * test_matem) / 3.0).
3.5. Se consider un director de fiiere. Fiecare intrare n director
conine numele (8 caractere) i extensia (3 caractere) fiierului, numrul de
blocuri alocate pentru el, adresa primului bloc alocat, data i ora ultimei
actualizri. (zi, luna, an, ora, minut, secunda).
Se cere:
a) crearea directorului de fiiere;
b) afiarea directorului n ordine alfabetic a numelor
fiierelor;
c) afiarea directorului n ordine cresctoare a datei i orei
ultimei actualizri.

114

115

BIBLIOGRAFIE

1. V.Cristea, E.Kalisz, I.Atanasiu, V.Iorga. Tehnici de programare.


Ed.Teora, Bucureti, 1995.
2.
V.Ddrlat, I.Ignat, M.Topan, L.Petrescu. Programarea
calculatoarelor. Structuri de date i algoritmi. Litografia U.T.C.N.,
1995.
3. I.Ignat, V,Ddrlat, M.Topan, L.Petrescu.. Turbo Pascal 7.0.
Fundamente i aplicaii. Ed.Albastr, Cluj-Napoca, 1996.
4. I.Ignat, V.Ddrlat, I.Rus, A.Kacso. Programarea sistematic n
Turbo Pascal 6.0. Ed. Crii de Stiin, Cluj-Napoca, 1992.
5. L.Livovschi, H.Georgescu. Analiza i sinteza algoritmilor. Ed.
Enciclopedic, Bucureti, 1986.
6. L.Negrescu. Limbajele C i C++ pentru nceptori, Vol. 1 i 2. Ed.
Microinformatica, Cluj_Napoca, 1994 (reeditare 2000).
7. L.D.Serbnai, V.Cristea, F.Moldoveanu, V.Iorga. Programarea
sistematic n limbajele Pascal i Fortran. Ed.Tehnic, Bucureti, 1984.
8. N.Wirth. Algorithms + Data Structures = Programs.Prentice Hall,
1978.

116

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