Sunteți pe pagina 1din 206

Cuprins

next

up

previous

Next: Introducere. Operatori. Expresii. Up: carte Previous: carte

Cuprins

Introducere. Operatori. Expresii.

Primul program n C. Structura generala a unui program C

Comparatie C - Pascal

Variabile. Operatori. Expresii

Probleme propuse

Functii. Functii de biblioteca

Functii definite de utilizator

Functii de biblioteca

Operatii aritmetice, expresii si operatori specifici limbajului C

Functii de intrare-iesire

Functii matematice

Functii de conversie

Exemple rezolvate

Probleme propuse

Operatii la nivel de bit

Operatori la nivel de bit

Utilizarea operatorilor

Probleme rezolvate

Probleme propuse

Caractere, siruri de caractere. Tablouri

Operatii cu caractere

Tablouri unidimensionale

Siruri de caractere

Observatii asupra sirurilor de caractere

http://labs.cs.utt.ro/labs/pc/html/node1.html (1 of 4) [22.07.2003 16:17:59]

Cuprins

Probleme rezolvate

Probleme propuse

Prelucrarea fisierelor

Tratarea fisierelor n C

Operatii asupra fisierelor


Deschiderea/nchiderea fisierelor

Alte functii referitoare la fisiere

Citirea si modificarea indicatorului de pozitie

Transferul caracterelor si al sirurilor de caractere

Citirea si scrierea cu format

Probleme rezolvate

Probleme propuse

Compilarea independenta a fisierelor

Etapele compilarii unui program C

Preprocesarea

Compilarea

Link-editare

Structurarea programelor C pe mai multe fisiere

De ce mai multe fisiere ?

Reguli de structurare pe mai multe fisiere

Lucrul n modul "project"

Tipuri de date abstracte

Definirea tipului abstract stiva

Evaluarea unei expresii n notatie poloneza

Probleme propuse

Pointeri

Introducere

Operatii cu pointeri

Pointeri ca argumente ale functiilor

Pointeri si tablouri

http://labs.cs.utt.ro/labs/pc/html/node1.html (2 of 4) [22.07.2003 16:17:59]

Cuprins

Pointeri la functii

Folosirea neadecvata a operatiilor cu pointeri

Problema rezolvata

Problema propusa

Liste liniare simplu nlantuite

Aspecte ale implementarii listelor liniare

Problema rezolvata

Comentarea programului

Problema propusa

Implementarea listelor multiplu nlantuite

Problema rezolvata

Sursa programului

Comentarea programului

Problema propusa

Tipul abstract arbore binar ordonat

Codul sursa

Liste liniare multiplu nlantuite

Arbori binari

Cautarea n arbori binari ordonati

Inserarea n arbori binari ordonati

Stergerea n arbori binari ordonati

Parcurgerea arborilor binari

Problema rezolvata

Sursa programului

Comentarea programului

Problema propusa

Probleme propuse spre rezolvare

Setul 1

Setul 2

http://labs.cs.utt.ro/labs/pc/html/node1.html (3 of 4) [22.07.2003 16:17:59]

Cuprins

Bibliografie

About this document ...

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node1.html (4 of 4) [22.07.2003 16:17:59]

Introducere. Operatori. Expresii.

next

up

previous

contents

Next: Primul program n C. Up: carte Previous: Cuprins Cuprins

Introducere. Operatori. Expresii.


Subsections
Primul program n C. Structura generala a unui program C

Comparatie C - Pascal

Variabile. Operatori. Expresii

Operatii aritmetice, expresii si operatori specifici limbajului C

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node2.html [22.07.2003 16:18:00]

Primul program n C. Structura generala a unui program C

next

up

previous

contents

Next: Comparatie C - Pascal Up: Introducere. Operatori. Expresii. Previous: Introducere. Operatori.
Expresii. Cuprins

Primul program n C. Structura generala


a unui program C
Toate programele scrise n limbajul C au n comun mai multe elemente esentiale.
Pentru nceput, vom urmari aceste elemente studiind cteva programe simple.
Unul dintre programele "clasice" prezentate ca introducere n mare parte a
literaturii de specialitate este Hello, World !:

#include <stdio.h>
void main(void)
{
printf("Hello, World !\n");
}

Dupa compilarea si rularea acestui program, pe ecran va fi afisat:


Hello, World !

Orice program scris n C respecta o anumita "compozitie", toate programele au n


comun o anumita structura. Astfel, orice program C este alcatuit din functii care
contin instructiuni. Dintr-o perspectiva generala, un program are structura:
directive preprocesor
http://labs.cs.utt.ro/labs/pc/html/node3.html (1 of 2) [22.07.2003 16:18:01]

Primul program n C. Structura generala a unui program C

declaratii si definitii globale


functii

Pentru exemplul anterior, prima linie:


#include <stdio.h>

este o directiva preprocesor. Aceste directive au ntotdeauna ca si prim caracter


simbolul #. Directiva include are ca efect includerea n program a fisierului
header stdio.h. Acest mecanism de includere permite programatorului sa
foloseasca functii gata implementate si puse la dispozitie prin intermediul
bibliotecilor de functii. Includerea fisierelor header (adica fisiere antet care contin
declaratiile functiilor de biblioteca) se executa de catre compilator n faza de
preprocesare, o prima faza a compilarii n care au loc diferite operatii asupra
codului sursa nainte ca acesta sa fie efectiv compilat.
Urmatoarea linie cu care se continua executia programului este functia main.
Orice program C este compus din functii, dintre care functia main are o
semnificatie speciala, aceasta fiind functia care se executa la lansarea
programului. n acest caz, functia main nu are parametri si nu returneaza nici un
rezultat, fapt marcat prin tipul void, adica tipul vid, un tip de date particular
limbajului C (mai multe despre functii si modul n care se transmit parametri si se
returneaza valori, n capitolul urmator). Corpul functiei main (si al oricarei
functii) este cuprins ntre acolade, care n C sunt delimitatori de bloc (echivalent
cu begin - end din Pascal). Corpul functiei n acest exemplu contine o singura
instructiune:
printf("Hello, World !\n");

n aceasta linie de program se apeleaza functia printf, apartinnd bibliotecii stdio


si are ca actiune afisarea valorilor transmise ca parametru. n acest caz,
parametrul este sirul de caractere "Hello, World ! $\backslash$
n". Caracterul $\backslash$
n reprezinta
caracterul linie noua.
next

up

previous

contents

Next: Comparatie C - Pascal Up: Introducere. Operatori. Expresii. Previous: Introducere. Operatori.
Expresii. Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node3.html (2 of 2) [22.07.2003 16:18:01]

Comparatie C - Pascal

next

up

previous

contents

Next: Variabile. Operatori. Expresii Up: Introducere. Operatori. Expresii. Previous: Primul program n
C. Cuprins

Comparatie C - Pascal
n general, majoritatea celor care nvata limbajul C sunt familiarizati cu Pascal,
motiv pentru care prezentam n tabelul 1.1 o comparatie ntre principalele
elemente diferite ale celor doua limbaje.
Tabela 1.1: Exemplificari ale diferentei ntre Pascal si C
Element

n Pascal

n C

declarare
variabile

var nume_var : tip ;

tip nume_var ;

integer

int

real

double sau float

tipuri

fundamentale boolean

nu exista, se foloseste 0
si 1

string

se folosesc tablouri
(char[]) sau pointeri
(char *)

tipul tablou

array[min..max] of tip

tip[lung_tablou]

alte tipuri

record

struct sau union

set of

nu exista

while conditie do

while (conditie)

sintaxa unor

if conditie then

if (conditie)

instructiuni

for v:= min to max do

for (v=min; v $<$max;


v++)

case

switch

:=

http://labs.cs.utt.ro/labs/pc/html/node4.html (1 of 2) [22.07.2003 16:18:01]

Comparatie C - Pascal

=
operatori

$<>$

AND OR NOT

modulo

next

up

==
!=

&& $\vert\vert$
!
%

subprograme functii si proceduri

doar functii

operatii de
I/O

instructiuni: readln,
writeln, ...

functii de biblioteca:
printf, scanf, ...

delimitatori
de bloc

begin ...end

{ ...}

comentarii

{ ...}

/* ...*/

previous

contents

Next: Variabile. Operatori. Expresii Up: Introducere. Operatori. Expresii. Previous: Primul program n
C. Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node4.html (2 of 2) [22.07.2003 16:18:01]

Variabile. Operatori. Expresii

next

up

previous

contents

Next: Operatii aritmetice, expresii si Up: Introducere. Operatori. Expresii. Previous: Comparatie C Pascal Cuprins

Variabile. Operatori. Expresii


La fel ca n primul paragraf, vom studia un mic exemplu comentat.

#include <stdio.h>
#define FEET 0.303
void main(void)
{
/* program de conversie pasi - metri */
int dist1;
double dist2;
printf("Introduceti distanta in pasi\n");
scanf("%d",&dist1);
dist2=dist1*FEET;
printf("Distanta in metri este: %lf metri\n",dist2);
}

Vom ncepe explicatiile cu a doua linie a programului. Dupa cum s-a aratat n
primul paragraf, caracterul # semnifica o directiva preprocesor. Directiva define
are ca efect substituirea textuala n cadrul programului a identificatorului FEET
cu valoarea 0.303.

http://labs.cs.utt.ro/labs/pc/html/node5.html (1 of 2) [22.07.2003 16:18:01]

Variabile. Operatori. Expresii

Urmatoarea linie reprezinta nceputul functiei main. Corpul acestei functii ncepe
(dupa comentariile ignorate de compilator) cu definirea a doua variabile, dist1 si
dist2 de tip ntreg, respectiv real dubla precizie (pentru real dubla precizie, se
foloseste tipul double). Definirea variabilelor se poate face doar la nceputul
functiei sau n afara functiei (pentru variabile globale).
Urmatoarea instructiune este apelul functiei printf si are ca efect tiparirea unui
mesaj pe ecran. Functia scanf citeste de la tastatura o valoare ntreaga (specificata
prin descriptorul de format %d) si o memoreaza n variabila dist1. n lista de
argumente a lui scanf trebuie precizate nu variabilele care se citesc, ci adresele
acestora (de unde folosirea operatorului de adresa &). Mai mult despre aceste
functii, n capitolul urmator.
Dupa citirea variabilei dist1, se calculeaza valoarea dist2, prin nmultirea cu
valoarea 0.303 (obtinuta prin nlocuirea constantei FEET). Se observa ca cele
doua valori sunt de tipuri diferite (dist1 de tip ntreg, iar FEET de tip real dubla
precizie). C-ul este un limbaj foarte flexibil n ceea ce priveste conversia ntre
tipuri si atribuiri ntre variabile de tipuri diferite, astfel rezultatul unei operatii
este de tipul operandului "mai mare" din punct de vedere al reprezentarii (n cazul
nostru, int se reprezinta pe mai putini octeti dect double). Daca variabila din
stnga atribuirii este de un tip egal sau mai mare ca expresia rezultata n dreapta,
operatia de atribuire are loc fara probleme. Daca nsa n stnga atribuirii se afla o
variabila mai "slaba", rezultatul expresiei din stnga va fi trunchiat corespunzator.
Ultima linie din cadrul functiei main este un apel al functiei printf pentru
afisarea valorii variabilei dist2, valoare reala care impune folosirea descriptorului
de format %lf.
Subsections
Operatii aritmetice, expresii si operatori specifici limbajului C
next

up

previous

contents

Next: Operatii aritmetice, expresii si Up: Introducere. Operatori. Expresii. Previous: Comparatie C Pascal Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node5.html (2 of 2) [22.07.2003 16:18:01]

Operatii aritmetice, expresii si operatori specifici limbajului C

next

up

previous

contents

Next: Probleme propuse Up: Variabile. Operatori. Expresii Previous: Variabile. Operatori. Expresii
Cuprins

Operatii aritmetice, expresii si operatori specifici


limbajului C
Limbajului C ofera o foarte mare libertate programatorului, libertate nentlnita n
nici un alt limbaj de programare, fapt ce explica popularitatea sa. Aceasta
particularitate se reflecta cel mai mult n manipularea tipurilor, deoarece
compilatorul de C (spre deosebire de cel de Pascal) nu face verificari referitoare
la compatibilitatea tipurilor.
Cea mai evidenta "libertate" se regaseste la tipul caracter (char). Tipul caracater
este de fapt un tip ntreg reprezentat pe un octet (asemanator cu tipul byte din
Pascal). Astfel, secventa urmatoare de cod este perfect legala, acest tip de
"artificii" de programare fiind des ntlnite:

int i;
char c;
c='A';
i=c;
printf("codul ASCII al caracterului %c este %d\n",i,i);
i='A'+1;
printf("si urmatorul caracter este %c cu codul %d\n",i,i);

Folosirea descriptorului de format %c specific caracterelor duce la interpretarea


variabilei ntregi i ca o variabila caracter, si deci la tiparirea caracterului cu codul
ASCII egal cu valoarea lui i. De fapt, un caracter este memorat intern prin codul
sau ASCII, de aici si tratarea unitara a caracterelor si intregilor.

http://labs.cs.utt.ro/labs/pc/html/node6.html (1 of 4) [22.07.2003 16:18:02]

Operatii aritmetice, expresii si operatori specifici limbajului C

Un operator foarte folosit n C este operatorul de incrementare ++. Astfel,


secventele:
i++;
sau
++i;
sunt echivalente cu:
i=i+1;.
Diferenta ntre cele doua forme de scriere a operatorului de incrementare (format
postfix si format prefix) consta n modul n care se face incrementarea lui i: dupa
sau nainte de folosirea valorii variabilei

int i,j,k;
i=5;

k=i++;
/* dupa aceasta instructiune,
k va avea valoarea 5, iar i 6;
atribuirea are loc inainte de incrementare*/
j=++i;
/* dupa aceasta instructiune,
i va lua valoarea 7, iar j tot 7
atribuirea are loc dupa incrementare*/

n mod analog se comporta si operatorul de decrementare

http://labs.cs.utt.ro/labs/pc/html/node6.html (2 of 4) [22.07.2003 16:18:02]

$--$

Operatii aritmetice, expresii si operatori specifici limbajului C

Un alt mod de a compune operatorii este prin folosirea operatorului = dupa un


operator aritmetic (+ - * / %) sau un operator la nivel de bit (vezi capitolul 3).
De exemplu:
a+=3;
nseamna:
a=a+3;.
Limbajul C permite si atribuiri multiple, de tipul:
a=b=c=2;
n asemenea atribuiri, evaluarea se face de la dreapta spre stnga.
Dupa cum s-a aratat n paragrafele anterioare, n C nu exista tipul boolean,
valorile de adevar true-false fiind reprezentate de 0 si 1, astfel ca rezultatul unei
comparatii poate fi folosit n cadrul unei atribuiri:
a=b $>$3;
Aceasta are ca efect atribuirea valorii 1 sau 0 (functie de b mai mare ca 3 sau nu)
variabilei a.
O alta particularitate a limbajului C este posibilitatea de a initializa variabile n
momentul definitiei. Secventa:
int i=5;
defineste variabila i ca fiind de tip ntreg, avnd valoarea initiala 5.
Un operator specific C-ului este operatorul de secventiere , (reprezentat prin
virgula). Astfel:
i=(j++, a $<$b++);

http://labs.cs.utt.ro/labs/pc/html/node6.html (3 of 4) [22.07.2003 16:18:02]

Operatii aritmetice, expresii si operatori specifici limbajului C

are ca efect evaluarea expresiei j++, dupa care se evalueaza expresia a $<$b++,
rezultatul acestei ultime evaluari fiind cel atribuit lui i.
Dupa cum s-a aratat n exemplele anterioare, n C se efectueaza automat
conversia dintre tipuri n cazul atribuirii. La fel se ntmpla si n cazul transmiterii
de parametri in functii.
Programatorul poate controla explicit aceste conversii folosind operatorul de
casting (). ntre paranteze se scrie tipul la care se doreste sa se faca conversia, iar
parantezele se plaseaza naintea variabilei sau expresiei de convertit. Un exemplu
este prezentat n secventa:
float b;
b=3/(float)2;

Folosind operatorul de casting, b va avea valoarea 1.5. n absenta acestui


operator, la mpartirea lui 3 la 2, ambele valori fiind ntregi, rezultatul ar fi fost
trunchiat la 1, dupa care ar fi fost atribuit variabilei b.
Toti operatorii prezentati pna acum au fost unari sau binari (cu unul sau doi
operanzi). n C exista si un operator ternar (cu trei operanzi). Acesta este
operatorul conditional ? :, echivalent cu instructiunea if. Astfel, secventa:
x=(a<b)?a:b;

este echivalenta cu:


if (a<b)
x=a;
else
x=b;
next

up

previous

contents

Next: Probleme propuse Up: Variabile. Operatori. Expresii Previous: Variabile. Operatori. Expresii
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node6.html (4 of 4) [22.07.2003 16:18:02]

Probleme propuse

next

up

previous

contents

Next: Functii. Functii de biblioteca Up: Introducere. Operatori. Expresii. Previous: Operatii aritmetice,
expresii si Cuprins

Probleme propuse
1. Sa se ruleze secventa urmatoare, urmarind pas cu pas evolutia programului. Sa se explice ce efect
are executia programului prezentat. Cu ajutorul help-ului mediului de programare, se vor studia
functiile de biblioteca apelate.
#include <stdio.h>
#include <stdlib.h>
#define PROMPT ':'
void main(void)
{
int a,b;
char c;
int rez;
while (putchar(PROMPT), scanf("%d%c%d",&a,&c,&b)!=EOF)
{
switch (c)
{
case '+':
rez=a+b; break;
case '-':
rez=a-b; break;
case '*':
rez=a*b; break;
case '/':
if (b==0)
{
printf("\nImpartire la 0");
exit(1);
}
rez=a/b; break;
default:
printf("\nOperatie necunoscuta");
exit(1);
http://labs.cs.utt.ro/labs/pc/html/node7.html (1 of 3) [22.07.2003 16:18:02]

Probleme propuse

}
printf("\n%d%c%d=%d",a,c,b,rez);
}
}
2. Fiind date definitiile:
int i=3,j=5;
determinati valoarea urmatoarelor expresii, precum si valorile lui i si j, dupa evaluarea celor 4
expresii.
1. (i/2) +4
2. (j%3) * i
3. (i++) - ( $--$ j)
4. j = (i += 2)
3. Fiind date definitiile:
int a=2, b=2, c=1, d=0, e=4;
determinati valoarea urmatoarelor expresii:
1. a++ / ++c * $--$ e
2.

$--$ b * c++ - a

3. -b - $--$ c
4. ++a - $--$ e
5. e / $--$ a * b++ / c++
6. a%=b=d=1+e/2
4. Fiind date definitiile:
int i=2, j=4;
precizati care vor fi valorile lui i si j dupa executia urmatoarei instructiuni:
j = (i++, i-j);
5. Rulati urmatorul program pas cu pas vizualiznd valorile variabilelor din program. Justificati
rezultatele obtinute.

http://labs.cs.utt.ro/labs/pc/html/node7.html (2 of 3) [22.07.2003 16:18:02]

Probleme propuse

void main(void)
{
int a,b,c; float z;
a=25000; b=15000;
c=a+b;
z=a+b;
z=(float)a+b;
c=a/b;
c=a%b;
c=a>b;
z=a/b;
z=a/(float)b;
c=a=b;
c=a!=b;
a=3; b=11;
c=a++ + ++b;
a=0; b=1;
c=a&&b;
c=a||b;
c=!a;
a=2; b=5;
c=(a-5,b++);
c*=a+b;
c=(a>b)?a:b;
}

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node7.html (3 of 3) [22.07.2003 16:18:02]

Functii. Functii de biblioteca

next

up

previous

contents

Next: Functii definite de utilizator Up: carte Previous: Probleme propuse Cuprins

Functii. Functii de biblioteca


Subsections
Functii definite de utilizator

Functii de biblioteca

Functii de intrare-iesire

declarate n stdio.h

declarate n conio.h

Functii matematice

Functii de conversie

Exemple rezolvate

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node8.html [22.07.2003 16:18:02]

Functii definite de utilizator

next

up

previous

contents

Next: Functii de biblioteca Up: Functii. Functii de biblioteca Previous: Functii. Functii de biblioteca
Cuprins

Functii definite de utilizator


Functiile reprezinta un aspect important al programarii, independent de limbajul
utilizat. Ele permit ncapsularea unor rutine n cadrul unor "cutii negre", astfel ca
programatorul care se foloseste de anumite functii trebuie sa cunoasca doar
actiunea lor - ce fac ele, nu si modul cum sunt implementate. n plus, functiile
permit structurarea programului pe blocuri, separnd astfel zonele de cod ce
ndeplinesc actiuni diferite si conferind o mai mare lizibilitate a codului.
La fel ca n capitolul precedent, vom analiza modul n care utilizatorul poate
defini si apela o functie urmarind un exemplu. Se va defini o functie pentru a
verifica daca restul mpartirii a doua numere este 0; cu ajutorul acestei functii se
verifica apoi divizibilitatea cu 3 a primelor 100 numere naturale.

#include <stdio.h>
int divizibil(int, int);
void main(void)
{
int i;
for (i=1; i<=100; i++)
if (divizibil(i,3))
printf("numarul %d se divide cu 3\n",i);
else
printf("numarul %d nu se divide cu 3\n",i);
}

http://labs.cs.utt.ro/labs/pc/html/node9.html (1 of 4) [22.07.2003 16:18:03]

Functii definite de utilizator

int divizibil(int a, int


{
if (a%b)
/* a modulo b este
returneaza 0 */
return 0;
else
/* a modulo b este
divizibil cu b)
return 1;

b)

diferit de 0,

0 (a este
*/

Observatie: O alta implementare a functiei divizibil este prezentata mai jos:


int divizibil(int a, int b)
{
return !(a%b);
}

Definirea unei functii se face n maniera:


tip_returnat nume_functie(declaratia parametrilor)
{
definitii locale
instructiuni
}

Definirea unei functii se poate face oriunde n cadrul codului sursa, sau chiar n
alte fisiere, nsa nu poate fi facuta n interiorul altei functii.
n exemplul anterior, a doua linie a programului reprezinta declaratia sau
prototipul functiei divizibil. Aceasta are rolul de a anunta numele functiei, tipul
returnat si tipul si numarul parametrilor. Nu este obligatorie prezenta prototipului,
dar daca acesta lipseste, iar functia este apelata naintea declaratiei ei, unele
http://labs.cs.utt.ro/labs/pc/html/node9.html (2 of 4) [22.07.2003 16:18:03]

Functii definite de utilizator

compilatoare (mai vechi) vor da mesaje de avertizare n momentul compilarii.


Prototipurile au fost introduse n standardul ANSI C (versiunile mai vechi de C
nu prevedeau prototipuri de functii) pentru a permite compilatorului sa faca
anumite verificari legate de numarul parametrilor functiei si de conversii ilegale
ntre tipul parametrilor si cel al argumentelor.
n exemplu anterior, functia divizibil are doi parametri ntregi si returneaza o
valoare ntreaga. Valoarea returnata de o functie se transmite prin instructiunea
return, care are ca efect si parasirea executiei functiei. n cazul ca functia nu are
parametri sau nu returneaza nici o valoare, se foloseste tipul vid void.
Spre deosebire de alte limbaje (ca de ex. Pascal) unde mecanismul de transmitere
a parametrilor catre functii este prin adresa sau prin valoare, n C exista doar
transmiterea prin valoare. La transmiterea prin valoare, modificarile asupra
parametrilor efectuate n interiorul functiei nu se propaga si n afara functiei, dupa
cum se poate observa si din executia exemplului urmator:

#include <stdio.h>
void schimba(int a, int b)
{
int k;
k=a;
a=b;
b=k;
printf("in cadrul functiei, dupa schimbare a=%d b=%d\n",a,b);
}
void main(void)
{
int a=1, b=4;
printf("inainte de apelul functiei a=%d b=%d\n",a,b);
schimba(a,b);
printf("dupa apelul functiei a=%d b=%d\n",a,b);
}

http://labs.cs.utt.ro/labs/pc/html/node9.html (3 of 4) [22.07.2003 16:18:03]

Functii definite de utilizator

Chiar daca mecanismul de transmitere a parametrilor este doar prin valoare, n C


se pot transmite parametri si prin adresa, ntr-un mod indirect, folosind pointeri
(dupa cum se va arata n capitolele urmatoare).
next

up

previous

contents

Next: Functii de biblioteca Up: Functii. Functii de biblioteca Previous: Functii. Functii de biblioteca
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node9.html (4 of 4) [22.07.2003 16:18:03]

Functii de biblioteca

next

up

previous

contents

Next: Functii de intrare-iesire Up: Functii. Functii de biblioteca Previous: Functii definite de utilizator
Cuprins

Functii de biblioteca
Limbajul C a fost conceput ca un limbaj relativ redus, evitndu-se elemente care
nu au fost considerate strict necesare sau care ar reduce flexibilitatea si viteza de
executie. Prin urmare, C nu are ncorporate facilitati de prelucrare directa a
sirurilor de caractere, multimilor, listelor, tablourilor. Din acest motiv, nu exista
definit un tip de date pentru sirurile de caractere, folosindu-se pentru siruri
tablouri de caractere (char[]) sau pointeri la caracter (char *). De asemenea, nu
sunt prevazute n limbaj facilitati de intrare/iesire (nu exista instructiuni READ
sau WRITE), de alocare dinamica de memorie sau metode de acces la fisiere.
Pentru aceste operatii, cea mai mare parte a implementarilor de C ofera colectii
standard de functii de biblioteca. Aceste functii au o varietate de optiuni. n plus,
fiecare programator isi poate construi propria sa biblioteca de functii care sa
nlocuiasca sau sa extinda colectia de functii standard ale limbajului.
n cele ce urmeaza, vom trece n revista functiile de biblioteca cele mai uzuale
(mai putin functiile pentru tratarea sirurilor de caractere si functiile relative la
fisiere, care vor fi prezentate n capitolele urmatoare).
Subsections
Functii de intrare-iesire

declarate n stdio.h

declarate n conio.h

Functii matematice

Functii de conversie

Exemple rezolvate

http://labs.cs.utt.ro/labs/pc/html/node10.html (1 of 2) [22.07.2003 16:18:03]

Functii de biblioteca

next

up

previous

contents

Next: Functii de intrare-iesire Up: Functii. Functii de biblioteca Previous: Functii definite de utilizator
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node10.html (2 of 2) [22.07.2003 16:18:03]

Functii de intrare-iesire

next

up

previous

contents

Next: declarate n stdio.h Up: Functii de biblioteca Previous: Functii de biblioteca Cuprins

Functii de intrare-iesire
Subsections
declarate n stdio.h

declarate n conio.h

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node11.html [22.07.2003 16:18:03]

declarate n stdio.h

next

up

previous

contents

Next: declarate n conio.h Up: Functii de intrare-iesire Previous: Functii de intrare-iesire Cuprins

declarate n stdio.h
getchar
Prototip:
int getchar(void);
Efect: returneaza un caracter citit de la tastatura sau constanta simbolica EOF
daca s-a ntlnit sfrsitul fisierului de intrare (perechea CTRL-Z).
Observatie: Functia asteapta apasarea tastei Enter.

putchar
Prototip:
int putchar(int c);
Efect: afiseaza caracterul c pe ecran; returneaza caracterul afisat sau valoarea
EOF la detectia unei erori.

gets
Prototip:
char *gets(char *s);
Efect: citeste un sir de caractere s de la tastatura pna la ntlnirea caracterului
newline ( $\backslash$
n); returneaza adresa sirului citit sau valoarea NULL daca s-a citit

http://labs.cs.utt.ro/labs/pc/html/node12.html (1 of 4) [22.07.2003 16:18:03]

declarate n stdio.h

CTRL-Z. Caracterul newline nu este memorat n sir.


Observatie: Deoarece este imposibil de prevazut cte caractere vor fi citite de la
tastatura ntr-o operatie de introducere de siruri, si deoarece gets nu verifica
lungimea alocata sirului destinatie, folosirea acestei functii n programele
importante poate duce la efecte "neplacute" (prin scrierea datelor citite peste zone
de memorie alocate altor variabile). Acest "bug" a dus la "spargerea" multor
sisteme vechi care foloseau gets pentru citirea parolei.
puts
Prototip:
int puts(char *s);
Efect: afiseaza pe ecran sirul s urmat de caracterul newline.

printf
Prototip:
int printf(char *format, arg1, arg2, ...);
Efect: afiseaza pe ecran valorile din lista de argumente, conform formatului
specificat. Sirul format poate contine caractere ordinare, care se vor afisa ca atare,
si descriptori de format prefixati de caracterul %.
Un descriptor de format poate contine n ordine urmatoarele:

un semn minus care indica alinierea la stnga n cadrul formatului a valorii afisate;
un numar care specifica lungimea minima a cmpului de afisare;
un punct care separa lungimea cmpului de afisare de precizia de afisare (de ex. numarul de
zecimale pentru valorile reale);

n tabelul 2.1 sunt prezentate caracterele de conversie cele mai uzuale ce pot
aparea n descriptorii de format.
Tabela 2.1: Descriptori de format

http://labs.cs.utt.ro/labs/pc/html/node12.html (2 of 4) [22.07.2003 16:18:03]

declarate n stdio.h

Caracter

Valoare

d,i

ntreg zecimal

ntreg octal fara semn

x, X

ntreg hexazecimal fara semn

ntreg zecimal fara semn

caracter

sir de caractere

real simpla precizie

lf

real dubla precizie

scanf
Prototip:
int scanf(char *format, adr1, adr2,...);
Efect: citeste caractere de la tastatura, conform formatului, si nscrie valorile citite
la adresele specificate. Functia returneaza numarul de cmpuri citite cu succes sau
valoarea EOF la ntlnirea sfrsitului fisierului de intrare. Sirul format poate
contine:

caractere blank sau tab care sunt ignorate;


caractere ordinare care trebuie sa fie citite corespunzator de la intrare;
specificatori de conversie, la fel ca la printf.

Specificatorii de conversie determina modul de conversie a cmpurilor de intrare.


Un cmp de intrare se defineste ca o secventa de caractere, altele dect spatiile
albe ale limbajului: blank, tab, newline, carriage return, formfeed, tab vertical.
De exemplu, pentru citirea unei linii de forma:
6 Mar 1996

http://labs.cs.utt.ro/labs/pc/html/node12.html (3 of 4) [22.07.2003 16:18:03]

declarate n stdio.h

se va scrie urmatoarea secventa:


int zi, an;
char luna[4];
scanf("%d %s %d", &zi, luna, &an);

Se observa ca la variabilele zi si an s-a folosit operatorul de adresa &; la variabila


luna, el nu apare deoarece n limbajul C numele unui tablou este echivalent cu
adresa sa (este un pointer catre primul sau element).
Observatie: Pentru mai multe informatii privind functiile scanf si printf
consultati fisierul de help prezent n mediul de programare utilizat.

sscanf
Prototip:
int sscanf(char *sir,char *format, adr1, adr2,...);
Efect: citeste date cu formatare; spre deosebire de scanf la care citirea se face de
la tastatura (dispozitivul standard de intrare), la sscanf citirea datelor se face
dintr-un sir.

next

up

previous

contents

Next: declarate n conio.h Up: Functii de intrare-iesire Previous: Functii de intrare-iesire Cuprins
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node12.html (4 of 4) [22.07.2003 16:18:03]

declarate n conio.h

next

up

previous

contents

Next: Functii matematice Up: Functii de intrare-iesire Previous: declarate n stdio.h Cuprins

declarate n conio.h
getch
Prototip:
int getch(void);
Efect: citeste un caracter de la tastatura fara sa-l afiseze pe ecran; returneaza
caracterul citit.

getche
Prototip:
int getche(void);
Efect: citeste un caracter de la tastatura si-l afiseaza pe ecran; returneaza
caracterul citit.

ungetch
Prototip:
int ungetch(int c);
Efect: reinsereaza caracterul c n buffer-ul tastaturii, astfel nct urmatorul
caracter care va fi citit este cel reinserat.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node13.html [22.07.2003 16:18:04]

Functii matematice

next

up

previous

contents

Next: Functii de conversie Up: Functii de biblioteca Previous: declarate n conio.h Cuprins

Functii matematice
Functiile prezentate n tabelul 2.2 sunt declarate in fisierul antet math.h.
Tabela 2.2: Functii matematice din biblioteca math
Prototipul functiei

Efect

double acos(double x);

arccosinus de x

double asin(double x);

arcsinus de x

double atan(double x);

arctangenta de x

double atan2(double y, double x);

arctangenta de y/x

double ceil(double x);

cel mai mic intreg mai mare sau egal cu x

double cos(double x);

cosinus de x

double exp(double x);

next

up

exponentiala $e^x$

double fabs(double x);

valoarea absoluta a lui x

double floor(double x);

cel mai mare intreg mai mic sau egal cu x

double log(double x);

ln de x

double log10(double x);

lg de x

double pow(double x, double y);

x la puterea y

double sin(double x);

sinus de x

double sqrt(double x);

radicalul lui x

double tan(double x);

tangenta lui x

previous

contents

Next: Functii de conversie Up: Functii de biblioteca Previous: declarate n conio.h Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node14.html [22.07.2003 16:18:04]

Functii de conversie

next

up

previous

contents

Next: Exemple rezolvate Up: Functii de biblioteca Previous: Functii matematice Cuprins

Functii de conversie
Prezentam n tabelul 2.3 doua functii de conversie a unui sir de caractere ntr-o
valoare ntreaga, respectiv ntr-o valoare reala. Aceste functii sunt declarate n
fisierul antet stdlib.h.
Tabela 2.3: Functii de conversie sir - valoare numerica
Prototip

Efect

int atoi(char *s);

converteste sirul s ntr-o valoare ntreaga

double atof(char *s);

converteste sirul s ntr-o valoare reala

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node15.html [22.07.2003 16:18:04]

Exemple rezolvate

next

up

previous

contents

Next: Probleme propuse Up: Functii de biblioteca Previous: Functii de conversie Cuprins

Exemple rezolvate
1. Sa se scrie un program care citeste o succesiune de linii ce contin date calendaristice n formatul:
zi/luna/an. Se cere sa se afiseze liniile scrise corect conform formatului specificat anterior.
#include <stdio.h>
void main(void)
{
char linie[80];
int zi, luna, an;
while (gets(linie)!=NULL)
if (sscanf(linie, "%d/%d/%d", &zi, &luna, &an)==3)
printf("%s\n", linie);
}
2. Sa se realizeze programul care citeste o secventa de numere reale, terminata cu Ctrl-Z si afiseaza
dupa fiecare citire suma valorilor absolute citite pna n acel moment. Afisarea sumei se face cu o
precizie de 3 cifre zecimale.
#include <stdio.h>
#include <math.h>
void main(void)
{
double suma=0, valoare;
while(1)
{
printf("\nDati un numar: ");
if (scanf("%lf", &valoare)==EOF) break;
printf("\t %.3lf\n", suma+=fabs(valoare));
}
}
Observatie: Unii autori recomanda, pe ct posibil, evitarea unei bucle while(1) si iesirea prin
instructiunea break, deoarece prin aceasta practica se distruge lizibilitatea programelor. Conditia
de iesire din bucla e bine sa apara ca si conditie pentru while, chiar daca aceasta nseamna lungirea

http://labs.cs.utt.ro/labs/pc/html/node16.html (1 of 2) [22.07.2003 16:18:05]

Exemple rezolvate

cu 2-3 linii a secventei.


3. Se citeste de la tastatura un text terminat cu Ctrl-Z. Se cere sa se afiseze toate numerele ntregi
continute n text.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define N
15
void main(void)
{
char c;
/* caracterul citit la un moment dat */
char s[20];
/* buffer cu caract. ce compun un numar */
int numere[N]; /* tablou cu numerele citite */
int i=0, j=0;
c=getchar();
while (c!=EOF)
if (isdigit(c)) /* incepe un numar */
{
i=0;
s[i++]=c;
while (isdigit(c=getchar()))
s[i++]=c;
s[i]='\0';
numere[j++]=atoi(s);
}
else
c=getchar();
/* afisarea numerelor */
for (i=0; i<j; i++)
printf("\n %6d", numere[i]);
}
Observatie: Pentru a testa daca un caracter este cifra s-a folosit functia isdigit() declarata n
fisierul antet ctype.h (va fi prezentata n capitolele urmatoare). Dupa ce s-au citit caracterele
corespunzatoare unui numar, folosind functia atoi se face conversia n numarul ntreg
corespunzator. Numerele ntlnite n cadrul textului se memoreaza n tabloul numere.
next

up

previous

contents

Next: Probleme propuse Up: Functii de biblioteca Previous: Functii de conversie Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node16.html (2 of 2) [22.07.2003 16:18:05]

Probleme propuse

next

up

previous

contents

Next: Operatii la nivel de Up: Functii. Functii de biblioteca Previous: Exemple rezolvate Cuprins

Probleme propuse
1. Scrieti instructiunea care va afisa urmatoarele linii:
H. Smith /78 \ aaa #67 "ggg"
mmm
2. Aratati ce afiseaza urmatorul program:
#include <stdio.h>
void main(void)
{
int i=43;
char c='A';
float f=55.45;
printf("%5d %.1f %c\n",i,f,c);
printf("%d %d %d \n",i, (int)f, c);
printf("%c %d\n", c+1, c);
}
3. Sa se implementeze o functie
int putere(int x, int n);
care ridica pe x la puterea n. Sa se scrie un program care calculeaza patratele si cuburile primelor
10 numere naturale folosind functia putere.
4. Sa se scrie un program care citeste de la tastatura un numar real x si un caracter ce reprezinta
optiunea utilizatorului privind operatia ce trebuie efectuata cu numarul respectiv, dupa care
afiseaza rezultatul operatiei. Prezentam mai jos optiunile posibile:
''e'' - e la puterea x
''l'' - ln de x
''r'' - radicalul lui x
''m'' - valoarea absoluta a lui x.

Cristian Gavrila 2001-10-02


http://labs.cs.utt.ro/labs/pc/html/node17.html [22.07.2003 16:18:05]

Operatii la nivel de bit

next

up

previous

contents

Next: Operatori la nivel de Up: carte Previous: Probleme propuse Cuprins

Operatii la nivel de bit


Subsections
Operatori la nivel de bit

Utilizarea operatorilor

Probleme rezolvate

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node18.html [22.07.2003 16:18:05]

Operatori la nivel de bit

next

up

previous

contents

Next: Utilizarea operatorilor Up: Operatii la nivel de Previous: Operatii la nivel de Cuprins

Operatori la nivel de bit


Spre deosebire de alte limbaje de nivel nalt, de exemplu Pascal Standard, C ofera
o familie de 6 operatori la nivel de bit, furniznd astfel facilitati specifice, de
obicei, limbajelor de asamblare. Acestia permit scrierea unor programe care
lucreaza ndeaproape cu sistemul hardware al calculatorului.
Operatorii la nivel de bit se aplica unor ntregi, adica obiecte de tipul char, short,
int, long, cu sau fara semn, iar rezultatele obtinute sunt de asemenea ntregi. Fata
de ceilalti operatori ai limbajului, ei opereaza asupra fiecarui bit din reprezentarea
interna a operanzilor, tratndu-l independent de valorile celorlalti biti.
Acesti operatori sunt:
$\thicksim$

operatorul unar de negare


&
operatorul binar si
$\vert$

operatorul binar sau


^
operatorul binar sau exclusiv
$<<$

operatorul de deplasare la stnga


$>>$

operatorul de deplasare la dreapta.

http://labs.cs.utt.ro/labs/pc/html/node19.html (1 of 2) [22.07.2003 16:18:06]

Operatori la nivel de bit

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node19.html (2 of 2) [22.07.2003 16:18:06]

Utilizarea operatorilor

next

up

previous

contents

Next: Probleme rezolvate Up: Operatii la nivel de Previous: Operatori la nivel de Cuprins

Utilizarea operatorilor
Un exemplu tipic de utilizare a operatorilor la nivel de bit este implementarea
unei multimi ca vector de biti. n acest caz, un bit dintr-un ntreg fara semn se
asociaza unui element din multime, iar valoarea 1, respectiv 0 a unui bit
semnifica prezenta, respectiv absenta elementului din multime. Numarul de
elemente din multime este limitat la numarul de biti disponibili. n acest caz
operatorul binar & este interpretat ca si intersectie, iar $\vert$
ca si reuniune.
Alte utilizari ale acestor operatori se ntlnesc n programele dedicate operatiilor
hardware.
Indiferent de scopul n care sunt utilizati operatorii, maniera n care sunt folositi
este n general aceeasi. n cele ce urmeaza, se vor descrie pe scurt principiile de
baza ale utilizarii lor.
Atentie! Operatorii la nivel de bit nu modifica valoarea operanzilor (se comporta
ca si operatorii aritmetici obisnuiti), astfel o operatie n 2 va rezulta ntr-un
nou numar, fara a modifica valoarea variabilei n. Pentru a modifica valoarea
variabilei n trebuie sa avem o atribuire:
n = n 2;
n general, operatorul si (&) este folosit pentru a masca anumiti biti dintr-un
numar:
n = n & 177

http://labs.cs.utt.ro/labs/pc/html/node20.html (1 of 3) [22.07.2003 16:18:06]

Utilizarea operatorilor

va pune pe 0 bitii din n corespunzatori zero-urilor din reprezentarea binara a


numarului 177 (adica 10110001), bitii corespunzatori unu-rilor ramnnd
nemodificati.
Operatorul sau ( $\vert$
) se comporta asemanator, doar ca elementul neutru nu este 1 ca
la si, ci 0.
Trebuie facuta distinctia ntre operatorii la nivel de bit (& si $\vert$
) si operatorii logici
(&& si

). De exemplu,
$\vert\vert$

daca x=1 si y=2, atunci x & y va fi 0, iar x && y va

fi 1.
Operatorii de deplasare

$<<$

si

$>>$

realizeaza deplasarea bitilor din operandul

stng cu attea pozitii cte sunt indicate de operandul drept. n cazul deplasarii la
stnga ( $<<$ ) bitii din stnga se vor pierde, iar n dreapta numarului vor fi
introduse cifre de 0. n cazul deplasarii la dreapta, bitii din dreapta se pierd, iar n
stnga se introduc biti de 0, n caz ca numarul era de tip fara semn (unsigned,
char) sau biti egali cu bitul de semn (cel mai din stnga bit) n cazul numerelor
de tip cu semn.
Operatorul de negare $\thicksim$
realizeaza complementarea tuturor bitilor unui numar.
Se impun doua observatii legate de acest operator:
1. n general, daca dorim setarea pe 1 a unor biti de la nceputul unui numar, nu vom folosi o expresie
de tipul x = x & 252 (adica un numar cu primele cifre binare 1), deoarece nu putem fi siguri
niciodata pe cti octeti este reprezentata variabila x (chiar daca stim exact de ce tip este variabila,
lungimea reprezentarii depinde de arhitectura calculatorului si de sistemul de operare). Astfel, se
3 (unde 3 = $\thicksim$
252).
va prefera folosirea unor expresii de tipul x = x & $\thicksim$
2. deoarece reprezentarea interna a numerelor cu semn poate diferi ntre arhitecturi sau sisteme de
operare diferite, operatorul de negare pe biti reduce portabilitatea programelor ntre diferite
sisteme de calcul. Din acest motiv se recomanda folosirea acestui operator doar cu numere de tip
fara semn.
next

up

previous

contents

Next: Probleme rezolvate Up: Operatii la nivel de Previous: Operatori la nivel de Cuprins Cristian
http://labs.cs.utt.ro/labs/pc/html/node20.html (2 of 3) [22.07.2003 16:18:06]

Utilizarea operatorilor

Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node20.html (3 of 3) [22.07.2003 16:18:06]

Probleme rezolvate

next

up

previous

contents

Next: Probleme propuse Up: Operatii la nivel de Previous: Utilizarea operatorilor Cuprins

Probleme rezolvate
Sa se scrie o functie getbits(x,p,n) care returneaza, aliniat la dreapta, un cmp de n
biti dintr-un ntreg fara semn x, ncepnd cu pozitia p a lui x, dupa cum se arata n
figura 3.1. Se considera ca bitul cel mai putin semnificativ al lui x are pozitia 0.

\begin{figure}\begin{center}
\epsfig{file=getbits.eps} \end{center}\end{figure}

Figura 3.1: Functia getbits


#include <stdio.h>
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p+1-n)) & ~(~0 << n);
}

http://labs.cs.utt.ro/labs/pc/html/node21.html (1 of 2) [22.07.2003 16:18:06]

Probleme rezolvate

void main(void)
{
unsigned x;
int p=6,n=3;
printf("Numar initial: ");
scanf("%u", &x);
printf("Valoarea extrasa: %u\n", getbits(x,p,n));
}

Se observa ca n functia getbits:

secventa

secventa $\thicksim (\thicksim 0 creeaza masca de extragere, adica 000...0111

$x >> (p+1-n)$

aliniaza la dreapta bitii de extras

<< n)$

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node21.html (2 of 2) [22.07.2003 16:18:06]

Probleme propuse

next

up

previous

contents

Next: Caractere, siruri de caractere. Up: Operatii la nivel de Previous: Probleme rezolvate Cuprins

Probleme propuse
1. Sa se scrie o functie setbits(x,p,n,y), care returneaza un ntreg x avnd n biti ncepnd de la pozitia p egali
cu cei mai din dreapta n biti ai ntregului y, ca n figura 3.2. Restul bitilor lui x ramn nemodificati.

\begin{figure}\begin{center}
\epsfig{file=setbits.eps} \end{center}\end{figure}

Figura 3.2: Functia setbits


2. Sa se scrie o functie bin(x) care afiseaza reprezentarea binara a unui ntreg x, utiliznd operatorii de
deplasare la nivel de bit.
3. Se considera multimi cu elemente ntregi avnd valori n intervalul [1...n]. Aceste multimi se
implementeaza ca vectori de biti: char tab[n/8+1], n care sunt setati bitii corespunzatori
elementelor prezente n multime. Sa se implementeze urmatoarele operatii (functii) cu aceste multimi:
afisarea elementelor unei multimi:
void afiseaza(char mult[]);
adaugarea unui element la o multime:
void adauga(int x,char mult[]);
verificarea prezentei unui element n multime:
int prezent(int x,char mult[]);
reuniunea a doua multimi:
http://labs.cs.utt.ro/labs/pc/html/node22.html (1 of 2) [22.07.2003 16:18:07]

Probleme propuse

void reuniune(char mult1[],char mult2[],char mult3[]);


intersectia a doua multimi:
void intersectie(char mult1[],char mult2[],char mult3[]);
diferenta a doua multimi:
void diferenta(char mult1[],char mult2[],char mult3[]);
Se va scrie un program care permite, pe baza unui meniu, selectarea acestor operatii.
next

up

previous

contents

Next: Caractere, siruri de caractere. Up: Operatii la nivel de Previous: Probleme rezolvate Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node22.html (2 of 2) [22.07.2003 16:18:07]

Caractere, siruri de caractere. Tablouri

next

up

previous

contents

Next: Operatii cu caractere Up: carte Previous: Probleme propuse Cuprins

Caractere, siruri de caractere. Tablouri


Subsections
Operatii cu caractere

Tablouri unidimensionale

Siruri de caractere

Observatii asupra sirurilor de caractere

Probleme rezolvate

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node23.html [22.07.2003 16:18:07]

Operatii cu caractere

next

up

previous

contents

Next: Tablouri unidimensionale Up: Caractere, siruri de caractere. Previous: Caractere, siruri de
caractere. Cuprins

Operatii cu caractere
Tipul predefinit, destinat n C lucrului cu caractere, este tipul char. Spatiul de
memorie asociat variabilelor acestui tip este 1 octet; un caracter se memoreaza ca
numarul ntreg corespunzator codului ASCII al caracterului respectiv. Prin
urmare, n C un caracter poate aparea n operatii numerice. Valorile acestui tip
sunt cuprinse n intervalul [-128...127] n cazul caracterelor cu semn, respectiv
[0...255] n cazul celor fara semn.
Biblioteca C standard ofera o gama larga de functii pentru manipularea
caracterelor. Aceste functii sunt grupate n doua categorii:

functii de citire si scriere a caracterelor (declarate n fisierul stdio.h)


functii de clasificare si conversie a caracterelor.

O parte din functiile din prima categorie au fost tratate n Capitolul 2. n


continuare prezentam cteva functii din a doua categorie. La unele dintre acestea
vor fi date ca exemplu variante posibile de implementare.
int isalpha(int c);
Efect: returneaza o valoare nenula daca c este litera ['' A''...''Z'', ''a''...''z''];
Exemplu de implementare:
int isalpha(int c)
{
return c>='A' && c<='Z' || c>='a' && c<='z';
}

http://labs.cs.utt.ro/labs/pc/html/node24.html (1 of 3) [22.07.2003 16:18:07]

Operatii cu caractere

int isdigit(int c);


Efect: returneaza o valoare nenula daca c este cifra [''0''...''9''];
int isalnum(int c);
Efect: returneaza o valoare nenula daca c este litera sau cifra;
int isupper(int c);
Efect: returneaza o valoare nenula daca c este litera mare;
int islower(int c);
Efect: returneaza o valoare nenula daca c este litera mica;
int isspace(int c);
Efect: returneaza o valoare nenula daca c este un caracter spatiu ('' '',

r, $\backslash$
t, $\backsl
n,
$\backslash$

f, $\backslash$
v);
$\backslash$

int toupper(int c);


Efect: returneaza litera majuscula ce corespunde lui c, daca c este litera mica;
Exemplu de implementare:
int toupper(int c)
{
return islower(c) ? c-'a'+'A' : c;
}

http://labs.cs.utt.ro/labs/pc/html/node24.html (2 of 3) [22.07.2003 16:18:07]

Operatii cu caractere

int tolower(int c);


Efect: returneaza litera mica ce corespunde lui c, daca c este litera mare;
next

up

previous

contents

Next: Tablouri unidimensionale Up: Caractere, siruri de caractere. Previous: Caractere, siruri de
caractere. Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node24.html (3 of 3) [22.07.2003 16:18:07]

Tablouri unidimensionale

next

up

previous

contents

Next: Siruri de caractere Up: Caractere, siruri de caractere. Previous: Operatii cu caractere Cuprins

Tablouri unidimensionale
n C, tablourile unidimensionale sunt alcatuite dintr-un grup de elemente de
acelasi tip (numit tip de baza) si referite printr-un nume comun.
Variabilele de tip tablou se definesc n maniera:
tip_de_baza nume_var[dimensiune];
Un element al tabloului este accesat folosind ca index pozitia elementului, astfel
tabloul_meu[6] va referi al saptelea element al tabloului tabloul_meu.
Atentie! n C, "numerotarea" elementelor tablourilor ncepe cu pozitia 0, astfel,
daca avem definitia:
int tabloul_meu[100];
primul element al tabloului va fi tabloul_meu[0], iar ultimul tabloul_meu[99].
Tablourile sunt stocate n memorie la locatii consecutive, un tablou ocupnd o
zona contigua de memorie, cu primul element al tabloului aflat la adresa mai
mica.
Atentie! O problema legata de tablouri este ca n C nu se face nici o verificare
legata de "marginile" tabloului, astfel ca se pot accesa gresit elemente din afara
tabloului. De exemplu, pentru definitia:
int tabloul_meu[100];
daca accesam tabloul_meu[105] nu se va semnala nici o eroare, returnndu-se
valoarea de la o locatie de memorie aflata la o distanta de 5 locatii fata de sfrsitul
tabloului, fapt ce va duce la comportari "bizare" ale programului. Aceeasi situatie,
dar fata de nceputul tabloului, se ntmpla la accesarea tabloul_meu[-5].
http://labs.cs.utt.ro/labs/pc/html/node25.html (1 of 2) [22.07.2003 16:18:08]

Tablouri unidimensionale

next

up

previous

contents

Next: Siruri de caractere Up: Caractere, siruri de caractere. Previous: Operatii cu caractere Cuprins
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node25.html (2 of 2) [22.07.2003 16:18:08]

Siruri de caractere

next

up

previous

contents

Next: Observatii asupra sirurilor de Up: Caractere, siruri de caractere. Previous: Tablouri
unidimensionale Cuprins

Siruri de caractere
Cele mai des ntlnite utilizari ale tablorilor unidimensionale n limbajul C sunt
sirurile de caractere, din cauza ca n C nu exista prevazut tipul de date sir de
caractere. Pentru memorarea sirurilor se utilizeaza tablouri cu tipul de baza char,
care au pe ultima pozitie, ca marca de sfrsit a sirului, caracterul '' $\backslash$
0''.
Pe lnga necesitatea de a defini un sir de caractere ca si tablou de caractere, n
prelucrarea sirurilor se utilizeaza deseori tipul pointer la caracter. De exemplu:
char sir[30];
char *psir;

/* tablou de 30 de caractere */
/* pointer la caracter */

Astfel, sir este o variabila de tipul tablou de caractere pentru care se rezerva un
spatiu de memorie de 30 de octeti, n timp ce psir este un pointer la caracter care
poate primi ca valoare adresa unui caracter (n particular, adresa primului element
dintr-un sir de caractere). Trebuie retinut ca ori de cte ori se lucreaza cu variabile
siruri de caractere ntr-un program, trebuie sa existe fie o definitie de forma celei
prezentate pentru variabila sir, prin care se rezerva static (n timpul compilarii),
spatiul de memorie necesar variabilei, fie sa se aloce dinamic memoria necesara.
Neexistnd tipul sir de caractere, n C nu sunt prezenti nici operatorii pentru
siruri. n schimb, biblioteca standard contine numeroase functii pentru prelucrarea
sirurilor de caractere. O parte a functiilor pentru citirea/scrierea sirurilor,
declarate n fisierul antet stdio.h, le-am prezentat n Capitolul 2. n continuare,
trecem n revista functiile pentru compararea, copierea, concatenarea sirurilor,
s.a.m.d. Acestea sunt declarate n fisierul string.h. Ele primesc adresele sirurilor
prelucrate, prin intermediul parametrilor de tipul pointer la caracter.

http://labs.cs.utt.ro/labs/pc/html/node26.html (1 of 3) [22.07.2003 16:18:08]

Siruri de caractere

int strcmp(char *s1, char *s2);


Efect: compara sirurile s1 si s2 si returneaza
daca s1 egal s2, si

$>0$

daca s1

$<0$ ,

daca sirul s1

$<$ sirul

s2, 0

$>$ s2.

int strncmp(char *s1, char *s2, int n);


Efect: identica cu strcmp, dar se compara sirurile s1 si s2 pentru cel mult n
caractere.

char *strcpy(char *d, char *s);


Efect: copiaza sirul sursa s n sirul destinatie d si returneaza adresa sirului
destinatie.

char *strncpy(char *d, char *s, int n);


Efect: copiaza maxim n caractere de la sursa s la destinatia d si returneaza adresa
sirului destinatie.

int strlen(char *s);


Efect: returneaza lungimea sirului fara a numara caracterul terminator ('' $\backslash$
0'').

http://labs.cs.utt.ro/labs/pc/html/node26.html (2 of 3) [22.07.2003 16:18:08]

Siruri de caractere

char *strcat(char *d, char *s);


Efect: concateneaza cele doua siruri si returneaza adresa sirului rezultat.
n paragraful urmator vor fi prezentate particularitati ale operatiilor cu siruri de
caractere, ct si dificultati si erori tipice rezultate din manipularea sirurilor de
caractere.
Subsections
Observatii asupra sirurilor de caractere
next

up

previous

contents

Next: Observatii asupra sirurilor de Up: Caractere, siruri de caractere. Previous: Tablouri
unidimensionale Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node26.html (3 of 3) [22.07.2003 16:18:08]

Observatii asupra sirurilor de caractere

next

up

previous

contents

Next: Probleme rezolvate Up: Siruri de caractere Previous: Siruri de caractere Cuprins

Observatii asupra sirurilor de caractere


Se impun facute cteva precizari asupra unor operatii cu siruri.
Prima precizare se refera la natura "duala" tablou-pointer (care va fi prezentata n
capitolele urmatoare), motiv pentru care, n cazul citirii unui sir de caractere
folosind functia scanf, nu este necesara folosirea operatorului de adresa & n fata
variabilei sir (indiferent ca aceasta a fost declarata ca pointer la char sau ca
tablou de caractere).
O recomandare de ordin "practic", impusa de maniera n care unele functii de
intrare/iesire folosesc buffer-ul de intrare: se va evita folosirea functiei scanf
pentru citirea unui singur caracter, mai ales dupa un alt apel al functiei scanf; se
recomanda folosirea functiilor getch sau getche (nu getchar).
O alta problema n folosirea functiei scanf la citirea sirurilor de caractere apare la
siruri care contin caractere de tip separator (spatii goale, tab-uri, etc.). Functia
scanf va citi sirul doar pna la primul caracter de acest tip.
Frecvent, programatorii obisnuiti cu limbajul Pascal si care "migreaza" la C fac o
greseala importanta: compararea sirurilor folosind operatorii de comparatie
aritmetici: $<$, $>$ si $==$ . Din punct de vedere sintactic, nu se semnaleaza nici o
eroare n timpul compilarii, dar n timpul executiei vor aparea comportari
anormale ale programului. Cauza acestui fapt este ca folosind comparatii ntre
siruri cu operatori aritmetici, se realizeaza, de fapt, o comparatie ntre adresele de
memorie la care sunt stocate sirurile, si nu o comparatie efectiva ntre siruri.
Pentru a compara siruri, trebuie folosite doar functiile dedicate (strcmp,
strncmp).

http://labs.cs.utt.ro/labs/pc/html/node27.html (1 of 2) [22.07.2003 16:18:09]

Observatii asupra sirurilor de caractere

O greseala asemanatoare este folosirea operatorului aritmetic de atribuire ntre


siruri. n loc sa se efectueze copierea unui sir peste celalalt, dupa atribuirea
aritmetica, cele doua variabile sir vor referi aceeasi zona de memorie (deoarece
s-a realizat o atribuire de pointeri). Pentru atribuiri de siruri, se vor folosi functii
specifice (strcpy, strncpy, bcopy, memcpy, memmove). Compilatorul nu va
sesiza eroare dect daca cele doua siruri au fost declarate ca tablouri. Exemplul
urmator ilustreaza aceasta greseala (operatia de alocare va fi explicata n capitolul
dedicat pointerilor):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void){
char * s1;
char * s2;
s1=(char *)malloc(20);
s2=(char *)malloc(20);

/* alocare dinamica, 20 caractere */


/* echivalent cu declaratia: */
/* char s1[20], s2[20]; */

strcpy(s1,"abcedfg");
strcpy(s2,"mnopqrs");
s1=s2;

/* s1 si s2 vor referi
acelasi sir de caractere */

s1[3]='\0';
/* scurteaza pe s1 la 3 caractere */
printf("%s\n%s\n",s1,s2); /* modificarea se va reflecta si */
/* asupra lui s2 */
}
next

up

previous

contents

Next: Probleme rezolvate Up: Siruri de caractere Previous: Siruri de caractere Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node27.html (2 of 2) [22.07.2003 16:18:09]

Probleme rezolvate

next

up

previous

contents

Next: Probleme propuse Up: Caractere, siruri de caractere. Previous: Observatii asupra sirurilor de
Cuprins

Probleme rezolvate
1. Sa se implementeze n doua moduri functia strcmp.

int strcmp(char *s1, char *s2)


{
int i;
for (i=0; s1[i]||s2[i]; i++)
if (s1[i]<s2[i])
return -1;
else
if (s1[i]>s2[i])
return 1;
return 0;
}

int strcmp(char *s1, char *s2)


{
int i;
for (i=0; s1[i]||s2[i]; i++)
if (s1[i]!=s2[i])
break;
return s1[i]-s2[i];
}
2. Sa se implementeze functia strcpy.
char *strcpy(char *d, char *s)
{
int i=0;
while (s[i])
http://labs.cs.utt.ro/labs/pc/html/node28.html (1 of 3) [22.07.2003 16:18:09]

Probleme rezolvate

/* nu s-a ajuns la sfarsitul sirului s */


d[i]=s[i];
i++;

}
d[i]='\0';
return d;
}
3. Sa se scrie o functie care converteste un caracter reprezentnd o cifra hexazecimala n echivalentul
ntreg zecimal.
int hexa (char c)
{
if (isalpha(c))
return toupper(c)-'A'+10;
return c-'0';
}
4. Sa se scrie o functie care verifica daca un sir de caractere este compus n ntregime din cifre.
Folosind aceasta functie, sa se scrie un program care citeste de la intrare siruri de caractere (cte
unul pe fiecare linie) pna la ntlnirea caracterului EOF si afiseaza inversat (de la dreapta la
stnga) fiecare sir citit, exceptnd sirurile compuse doar din cifre, care se vor afisa nemodificate.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int numar(char * s)
{
int i=0;
while(s[i])
if (!isdigit(s[i++]))
return 0; /* s-a gasit un caracter non-cifra */
return 1; /* toate caraterele sunt cifre */
}
void main(void)
{
char sir[80], c;
short i, j;
while (gets(sir)!=NULL)
{
if (!numar(sir))
/* se interschimba prin intermediul lui c elementele
http://labs.cs.utt.ro/labs/pc/html/node28.html (2 of 3) [22.07.2003 16:18:09]

Probleme rezolvate

aflate pe pozitii simetrice in raport cu mijlocul sirului */


for (i=0, j=strlen(sir)-1; i<j; ++i, --j)
c=sir[i], sir[i]=sir[j], sir[j]=c;
puts(sir);
}
}

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node28.html (3 of 3) [22.07.2003 16:18:09]

Probleme propuse

next

up

previous

contents

Next: Prelucrarea fisierelor Up: Caractere, siruri de caractere. Previous: Probleme rezolvate Cuprins

Probleme propuse
1. Se da o lista de cuvinte separate prin spatiu, lista care se ncheie prin doua rnduri goale succesive
(doua enter-uri). Sa se tipareasca n ordine alfabetica toate palindroamele care apar n lista. Un
palindrom este un cuvnt care este identic citit de la nceput spre sfrsit ca si de la sfrsit spre
nceput (de exemplu: cazac, elevele, cojoc).
2. Un numar real are diagrama sintactica prezentata n Figura 4.1. Scrieti o functie care converteste un
sir de caractere, ce respecta aceasta diagrama, n valoarea reala corespunzatoare. Functia primeste
ca parametru pointerul la sirul de convertit si returneaza valoarea reala calculata. Functia elimina
eventualele spatii ce preced numarul. Scrieti un program care citeste repetat de la intrare siruri de
caractere si, folosind functia anterioara, afiseaza valoarea numerica a sirului citit. Programul se
termina prin introducerea numarului 0. n caz ca un sir de caractere nu respecta diagrama
sintactica, programul se termina cu un mesaj de eroare care specifica exact ce neconcordanta cu
diagrama a avut loc.

\begin{figure}\begin{center}
\epsfig{file=diagrama.eps, width=\textwidth} \end{center} \end{figure}

Figura 4.1: Diagrama sintactica a unui numar real


next

up

previous

contents

Next: Prelucrarea fisierelor Up: Caractere, siruri de caractere. Previous: Probleme rezolvate Cuprins
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node29.html [22.07.2003 16:18:09]

Prelucrarea fisierelor

next

up

previous

contents

Next: Tratarea fisierelor n C Up: carte Previous: Probleme propuse Cuprins

Prelucrarea fisierelor
Subsections
Tratarea fisierelor n C

Operatii asupra fisierelor

Deschiderea/nchiderea fisierelor

Alte functii referitoare la fisiere

Citirea si modificarea indicatorului de pozitie

Transferul caracterelor si al sirurilor de caractere

Citirea si scrierea cu format

Probleme rezolvate

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node30.html [22.07.2003 16:18:10]

Tratarea fisierelor n C

next

up

previous

contents

Next: Operatii asupra fisierelor Up: Prelucrarea fisierelor Previous: Prelucrarea fisierelor Cuprins

Tratarea fisierelor n C
n C, operatiile de intrare/iesire au la baza conceptul de stream. Un stream (flux)
este o interfata logica ntre diverse dispozitive ale unui calculator. n mod uzual,
un stream este o interfata logica pentru un fisier. Conceptul de fisier, n C este
mai larg dect n alte limbaje de programare, el incluznd un fisier pe suport
permanent (hard-disk, CD, etc.), ecranul, tastatura, diverse porturi, s.a.m.d.
Tratarea unitara a tuturor operatiilor de intrare/iesire prin intermediul
stream-urilor asigura o mai mare portabilitate limbajului C, ct si o transparenta
pentru programator fata de arhitectura masinii pe care lucreaza.
Un stream este asociat unui fisier printr-o operatie de deschidere (open), asocierea
distrugndu-se prin operatia de nchidere a stream-ului (close).
Exista doua tipuri de stream-uri: text si binare. Ceea ce diferenteaza cele doua
tipuri este existenta unor translatii n cazul stream-urile text. De exemplu,
caraterul newline (sfrsit de linie) cnd este ntlnit este convertit ntr-o secventa
de doua caractere carriage-return/linefeed (ntoarcere/deplasare rnd). Din acest
motiv, poate sa apara o diferenta ntre ceea ce este trimis la stream si ceea ce este
scris fizic n fisier.
n cazul stream-urilor binare, exista o perfecta concordanta ntre stream si fisierul
fizic, astfel stream-urile binare pot fi folosite cu orice tip de date, pe cnd n
cazul celor de tip text exista anumite limitari. Exista sisteme de operare (cum ar fi
Unix-ul) n care nu exista stream-uri de tip text.
La deschiderea unui stream, se asociaza acestuia un pointer la o structura de tip
FILE (fisier). Aceasta structura, definita n stdio.h, retine diverse informatii
legate de fisierul deschis (dimensiune, pozitia curenta a cursorului n fisier,
moduri de acces). Prin operatia de deschidere, se rezerva automat si o zona
tampon pentru transferul datelor.
http://labs.cs.utt.ro/labs/pc/html/node31.html (1 of 2) [22.07.2003 16:18:10]

Tratarea fisierelor n C

next

up

previous

contents

Next: Operatii asupra fisierelor Up: Prelucrarea fisierelor Previous: Prelucrarea fisierelor Cuprins
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node31.html (2 of 2) [22.07.2003 16:18:10]

Operatii asupra fisierelor

next

up

previous

contents

Next: Deschiderea/nchiderea fisierelor Up: Prelucrarea fisierelor Previous: Tratarea fisierelor n C


Cuprins

Operatii asupra fisierelor


Subsections
Deschiderea/nchiderea fisierelor

Alte functii referitoare la fisiere

Citirea si modificarea indicatorului de pozitie

Transferul caracterelor si al sirurilor de caractere

Citirea si scrierea cu format

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node32.html [22.07.2003 16:18:10]

Deschiderea/nchiderea fisierelor

next

up

previous

contents

Next: Alte functii referitoare la Up: Operatii asupra fisierelor Previous: Operatii asupra fisierelor
Cuprins

Deschiderea/nchiderea fisierelor
La lansarea n executie a unui program se deschid trei fisiere cu canale de tip text:
stdin
- pentru intrarea standard, asociat implicit tastaturii;
stdout
- pentru iesirea standard, asociat implicit ecranului monitorului;
stderr
- pentru iesirea standard pentru erori, asociat implicit ecranului monitorului.

Orice alte fisiere utilizate n program trebuie deschise n mod explicit cu functia
fopen.
FILE *fopen(const char *filename, const char *mode);
Prin aceasta se deschide fisierul cu numele filename (care poate include si
specificarea caii), i se asociaza un stream si se returneaza un pointer catre
structura FILE creata sau NULL, daca fisierul nu a putut fi deschis. Acest pointer
este folosit n operatiile ulterioare asupra fisierului.
Parametrul mode este un sir de caractere care poate avea urmatoarele valori:
r
deschide pentru citire;
w
deschide pentru scriere (daca fisierul exista anterior el va fi sters);
a
deschide pentru adaugare (scriere la sfrsitul fisierului);
r+
deschide un fisier existent pentru actualizare (citire si scriere);
w+
deschide un fisier nou pentru actualizare;

http://labs.cs.utt.ro/labs/pc/html/node33.html (1 of 2) [22.07.2003 16:18:10]

Deschiderea/nchiderea fisierelor

a+
deschide pentru actualizare la sfrsitul fisierului.

La sfrsitul sirului de caractere reprezentnd modul de acces se mai poate adauga


optional sufixul:
t
pentru prelucrare n mod text (implicit);
b
pentru prelucrare n mod binar.

nchiderea unui fisier deschis cu fopen se realizeaza cu functia fclose:


int fclose(FILE *fp);
unde fp este pointerul returnat de functia fopen. Prin nchiderea fisierului se
elibereaza si zona tampon alocata acestuia. Functia returneaza valoarea 0 daca
operatia de nchidere s-a efectuat cu succes, respectiv EOF (-1) n caz de eroare.
next

up

previous

contents

Next: Alte functii referitoare la Up: Operatii asupra fisierelor Previous: Operatii asupra fisierelor
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node33.html (2 of 2) [22.07.2003 16:18:10]

Alte functii referitoare la fisiere

next

up

previous

contents

Next: Citirea si modificarea indicatorului Up: Operatii asupra fisierelor Previous:


Deschiderea/nchiderea fisierelor Cuprins

Alte functii referitoare la fisiere


int feof(FILE *fp);
returneaza o valoare nenula daca s-a ntlnit sfrsitul de fisier la ultima operatie
de intrare si 0 n caz contrar.

int fflush(FILE *fp);


determina golirea buffer-ului unui fisier.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node34.html [22.07.2003 16:18:11]

Citirea si modificarea indicatorului de pozitie

next

up

previous

contents

Next: Transferul caracterelor si al Up: Operatii asupra fisierelor Previous: Alte functii referitoare la
Cuprins

Citirea si modificarea indicatorului de pozitie


int fgetpos(FILE *fp, long int *poz);
nscrie valoarea indicatorului de pozitie n variabila adresata prin pointerul poz si
returneaza 0 n caz de succes.

int fsetpos(FILE *fp, const long int *poz);


atribuie indicatorului valoarea variabilei indicata prin pointerul poz si returneaza
valoarea 0 n caz de succes.

int fseek(FILE *fp, long offset, int whence);


repozitioneaza indicatorul fisierului la valoarea whence+offset; whence poate
avea urmatoarele valori:
SEEK_SET
= 0 - nceput de fisier
SEEK_CUR
= 1 - pozitie curenta
SEEK_END
= 2 - sfrsit de fisier

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node35.html [22.07.2003 16:18:11]

Transferul caracterelor si al sirurilor de caractere

next

up

previous

contents

Next: Citirea si scrierea cu Up: Operatii asupra fisierelor Previous: Citirea si modificarea indicatorului
Cuprins

Transferul caracterelor si al sirurilor de caractere


int getc(FILE *fp);
returneaza urmatorul caracter citit din fisierul fp sau EOF daca se ntlneste
sfrsitul fisierului.

int ungetc(int c, FILE *fp);


repune caracterul c n zona tampon corespunzatoare fisierului de intrare fp.

int putc(int c, FILE *fp);


nscrie caracterul c n fisierul fp; n caz de eroare returneaza EOF.

char *fgets(char *s, int n, FILE *fp);


citeste maxim n-1 caractere din fisierul fp sau pna la '' $\backslash$
n'' inclusiv, le depune n
s, adauga la sfrsit '' $\backslash$
0'' si returneaza adresa sirului s; n caz de eroare ntoarce
valoarea NULL.

http://labs.cs.utt.ro/labs/pc/html/node36.html (1 of 2) [22.07.2003 16:18:11]

Transferul caracterelor si al sirurilor de caractere

int fputs(const char *s, FILE *fp);


scrie sirul s n fisier, fara caracterul '' $\backslash$
0''; n caz de eroare ntoarce valoarea EOF.

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node36.html (2 of 2) [22.07.2003 16:18:11]

Citirea si scrierea cu format

next

up

previous

contents

Next: Probleme rezolvate Up: Operatii asupra fisierelor Previous: Transferul caracterelor si al Cuprins

Citirea si scrierea cu format


int fscanf(FILE *fp, const char *format [, adresa,
...]);
citeste date din fisierul fp, conform formatului specificat; returneaza numarul
cmpurilor de intrare pentru care citirea, conversia si memorarea s-au efectuat
corect sau EOF daca s-a ntlnit sfrsitul fisierului.

int fprintf(FILE *fp, const char *format [,


argum...]);
scrie date, conform formatului n fisierul fp; returneaza numarul de octeti
transferati sau EOF n caz de eroare.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node37.html [22.07.2003 16:18:11]

Probleme rezolvate

next

up

previous

contents

Next: Probleme propuse Up: Prelucrarea fisierelor Previous: Citirea si scrierea cu Cuprins

Probleme rezolvate
1. Sa se scrie un program care afiseaza lungimea celei mai lungi linii din fisierul text TEST:
/*------------------------------------------------*/
/*
*/
/* afiseaza lungimea lg_max a celei mai lungi
*/
/*
linii a fisierului
*/
/*
*/
/*------------------------------------------------*/
#include <stdio.h>
void main(void)
{
FILE *f;
char c;
int lg_max, lg_curenta;
lg_max=lg_curenta=0;
if (!(f=fopen("TEST", "r")))
{
puts("Fisierul TEST nu poate fi deschis");
return;
}
while ((c=getc(f))!=EOF)
if (c=='\n')
{
if (lg_max<lg_curenta)
lg_max = lg_curenta;
lg_curenta = 0;
}
else
lg_curenta++;

http://labs.cs.utt.ro/labs/pc/html/node38.html (1 of 6) [22.07.2003 16:18:12]

Probleme rezolvate

fclose(f);
printf ("\nLinia cea mai lunga are lungimea %d", lg_max);
}
2. Sa se scrie un program care copiaza un fisier binar sursa n alt fisier binar destinatie.
/*---------------------------------------*/
/*
*/
/* copiaza continutul unui fisier binar */
/*
in alt fisier binar
*/
/*
*/
/----------------------------------------*/
#include <stdio.h>
void main(void)
{
FILE *fs, *fd;
char c;
if ((fs=fopen("sursa", "rb"))==NULL)
{
fprintf(stderr, "Fisierul sursa nu poate fi deschis\n");
return;
}
if ((fd=fopen("dest", "wb"))==NULL)
{
fprintf(stderr, "Fisierul dest nu poate fi deschis\n");
return;
}
c=getc(fs);
while (!feof(fs))
{
putc(c, fd);
c=getc(fs);
}
fclose(fs);
fclose(fd);
}
3. Sa se realizeze un program care pastreaza evidenta unei grupe de studenti. Datele despre studenti
(numele, vrsta, media) se pastreaza sub forma unui fisier text. Programul trebuie sa permita
urmatoarele optiuni:
a, A - adaugarea unui nou student n fisier;
http://labs.cs.utt.ro/labs/pc/html/node38.html (2 of 6) [22.07.2003 16:18:12]

Probleme rezolvate

l, L - listarea datelor tuturor studentilor;


m, M - modificarea datelor unui student;
x, X - terminarea programului;

/*----------------------------------------------*/
/*
*/
/*
evidenta unei grupe de studenti
*/
/*
*/
/*----------------------------------------------*/
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#define LNUME 20 /* lungimea maxima a numelor

*/

typedef struct
{
char nume[LNUME];
int varsta;
float medie;
} student;
char fisier[13];

/* numele fisierului */

/*---------------------------------------------------*/
/*
*/
/* adauga datele unui nou student in fisier
*/
/*
*/
/----------------------------------------------------*/
void AdaugStudent(void)
{
FILE *f;
student s;
if (!(f=fopen(fisier, "at")))
{
puts("\nFisierul nu poate fi deschis.");
return;
}
printf("\nNumele, varsta, media: ");
scanf("%s %d %f", s.nume, &s.varsta, &s.medie);
http://labs.cs.utt.ro/labs/pc/html/node38.html (3 of 6) [22.07.2003 16:18:12]

Probleme rezolvate

fflush(stdin); /* se goleste buffer-ul tastaturii */


fprintf(f, "%20s %2d %6.2f\n", s.nume, s.varsta, s.medie);
fclose(f);
}
/*-------------------------------------------*/
/*
*/
/* afiseaza datele tuturor studentilor
*/
/*
*/
/*--------------------------------------------*/
void ListezStudenti(void)
{
FILE *f;
student s;
if (!(f=fopen(fisier, "rt")))
{
puts("\nFisierul nu poate fi deschis.");
return;
}
while(fscanf(f,"%s %d %f",s.nume,&s.varsta,&s.medie)!=EOF)
printf("\n%-20s %-2d %-6.2f\n",s.nume,s.varsta,s.medie);
fclose(f);
}

/*-----------------------------------------------*/
/*
*/
/*
modifica datele studentului
*/
/*
al carui nume se citeste in variabila n
*/
/*
*/
/*-----------------------------------------------*/
void ModificStudent(void)
{
int gasit=0;
FILE *f;
student s;
char n[LNUME]; /* numele studentului ale */
/* carui date se vor modifica */
if (!(f=fopen(fisier, "r+t")))
http://labs.cs.utt.ro/labs/pc/html/node38.html (4 of 6) [22.07.2003 16:18:12]

Probleme rezolvate

{
puts("Fisierul nu poate fi deschis.");
return;
}
printf("\nNume student: ");
fgets(n, LNUME, stdin);
while(fscanf(f,"%s %d %f",s.nume,&s.varsta,&s.medie)!=EOF)
if (!strcmp(n,s.nume))
{ /* studentul a fost gasit, se afiseaza datele sale */
printf("%-20s %-2d %-6.2f\n",s.nume,s.varsta,s.medie);
gasit=1;
break;
}
if (!gasit)
printf("\nStudentul %s nu exista in fisier.", n);
else
{
printf("\nNumele, varsta, media: ");
scanf("%s %d %f", s.nume, &s.varsta, &s.medie);
fflush(stdin);
/* pozitionare la inceputul inregistrarii */
fseek(f, -30, SEEK_CUR);
fprintf(f,"%20s %2d %6.2f\n", s.nume, s.varsta, s.medie);
}
fclose(f);
}
/*----------------------------------*/
/*
*/
/*
afiseaza meniul programului
*/
/*
*/
/*----------------------------------*/
void AfisezMeniu(void)
{
puts("\na, A ---- adaugare student");
puts("m, M ---- modificare date student");
puts("l, L ---- listare studenti");
puts("x, X ---- parasire program");
}
http://labs.cs.utt.ro/labs/pc/html/node38.html (5 of 6) [22.07.2003 16:18:12]

Probleme rezolvate

void main(void)
{
char opt;
puts("Nume fisier: ");
fgets(fisier, 13, stdin);
while (1)
{
AfisezMeniu();
opt=tolower(getche());
switch(opt)
{
case 'a':
AdaugStudent(); break;
case 'm':
ModificStudent(); break;
case 'l':
ListezStudenti(); break;
case 'x':
exit(0);
default:
puts("Comanda eronata\n");
}
}
}
Se observa ca cele trei operatii principale efectuate asupra fisierului: adaugare, listare si modificare
sunt implementate n trei functii distincte.
Functia adauga nscrie n fisier datele unui student sub forma unei nregistrari de 30 de octeti (20
pentru nume, 1 spatiu, 2 pentru vrsta, 1 spatiu, 6 pentru medie). Acest lucru este folosit n functia
modifica cnd se repozitioneaza indicatorul de pozitie n fisier la nceputul nregistrarii care
urmeaza a fi modificata.
next

up

previous

contents

Next: Probleme propuse Up: Prelucrarea fisierelor Previous: Citirea si scrierea cu Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node38.html (6 of 6) [22.07.2003 16:18:12]

Probleme propuse

next

up

previous

contents

Next: Compilarea independenta a fisierelor Up: Prelucrarea fisierelor Previous: Probleme rezolvate
Cuprins

Probleme propuse
1. Se considera doua fisiere care contin numere ntregi n ordine strict crescatoare, cte un numar pe
o linie. Se cere sa se creeze un al treilea fisier, obtinut prin interclasarea primelor doua. Daca un
numar apare n ambele fisiere de intrare, el va aparea o singura data n fisierul rezultat.
De exemplu:
fisier1: -1 0 4 5 67 123 678 2677
fisier2: 8 12 123 1234 1235 1236 7890 7892
fisier3 (rezultat): -1 0 4 5 8 12 67 123 678 1234 1235 1236 2677 7890 7892
2. Scrieti un program care concateneaza doua fisiere, FIS1 si FIS2 n fisierul FIS3.
3. Dintr-un fisier de intrare se citeste o propozitie terminata cu punct. Propozitia este formata din
cuvinte ce contin doar litere mari. Cuvintele sunt separate prin unul sau mai multi separatori din
t'','' $\backslash$
n''. Stiind ca propozitia are cel mult 30 de cuvinte, sa se afiseze grupurile de
multimea '' '','' $\backslash$
cuvinte n care fiecare membru reprezinta anagrama altui membru din grup. Un grup va contine
numarul maxim de membri, iar membrii sunt distincti.
next

up

previous

contents

Next: Compilarea independenta a fisierelor Up: Prelucrarea fisierelor Previous: Probleme rezolvate
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node39.html [22.07.2003 16:18:12]

Compilarea independenta a fisierelor

next

up

previous

contents

Next: Etapele compilarii unui program Up: carte Previous: Probleme propuse Cuprins

Compilarea independenta a fisierelor


Subsections
Etapele compilarii unui program C

Preprocesarea

Compilarea

Link-editare

Structurarea programelor C pe mai multe fisiere

De ce mai multe fisiere ?

Reguli de structurare pe mai multe fisiere

Lucrul n modul "project"

Tipuri de date abstracte

Definirea tipului abstract stiva

Evaluarea unei expresii n notatie poloneza

Probleme propuse

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node40.html [22.07.2003 16:18:12]

Etapele compilarii unui program C

next

up

previous

contents

Next: Preprocesarea Up: Compilarea independenta a fisierelor Previous: Compilarea independenta a


fisierelor Cuprins

Etapele compilarii unui program C


Pentru a putea ntelege modul n care sunt compilate programele n C (indiferent
de dimensiunea lor), vom trece n revista principalele etape care au loc pna la
obtinerea codului final executabil. Aceste etape sunt transparente pentru
programator n majoritatea compilatoarelor sau mediilor integrate, nefiind
necesara activarea lor separata. n unele situatii nsa (de obicei, pentru programele
structurate pe mai multe fisiere), anumite etape se pot desfasura independent.
Subsections
Preprocesarea

Compilarea

Link-editare

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node41.html [22.07.2003 16:18:13]

Preprocesarea

next

up

previous

contents

Next: Compilarea Up: Etapele compilarii unui program Previous: Etapele compilarii unui program
Cuprins

Preprocesarea
Preprocesarea este prima faza n obtinerea codului executabil. n aceasta etapa au
loc anumite transformari asupra codului sursa, rezultnd un fisier intermediar tot
n limbajul C.
Principalele operatii care au loc n aceasta faza sunt prelucrarea directivelor de
preprocesare (liniile care ncep cu caracterul #): expandarea macrodefinitiilor si
includerea fisierelor.
Expandarea macrodefinitiilor presupune nlocuirea textuala a macro-ului cu
valoarea asociata. De exemplu, pentru definitia
#define MAX 10
se va nlocui n textul sursa fiecare aparitie a sirului MAX cu numarul 10.
n faza de includere a fisierelor, toate fisierele specificate de directivele
#include vor fi incluse textual n codul sursa al programului. n paragrafele
urmatoare vor fi prezentate anumite reguli generale referitoare la continutul
fisierelor incluse.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node42.html [22.07.2003 16:18:13]

Compilarea

next

up

previous

contents

Next: Link-editare Up: Etapele compilarii unui program Previous: Preprocesarea Cuprins

Compilarea
n faza de compilare, codul sursa al programului este transformat n cod obiect
(un cod intermediar specific compilatorului de C). Dupa compilare, se creeaza un
fisier cu acelasi nume, dar cu extensia .obj. n aceasta faza sunt semnalate
posibilele erori sintactice din codul sursa.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node43.html [22.07.2003 16:18:13]

Link-editare

next

up

previous

contents

Next: Structurarea programelor C pe Up: Etapele compilarii unui program Previous: Compilarea
Cuprins

Link-editare
Linkeditare (editarea legaturilor) "leaga" ntre ele mai multe fisiere obiect si
creaza fisierul executabil. Aceasta faza este importanta pentru programe
structurate pe mai multe fisiere, dar si pentru programe constnd dintr-un singur
fisier (pentru legarea fisierelor obiect ale bibliotecilor de functii specificate prin
#include).
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node44.html [22.07.2003 16:18:13]

Structurarea programelor C pe mai multe fisiere

next

up

previous

contents

Next: De ce mai multe Up: Compilarea independenta a fisierelor Previous: Link-editare Cuprins

Structurarea programelor C pe mai multe


fisiere
Subsections
De ce mai multe fisiere ?

Reguli de structurare pe mai multe fisiere

Lucrul n modul "project"

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node45.html [22.07.2003 16:18:13]

De ce mai multe fisiere ?

next

up

previous

contents

Next: Reguli de structurare pe Up: Structurarea programelor C pe Previous: Structurarea programelor C


pe Cuprins

De ce mai multe fisiere ?


Utilitatea structurarii programelor C mari pe mai multe fisiere este explicata de
urmatoarele avantaje:

next

n cazul programelor mari, daca tot programul ar fi scris ntr-un singur fisier, programul ar fi foarte
greu de urmarit si timpul de compilare ar fi foarte mare, nefiind folosita facilitatea de compilare
independenta. Acest aspect este foarte util n faza de corectare a erorilor sintactice si semantice,
cnd doar fisierul eronat trebuie recompilat, pentru restul fisierelor trebuind doar linkeditate
fisierele obiect. Daca ntregul program este plasat ntr-un singur fisier atunci orice modificare sau
corectie impune recompilarea ntregului program.
Structurarea programelor pe mai multe fisiere permite simularea mecanismului de ncapsulare a
datelor. Variabilele si functiile avnd clasa de memorare static pot fi accesate doar n cadrul
fisierului n care ele au fost definite. Variabilele si functiile declarate cu clasa de memorare extern
sunt definite ntr-un alt fisier dect cel curent, dar ele pot fi accesate n fisierul curent. Astfel
fisierele apar n C ca un mecanism de control al vizibilitatii obiectelor.
up

previous

contents

Next: Reguli de structurare pe Up: Structurarea programelor C pe Previous: Structurarea programelor C


pe Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node46.html [22.07.2003 16:18:14]

Reguli de structurare pe mai multe fisiere

next

up

previous

contents

Next: Lucrul n modul "project" Up: Structurarea programelor C pe Previous: De ce mai multe
Cuprins

Reguli de structurare pe mai multe fisiere


Vom prezenta n continuare anumite reguli general acceptate pentru structurarea
unui program pe mai multe fisiere.
n general, se alege un fisier care va fi fisierul principal, n acest fisier fiind
implementata functia main(); n celelalte fisiere nu va mai fi implementata
aceasta functie. n fisierul antet se vor trece definitia tipurilor de date folosite si
declaratiile (prototipurile) functiilor. Nu se vor trece n fisierul antet declaratii de
variabile si implementari de functii (este perfect "legal" sa apara declaratii de
variabile si implementari de functii, fisierul antet fiind tratat ca orice fisier C, dar
aceasta maniera de programare distruge conceptul de modularizare a programelor
si de ncapsulare a datelor). n fisierul auxiliar antetului (cu acelasi nume si
extensia .c) se va trece implementarea functiilor definite n fisierul antet. n acest
fisier nu se va implementa functia main(). Att fisierul principal ct si cel auxiliar
vor include fisirul antet. Astfel se realizeaza ncapsularea tipurilor de date si a
functiilor n fisiere separate.
Aceasta maniera de structurare a programelor este folosita n scrierea unor
biblioteci de functii. Programatorul care doreste sa furnizeze o biblioteca de
functii va scrie fisierul antet si fisierul auxiliar antetului, care va include fisierul
antet. n fisierul antet vor fi trecute functiile si tipurile de date oferite de
biblioteca, iar n fisierul auxiliar vor fi implementate aceste functii. Aceste fisiere
se compileaza mpreuna, rezultnd un fisier obiect (nu executabil), iar biblioteca
va oferi acces la aceste functii prin includerea n orice program a fisierului antet si
prin linkeditarea cu fisierul obiect. Programatorul acestei biblioteci nu va oferi
spre utilizare dect fisierul antet si fisierul obiect, astfel maniera de implementare
a functiilor oferite de biblioteca ramne invizibila pentru utilizatorul bibliotecii.

http://labs.cs.utt.ro/labs/pc/html/node47.html (1 of 4) [22.07.2003 16:18:14]

Reguli de structurare pe mai multe fisiere

Pentru a exemplifica aceste reguli, consideram un program pentru calculul sumei


a doua numere complexe. Pentru aceasta, se va defini o functie suma. De
asemenea, vor fi definite si doua functii pentru citirea, respectiv afisarea
numerelor complexe.
Programul va fi structurat pe trei fisiere: calcule.c - care contine functia main,
operatii.h - fisierul antet unde sunt declarate principalele tipuri de date si functii
si operatii.c - implementarea functiilor.
Fisierele sursa sunt prezentate n continuare.

Fisierul calcule.c
#include <stdio.h>
#include "operatii.h"
void main(void)
{
complex x,y;
printf("introduceti primul numar\n");
x=citire();
printf("introduceti al 2-lea numar\n");
y=citire();
printf("\nsuma: ");
afisare(suma(x,y));
printf("\n");
}

Fisierul operatii.h
/* definire tip de date complex */
typedef struct nr_complex
{
double p_real;
double p_imag;
} complex;
/* prototipuri functii exportate */
http://labs.cs.utt.ro/labs/pc/html/node47.html (2 of 4) [22.07.2003 16:18:14]

Reguli de structurare pe mai multe fisiere

complex citire(void);
void afisare(complex);
complex suma(complex,complex);

Fisierul operatii.c
#include <stdio.h>
#include "operatii.h"
/* implementare functii exportate */
complex citire(void)
{
complex nr;
printf("Partea reala: ");
scanf("%lf",&nr.p_real);
printf("Partea imaginara: ");
scanf("%lf",&nr.p_imag);
return nr;
}

void afisare(complex nr)


{
if (nr.p_imag<0)
printf("%lf%lfi\n",nr.p_real,nr.p_imag);
else
printf("%lf+%lfi\n",nr.p_real,nr.p_imag);
}
complex suma(complex nr1, complex nr2)
{
complex rezult;
rezult.p_real=nr1.p_real + nr2.p_real;
rezult.p_imag=nr1.p_imag + nr2.p_imag;
return rezult;
}
next

up

previous

contents

Next: Lucrul n modul "project" Up: Structurarea programelor C pe Previous: De ce mai multe

http://labs.cs.utt.ro/labs/pc/html/node47.html (3 of 4) [22.07.2003 16:18:14]

Reguli de structurare pe mai multe fisiere

Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node47.html (4 of 4) [22.07.2003 16:18:14]

Lucrul n modul "project"

next

up

previous

contents

Next: Tipuri de date abstracte Up: Structurarea programelor C pe Previous: Reguli de structurare pe
Cuprins

Lucrul n modul "project"


Pentru a compila fisierele si a le "linkedita" mpreuna folosim modul project. n
mediul Borland C acest lucru presupune urmatorii pasi:

Selectam optiunea Project si apoi Open project.


Fixam numele fisierului project (care are extensia .prj).
Cu ajutorul butonul Ins precizam fisierele care trebuie compilate si apoi linkeditate mpreuna.
Fisierele antet nu se includ n project. Cu butonul Del fisierul selectat este eliminat din grupul
celor care sunt compilate si linkeditate mpreuna.
Selectam optiunea pentru construirea programului executabil (din meniul Compile, optiunea Build
all. Mediul Borland C compileaza automat toate fisierele enumerate si le linkediteaza mpreuna.
Prin selectarea optiunii Project si apoi a celei Close project, se ncheie lucrul n modul Project.

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node48.html [22.07.2003 16:18:14]

Tipuri de date abstracte

next

up

previous

contents

Next: Definirea tipului abstract stiva Up: Compilarea independenta a fisierelor Previous: Lucrul n
modul "project" Cuprins

Tipuri de date abstracte


Tipul de date abstract este o entitate manipulata doar prin operatiile ce definesc
acel tip. Avantajele utilizarii tipurilor de date abstracte sunt:
1. Programele devin independente de modul de reprezentare a datelor. Modul de reprezentare poate fi
modificat, fara nsa a afecta restul programului (de exemplu, o multime poate fi implementata
printr-un tablou sau printr-o lista ordonata, dar partea de program ce foloseste operatorii tipului
abstract ramne neschimbata).
2. Se previne violarea accidentala a datelor. Utilizatorul tipului abstract este fortat sa manipuleze
datele doar prin intermediul operatorilor ce compun tipul abstract, astfel reducndu-se riscul unei
distrugeri a datelor.

Dupa cum este exemplificat n continuare, n C tipurile abstracte sunt realizate


folosind fisiere. Acest mod are desigur propriile sale limitari. Mentionam doar
doua din ele: nu se pot defini tablouri de tipuri abstracte si nu se pot transmite
parametri avnd ca si tip un tip abstract.
Subsections
Definirea tipului abstract stiva

next

Evaluarea unei expresii n notatie poloneza


up

previous

contents

Next: Definirea tipului abstract stiva Up: Compilarea independenta a fisierelor Previous: Lucrul n
modul "project" Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node49.html [22.07.2003 16:18:15]

Definirea tipului abstract stiva

next

up

previous

contents

Next: Evaluarea unei expresii n Up: Tipuri de date abstracte Previous: Tipuri de date abstracte
Cuprins

Definirea tipului abstract stiva


Stiva este un tip special de lista n care toate insertiile si suprimarile de noduri au
loc la un singur capat. Acest capat se numeste vrful stivei.
Tipul abstract stiva pe care l definim contine urmatorii operatori:
1.
2.
3.
4.
5.
6.

Initializarea stivei.
Verificarea faptului ca stiva e plina.
Verificarea faptului ca stiva e goala.
Introducerea unui element n vrful stivei.
Eliminarea elementului din vrful stivei.
Furnizarea elementului din vrful stivei fara a-l elimina.

n exemplul nostru, stiva este materializata printr-un tablou de numere reale,


numit stiva, iar vrful stivei este indicat de variabila ind_top. Dimensiunea stivei
este egala cu MAX, valoare care este lungimea tabloului.
Toate declaratiile si definitiile care urmeaza mai jos trebuie sa fie continute
ntr-un singur fisier. Pentru a "ascunde" de utilizator detaliile de implementare a
stivei, att stiva ct si ind_top sunt definite cu clasa de memorare static. Astfel
domeniul lor de vizibilitate se restrnge la fisierul curent si aceste variabile nu pot
fi accesate dintr-un alt fisier.
Functiile au implicit clasa de memorare extern. Prin urmare, ele pot fi apelate din
alte fisiere, iar toate operatiile asupra stivei sunt realizate doar prin intermediul
lor.
static double stiva[MAX]; /* stiva */
static int ind_top; /* varful stivei */

http://labs.cs.utt.ro/labs/pc/html/node50.html (1 of 4) [22.07.2003 16:18:15]

Definirea tipului abstract stiva

Operatorii sunt implementati astfel:

Initializarea stivei:
void init(void)
{
int i;
for (i=0; i<MAX; i++)
stiva[i]=0; /* toate elementele devin 0 */
ind_top=-1; /* varful stivei indica primul element ocupat*/
} /* init */

Verificarea faptului ca stiva este plina:


int plin(void)
{
return ind_top==MAX-1;
} /* plin */

Stiva este plina atunci cnd vrful stivei indica spre ultimul element din stiva (cel
de indice MAX-1).

Verificarea faptului ca stiva este goala:


int gol(void)
{
return ind_top==-1;
} /* gol */

http://labs.cs.utt.ro/labs/pc/html/node50.html (2 of 4) [22.07.2003 16:18:15]

Definirea tipului abstract stiva

Functia gol verifica daca stiva este goala. Cnd indicele stivei este egal cu -1,
stiva nu contine nici o valoare si gol returneaza 1. Daca ind_top $>$-1 atunci stiva
contine cel putin o valoare, astfel ca gol returneaza 0.

Introducerea unui element n vrful stivei:


void push(double nr)
{
if (plin()) /* daca stiva este plina */
{
printf("Eroare: stiva este plina\n");
exit(1);
}
stiva[++ind_top] = nr; /* noul element este
introdus in varful stivei */
} /* push */

Rutina push introduce n vrful stivei numarul transmis prin parametrul double
nr. Daca stiva este plina atunci se afiseaza un mesaj de eroare si executia
programului este terminata. n caz contrar, se incrementeaza vrful stivei ind_top,
dupa care noul element este memorat n vrful stivei.

Eliminarea elementului din vrful stivei:


void pop(void)
{
if (gol() ) /* daca stiva este goala */
{
printf("Eroare: stiva este goala\n");
exit(1);
}
ind_top--; /* decrementeaza varful stivei */
} /* pop */

http://labs.cs.utt.ro/labs/pc/html/node50.html (3 of 4) [22.07.2003 16:18:15]

Definirea tipului abstract stiva

Rutina pop extrage elementul din vrful stivei fara a-l returna. Daca stiva este
goala atunci pop afiseaza un mesaj de eroare si executia programului este
ncheiata. n caz contrar, vrful stivei este decrementat.

Furnizarea elementului din vrful stivei (fara a-l elimina):


double top(void)
{
if (gol()) /* daca stiva este goala */
{
printf("Eroare: stiva este goala\n");
exit(1);
}
return stiva[ind_top]; /* returneaza
elementul din varful stivei */
} /* top */

Functia top returneaza valoarea elementului din vrful stivei, nsa fara a-l extrage.
Daca stiva este goala atunci se afiseaza un mesaj de eroare si executia
programului este ncheiata. n caz contrar, top returneaza valoarea din vrful
stivei.
next

up

previous

contents

Next: Evaluarea unei expresii n Up: Tipuri de date abstracte Previous: Tipuri de date abstracte
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node50.html (4 of 4) [22.07.2003 16:18:15]

Evaluarea unei expresii n notatie poloneza

next

up

previous

contents

Next: Probleme propuse Up: Tipuri de date abstracte Previous: Definirea tipului abstract stiva
Cuprins

Evaluarea unei expresii n notatie poloneza


Notatia poloneza (sau postfix) este un mod de scriere a expresiilor, n care ordinea
operatorilor si a operanzilor este schimbata fata de cea dintr-o expresie uzuala.
n notatia uzuala (numita si infix) o expresie are forma:
operand operator operand
n notatia postfix (poloneza) expresia este scrisa sub forma:
operand operand operator
De exemplu:
a + b devine n notatie poloneza a b +
(a - b) * c devine a b - c *
a - b * (c + d) devine a b c d + * Avantajul notatiei poloneze este acela ca indica ordinea corecta a evaluarii
operatiilor fara a utiliza paranteze. Astfel, o expresie poloneza poate fi evaluata
printr-o singura parcurgere a sa.
Pentru evaluarea unei expresii n notatie poloneza se poate folosi o stiva de valori
reale. Ori de cte ori ntlnim n expresie un operand, valoarea lui este introdusa
n stiva. Daca ntlnim un operator atunci se extrag doua valori din vrful stivei,
care sunt, de fapt, cei doi operanzi, aplicam operatorul asupra valorilor extrase si
rezultatul l depunem n stiva. n momentul n care s-a terminat parcurgerea
expresiei, rezultatul final al expresiei este n vrful stivei (si stiva contine doar
aceasta valoare).
next

up

previous

contents

http://labs.cs.utt.ro/labs/pc/html/node51.html (1 of 2) [22.07.2003 16:18:15]

Evaluarea unei expresii n notatie poloneza

Next: Probleme propuse Up: Tipuri de date abstracte Previous: Definirea tipului abstract stiva
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node51.html (2 of 2) [22.07.2003 16:18:15]

Probleme propuse

next

up

previous

contents

Next: Pointeri Up: Compilarea independenta a fisierelor Previous: Evaluarea unei expresii n Cuprins

Probleme propuse
1. Se citeste o expresie n notatie poloneza, care contine ca operanzi constante reale, iar ca operatori
+, -, * si /. Fiecare expresie apare pe o linie separata. Dupa ce s-a citit expresia, ea este evaluata si
rezultatul ei este tiparit. Programul citeste expresii si le evalueaza pna la citirea unui 0 singular pe
o linie.
Observatii:
Ca stiva se foloseste tipul abstract stiva cu valori reale, definit anterior.
Se va defini functia getop (char *s), care citeste ncepnd cu pozitia curenta a liniei
de intrare si detecteaza urmatorul operand sau operator. getop sare peste spatii si caracterele
tab. Pentru un operand, functia returneaza constanta NUMAR si, n parametrul s, adresa de
nceput a sirului format din cifrele numarului. Pentru un operator, getop returneaza
caracterul citit, iar n parametrul s adresa de nceput a sirului format din acel caracter.
Programul va fi mpartit n trei fisiere: stiva.h - contine definitiile constantelor si a tipurilor
de date folosite n program, precum si declaratiile functiilor ce prelucreaza tipul abstract
stiva. stiva.c - contine implementarea tipului abstract stiva. main.c - contine programul
principal precum si functia getop.
2. Sa se realizeze un program C ce tine evidenta personalului unei companii de dimensiuni mici
(aproximativ 50 de angajati). Informatia referitoare la angajati este pastrata ntr-un fisier si este
folosita pentru initializarea bazei de date. Fisierul contine linii de forma:
nume varsta adresa numar_matricol functie
Cmpurile sunt separate printr-un spatiu si sunt siruri de caractere cu urmatoarele lungimi: nume 19, vrsta - 2, adresa - 11, numar_matricol - 5 si functie - 5.
Functiile care trebuie implementate sunt:
IncarcBD(fis_bd) - ncarca baza de date din fisierul fis_bd.
SalvezBD(fis_bd) - salveaza baza de date din memorie n fisierul fis_bd.
AfisezBD() - afiseaza baza de date din memorie.
IntroducPersoana(n, v, a, nm, f) - introduce n baza de date o persoana si datele aferente ei.
CautPersoana(n) - verifica prezenta unei persoane n baza de date.
StergPersoana(n) - sterge din baza de date persoana cu numele n.
ModificPersoana(n) - permite modificarea informatiilor legate de persoana cu numele n.
RetVarsta(n) - returneaza vrsta persoanei cu numele n.
http://labs.cs.utt.ro/labs/pc/html/node52.html (1 of 2) [22.07.2003 16:18:16]

Probleme propuse

next

up

RetAdresa(n) - returneaza adresa persoanei cu numele n.


RetNrMatricol(n) - returneaza numarul matricol al persoanei cu numele n.
RetFunctia(n) - returneaza functia persoanei cu numele n.
previous

contents

Next: Pointeri Up: Compilarea independenta a fisierelor Previous: Evaluarea unei expresii n Cuprins
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node52.html (2 of 2) [22.07.2003 16:18:16]

Pointeri

next

up

previous

contents

Next: Introducere Up: carte Previous: Probleme propuse Cuprins

Pointeri
Subsections
Introducere

Operatii cu pointeri

Pointeri ca argumente ale functiilor

Pointeri si tablouri

Pointeri la functii

Folosirea neadecvata a operatiilor cu pointeri

Problema rezolvata

Problema propusa

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node53.html [22.07.2003 16:18:16]

Introducere

next

up

previous

contents

Next: Operatii cu pointeri Up: Pointeri Previous: Pointeri Cuprins

Introducere
Pointerii sunt variabile care contin adresa de memorie a unei alte variabile. Din
aceste considerente, pointerii se numesc si variabile de adresa.
Presupunem ca avem o variabila de tip ntreg numita entitate localizata la adresa
de memorie 0x1000 (adresele sunt automat asigante variabilelor de catre
compilator). Daca dorim sa referim aceasta variabila prin intermediul unui pointer
entitate_ptr, atunci valoarea pointerului va fi 0x1000 (entitate_ptr =
0x1000), astfel spunem ca entitate_ptr "arata" spre variabila entitate (Pentru a
se evita confuziile, se recomanda ca numele pointerilor sa aiba sufixul _ptr).
Pentru a ntelege mai bine mecanismul de functionare a pointerilor, introducem o
analogie pointeri - adrese postale, n care adresa de memorie este adresa postala,
numele variabilei pointer este numele cladirii, iar entitatea referita este cladirea
propriu-zisa. Aceasta analogie este prezentata n tabelul 7.1. Se observa ca doi
pointeri diferiti (Fac_AC si Fac_ETC) au aceeasi valoare, indicnd spre aceeasi
locatie, astfel referind aceeasi entitate.
Tabela 7.1: Analogie pointeri - adrese postale
Variabila (nume pointer) Valoare adresa

next

up

previous

Entitate

Fac_AC

Bd. V. Prvan 2 Cladire Electro

Fac_ETC

Bd. V. Prvan 2 Cladire Electro

Fac_Mate

Bd. V. Prvan 4

Cladire "U"

contents

Next: Operatii cu pointeri Up: Pointeri Previous: Pointeri Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node54.html [22.07.2003 16:18:16]

Operatii cu pointeri

next

up

previous

contents

Next: Pointeri ca argumente ale Up: Pointeri Previous: Introducere Cuprins

Operatii cu pointeri
Pointerii se declara punnd un asterisc (*) n fata numelui variabilei:
int variabila;
/*definire variabila intreg*/
int *variabila_ptr; /*definire pointer la un intreg */

Operatorii specifici pointerilor sunt: operatorul de dereferentiere * (pentru un


pointer, returneaza entitatea referita de pointer) si operatorul de adresa & (pentru
o entitate, returneaza adresa entitatii). Exemplul urmator explica folosirea acestor
operatori. Variabila pointer obiect_ptr primeste adresa variabilei obiect, astfel
obiect_ptr va indica spre zona de memorie unde este memorata variabila obiect.
n ultima linie, se stocheaza valoarea 5 la zona de memorie spre care arata
obiect_ptr, adica n variabila obiect.
int obiect; /* variabila de tip intreg */
int * obiect_ptr; /* pointer la un intreg */
obiect=4;
obiect_ptr=&obiect; /* obiect_ptr va indica
spre obiect */
printf("%d\n", *obiect_ptr); /* afiseaza valoarea
spre care indica
obiect_ptr */
*obiect_ptr=5; /* atribuie lui obiect
valoarea 5 */

Folosirea gresita a operatorilor poate duce la functionari incorecte a programului


sau, n cazul fericit, la erori semnalate de compilator:
*variabila
este ilegal, prin aceasta se solicita entitatea referita de o variabila care nu este un pointer;
&variabila_ptr
este legal, dar "neobisnuit", se solicita adresa lui variabila_ptr, adica un pointer la un pointer.

http://labs.cs.utt.ro/labs/pc/html/node55.html (1 of 3) [22.07.2003 16:18:16]

Operatii cu pointeri

Mai multi pointeri pot indica spre aceeasi zona de memorie:


int obiect;
int *obiect_ptr1;
int *obiect_ptr2;
obiect = 1; /* se atribuie valoarea 1 lui obiect */
obiect_ptr1 = &obiect;
obiect_ptr2 = obiect_ptr1;
/* obiect_ptr1 si obiect_ptr2 vor indica spre
aceasi locatie de memorie */
printf("%d %d\n", *obiect_ptr1, *obiect_ptr2);

Un pointer special definit n limbajul C este pointerul NULL, care nu indica spre
nimic (adresa spre care arata acest pointer este 0). Acest pointer este definit n
stdio.h si n stdlib.h ca fiind (void *) 0, adica un pointer spre o locatie de tip
void si care arata spre locatia de memorie 0.
O situatie n care pointerii sunt utili este declararea structurilor recursive. n C
nu se permite ca o structura sa contina cmpuri de tipul aceleiasi structuri.
Aceasta restrictie poate fi evitata folosind pointeri la structuri, dupa cum se arata
n exemplul urmator:
typedef struct pers
{
char nume[20];
int varsta;
struct pers * urmator;
} persoana;
persoana *p;

Pentru a referi un cmp folosind un pointer spre o structura, se foloseste


operatorul de dereferentiere: (*p).nume. Echivalent cu acest operator exista n
C un alt operator pentru accesarea cmpurilor din structurile indicate de pointeri:
p- $>$nume.
next

up

previous

contents

Next: Pointeri ca argumente ale Up: Pointeri Previous: Introducere Cuprins Cristian Gavrila
http://labs.cs.utt.ro/labs/pc/html/node55.html (2 of 3) [22.07.2003 16:18:16]

Operatii cu pointeri

2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node55.html (3 of 3) [22.07.2003 16:18:16]

Pointeri ca argumente ale functiilor

next

up

previous

contents

Next: Pointeri si tablouri Up: Pointeri Previous: Operatii cu pointeri Cuprins

Pointeri ca argumente ale functiilor


n C, transmiterea parametrilor la functii se face "prin valoare", singurul rezultat
vizibil n exterior fiind valoarea pe care o returneaza functia. Pentru ca o functie
sa poata returna mai multe valori sau pentru ca modificarile asupra parametrilor
sa se propage n exteriorul functiei, se folosesc pointeri. Acest concept este
ilustrat de urmatoarea analogie: Presupunem ca se ntlnesc doua persoane A si B,
A poate doar sa vorbeasca, iar B poate doar sa asculte. Cum poate B sa i
transmita informatii lui A ? Simplu: A i spune: "Lasa raspunsul tau n cutia
postala numarul x". Astfel, n momentul cnd se transmite un pointer catre o
functie, functiei i se "comunica" adresa variabilei transmise ca parametru, putnd
astfel face modificari asupra acelei variabile.
n exemplul urmator se arata cum functia inc_contor va modifica valoarea
variabilei contor.
#include <stdio.h>
void inc_contor(int *contor_ptr)
{
(*contor_ptr)++;
}
void main(void)
{
int contor = 0;
while (contor<10)
inc_contor(&contor);
printf("contor: %d\n",contor);
}

http://labs.cs.utt.ro/labs/pc/html/node56.html (1 of 2) [22.07.2003 16:18:17]

Pointeri ca argumente ale functiilor

Din functia main se transmite spre functia inc_contor nu variabila care trebuie
incrementata, ci adresa sa. Functia inc_contor primeste ca parametru nu un ntreg,
ci un pointer la un ntreg. Astfel, cunoscnd adresa variabilei contor, functia
poate modifica valoarea acelei variabile, referind-o indirect prin intermediul
pointerului.
next

up

previous

contents

Next: Pointeri si tablouri Up: Pointeri Previous: Operatii cu pointeri Cuprins Cristian Gavrila
2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node56.html (2 of 2) [22.07.2003 16:18:17]

Pointeri si tablouri

next

up

previous

contents

Next: Pointeri la functii Up: Pointeri Previous: Pointeri ca argumente ale Cuprins

Pointeri si tablouri
n C, exista o strnsa legatura ntre pointeri si tablouri. Cnd se foloseste numele
unui tablou (fara index), se genereaza un pointer catre primul element al
tabloului. Astfel, n C se pot transmite tablouri ca parametri n functii (de fapt, se
transmite adresa de nceput a tabloului). Alt avantaj al tratarii unitare
pointer-tablou este aplicarea aritmeticii pointerilor pentru accesarea elementelor
unui tablou. Identitate pointer-tablou se reflecta cel mai bine n operatiile cu siruri
de caractere, unde sirul de caractere este un tablou de caractere sau un pointer la
caracter.
Prezentam n cele ce urmeaza unele aspecte ale relatiei dintre pointeri si tablouri.
int tablou[5];
int *tablou_ptr;
tablou_ptr=&tablou[0];

Dupa secventa de mai sus, pointerul tablou_ptr va indica spre primul element al
tabloului, deci spre nceputul zonei de memorie unde este stocat tabloul.
Deoarece variabila tablou este vazuta n C ca un pointer, acelasi efect s-ar fi
obtinut prin atribuirea: tablou_ptr=tablou;.
Pentru a accesa elementele tabloului, se incrementeaza valoarea pointerului, astfel
daca tablou_ptr=tablou; atunci *(tablou_ptr++) va returna valoarea
lui tablou[0], dupa care tablou_ptr va arata spre tablou[1].
Atentie! *(tablou_ptr++) va returna valoarea lui tablou[0], dupa care se va
incrementa valoarea lui tablou_ptr, aratnd spre tablou[1]. n schimb,
(*tablou_ptr)++ va incrementa valoarea spre care arata tablou_ptr,
returnnd astfel tablou[0]++.

http://labs.cs.utt.ro/labs/pc/html/node57.html (1 of 2) [22.07.2003 16:18:17]

Pointeri si tablouri

n acelasi context, propunem ca exercitiu rularea urmatorului exemplu:


#include <stdio.h>
void main(void)
{
int t[4]={0, 1, 2, 3};
int *p=&t[1];
printf("%d\n", *p++); /* afiseaza valoarea
lui t[1] */
printf("%d\n", *++p); /* afiseaza valoarea
lui t[3] */
printf("%d\n", ++*p); /* afiseaza valoarea
incrementata a lui t[3] */
}
next

up

previous

contents

Next: Pointeri la functii Up: Pointeri Previous: Pointeri ca argumente ale Cuprins Cristian Gavrila
2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node57.html (2 of 2) [22.07.2003 16:18:17]

Pointeri la functii

next

up

previous

contents

Next: Folosirea neadecvata a operatiilor Up: Pointeri Previous: Pointeri si tablouri Cuprins

Pointeri la functii
Limbajul C permite nu doar referirea unor date, ci si referirea functiilor (pointeri la
functii). Aceasta nu difera mult de referirea datelor, un pointer la o functie retinnd
adresa de memorie unde ncepe rutina care implementeaza functia.
Un pointer la o functie se declara n maniera:
tip_returnat (*nume_pointer)(... declaratii parametri ...);
Astfel, daca avem implementata o functie f1 si un pointer spre functie f1_ptr, secventa
urmatoare va arata cum se poate realiza prin intermediul unui pointer apelul unei
functii:
#include <stdio.h>
void f1(int a)
{
printf("%d\n",a);
}
void main(void)
{
void (*f1_ptr)(int);
f1_ptr=f1; /* pointerul f1_ptr va indica
spre functia f1 */
(*f1_ptr)(4); /* prin intermediul lui f1_ptr
se apeleaza functia f1 */
}

La fel ca n cazul tablourilor, putem atribui direct unui pointer adresa functiei, fara a
folosi operatorul & (f1_ptr=f1; este identic cu f1_ptr=&f1;).
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node58.html [22.07.2003 16:18:17]

Folosirea neadecvata a operatiilor cu pointeri

next

up

previous

contents

Next: Problema rezolvata Up: Pointeri Previous: Pointeri la functii Cuprins

Folosirea neadecvata a operatiilor cu


pointeri
n C, deoarece limbajul ofera o mare libertate de exprimare, este foarte usor
pentru un programator neatent sa faca erori care nu sunt semnalate la compilare,
dar care duc la comportari neasteptate ale programului.
O eroare tipica este atribuirea de valori pointerilor neinitializati:
int *un_pointer;
*un_pointer=5;

n aceasta situatie, deoarece un_pointer este neinitializat, valoarea 5 este scrisa n


memorie la o locatie aleatoare, poate chiar rezervata altei variabile. n cazul n
care un pointer nu arata spre o zona de memorie rezervata, trebuie alocata o zona
de memorie n mod explicit, folosind functia malloc:
un_pointer=(int *)malloc(sizeof(int));
Functia malloc rezerva spatiu de memorie si returneaza adresa spatiului rezervat;
zona de memorie referita de un pointer poate fi eliberata folosind functia free.
Ambele functii sunt definite n stdlib.h.
n C nu exista un mecanism de garbage collection, astfel ca programatorul
trebuie sa aiba grija ca zonele de memorie alocate dinamic si care nu mai sunt
utile sa fie dealocate (folosind functia free). Faptul ca unui pointer i se atribuie o
noua valoare nu nseamna ca zona de memorie spre care arata s-a eliberat si n
acest mod programul poate ajunge sa tina alocata toata memoria disponibila.
O alta greseala des ntlnita este referirea pointerilor spre alte locatii de memorie:
int obiect=5;
int *obiect_ptr;

http://labs.cs.utt.ro/labs/pc/html/node59.html (1 of 2) [22.07.2003 16:18:18]

Folosirea neadecvata a operatiilor cu pointeri

obiect_ptr = obiect;

Lipsa operatorului de adresa & face ca obiect_ptr sa indice spre locatia de


memorie aflata la adresa 5.
Urmatorul exemplu ilustreaza un stil de programare "daunator", care strica
lizibilitatea codului. Limbajul C este foarte flexibil, fapt ce poate duce, n special
n cazul pointerilor, la rezultate imprevizibile:
void copy_string(char * p, char *q)
{
/* copiaza sirul q in p */
while (*p++ = *q++);
}

Chiar daca aceasta implementare este mult mai compacta, urmarirea codului este
foarte dificila, iar folosirea combinata a operatorilor de incrementare si pointerilor
poate duce la efecte necontrolate. Urmatoarea varianta de implementare a
aceleiasi functii copy_string prezinta un stil adecvat programarii cu pointeri:
void copy_string(char * dest, char * sursa)
{
*dest = *sursa;
while (*dest!='\0')
{
++dest;
++sursa;
*dest = *sursa;
}
}
next

up

previous

contents

Next: Problema rezolvata Up: Pointeri Previous: Pointeri la functii Cuprins Cristian Gavrila
2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node59.html (2 of 2) [22.07.2003 16:18:18]

Problema rezolvata

next

up

previous

contents

Next: Problema propusa Up: Pointeri Previous: Folosirea neadecvata a operatiilor Cuprins

Problema rezolvata
Sa se scrie un program care gestioneaza date despre un grup de studenti. Pentru
fiecare student se memoreaza numele si numarul sau matricol. Programul trebuie
sa implementeze urmatoarele operatii:

citirea numarului de studenti si a datelor acestora;


afisarea datelor tuturor studentilor;
sortarea listei de studenti n ordinea alfabetica a numelor;
sortarea listei de studenti n ordinea crescatoare a numerelor matricole;
cautarea unui student pentru care se precizeaza numele si afisarea pozitiei pe care o ocupa acesta n
lista ordonata alfabetic dupa numele studentilor;
cautarea unui student pentru care se precizeaza numarul matricol si afisarea pozitiei pe care o
ocupa acesta n lista ordonata crescator dupa numarul matricol al studentilor.

#include
#include
#include
#include
#include

<stdio.h>
<string.h>
<stdlib.h>
<ctype.h>
<conio.h>

typedef struct
{
char *nume;
int nr;
} student;
#define SIZE sizeof(student)
typedef int (*comp)(void *, void *); /* tip pointer la
functia de comparare */
typedef student *pstud;
/*--------------------------------------------------------*/
/*
*/
/* functia eroare afiseaza un mesaj de eroare,in
*/
http://labs.cs.utt.ro/labs/pc/html/node60.html (1 of 7) [22.07.2003 16:18:18]

Problema rezolvata

/* cazul in care nu poate fi alocata dinamic o zona


*/
/* de memorie; apoi se opreste executia programului
*/
/*
*/
/*--------------------------------------------------------*/
void eroare(void)
{
puts(" \n **** eroare alocare dinamica de memorie ****");
exit(1);
}
/*--------------------------------------------------------*/
/*
*/
/* citeste numarul de studenti si datele acestora,
*/
/* aloca dinamic spatiu pentru tabloul de studenti,
*/
/* memoreaza numele si nr. matricol ale studentilor
*/
/*
*/
/*--------------------------------------------------------*/
void citeste(int *n, pstud *tab)
{
pstud t;
char sir[40];
int i;
/* citeste numarul de studenti */
printf("\n dati numarul de studenti:");
scanf("%d", n);
/* aloca spatiu pentru toate inregistrarile de tip student */
if (!(t=(pstud)malloc((*n)*SIZE))) /* citeste1 */
eroare();
*tab=t;
/* citeste datele tuturor studentilor */
for (i=0; i<*n; i++, t++)
{
printf("\n nume: ");
scanf("%s", sir);
/* aloca dinamic spatiu pentru numele studentului */
if (!(t->nume=(char *)malloc(strlen(sir)+1))) /* citeste2 */
eroare();
strcpy(t->nume, sir);
printf("\n numar matricol:");
scanf("%d", &t->nr);
}
http://labs.cs.utt.ro/labs/pc/html/node60.html (2 of 7) [22.07.2003 16:18:18]

Problema rezolvata

}
/*--------------------------------------------------------*/
/*
*/
/* afiseaza numele si numarul matricol ale celor
*/
/* n studenti din tabelul a carui adresa este data
*/
/* in parametrul tab
*/
/*
*/
/*--------------------------------------------------------*/
void afiseaza (int n, pstud tab)
{
int i;
puts("\n tabelul cu studenti ");
for (i=0; i<n; i++, tab++)
printf("\n%-30s %4d", tab->nume, tab->nr);
}
/*--------------------------------------------------------*/
/*
*/
/* functia comp1 compara numele a doi studenti ale caror */
/* adrese sunt date de pointerii p si r
*/
/*
*/
/*--------------------------------------------------------*/
int comp1(void *p, void *r)
{
return strcmp(((pstud)p)->nume, ((pstud)r)->nume);
}
/*--------------------------------------------------------*/
/*
*/
/* functia comp2 compara nr. matricol a doi studenti ale */
/* caror adrese sunt date de pointerii p si r
*/
/*
*/
/*--------------------------------------------------------*/
int comp2(void *p, void *r)
{
return ((pstud)p)->nr - ((pstud)r)->nr;
}

/*--------------------------------------------------------*/
/*
*/
/* functia cauta studentul cu adresa data de parametrul s */
http://labs.cs.utt.ro/labs/pc/html/node60.html (3 of 7) [22.07.2003 16:18:18]

Problema rezolvata

/* in tabelul cu adresa indicata de parametrul tab;


*/
/* tabelul este ordonat dupa criteriul specificat prin
*/
/* parametrul f
*/
/*
*/
/*--------------------------------------------------------*/
void cauta(pstud s, pstud tab, int n, comp f)
{
pstud t=NULL;
int i;
t=bsearch(s, tab, n, SIZE, f);
if (t)
{ /* exista studentul cautat */
i=t-tab;
printf("\n studentul %s cu numarul matricol %d e al %d -lea
in evidenta", t->nume, t->nr, i+1);
}
else
printf("\n studentul nu se afla in evidenta");
}

/*--------------------------------------------------------*/
/*
*/
/* elibereaza spatiul de memorie detinut de campurile nume*/
/* ale celor n studenti din tabel si apoi zona detinuta */
/* de tabel
*/
/*
*/
/*--------------------------------------------------------*/
void elibereaza(pstud tabel, int n)
{
int i;
for (i=0; i<n; i++)
free(tabel[i].nume);
free(tabel);
}
/*--------------------------------------------------------*/
/*
*/
/* functia meniu afiseaza meniul programului
*/
/*
*/
/*--------------------------------------------------------*/

http://labs.cs.utt.ro/labs/pc/html/node60.html (4 of 7) [22.07.2003 16:18:18]

Problema rezolvata

void meniu(void)
{
puts("\n c, C --- citeste tabel studenti");
puts(" a, A --- afiseaza tabel studenti");
puts(" n, N --- ordoneaza dupa nume");
puts(" r, R --- ordoneaza dupa numar matricol");
puts(" f, F --- cauta dupa nume");
puts(" l, L --- cauta dupa numar matricol");
puts(" x, X --- iesire din program");
}

void main(void)
{
char opt;
int n;
/* numarul de studenti */
char nume[30];
student s;
pstud tabel=NULL; /* adresa tabloului cu studenti */
while (1)
{
meniu();
opt=tolower(getche());
switch (opt)
{
case 'c':
if(tabel) /* daca a existat anterior un
alt tablou in memorie */
elibereaza(tabel,n);
citeste(&n, &tabel);
break;
case 'a':
afiseaza(n,tabel);
break;
case 'n':
qsort(tabel, n, SIZE, comp1);
break;
case 'r':
qsort(tabel, n, SIZE, comp2);
break;
case 'f':
printf("\n dati numele:");
scanf("%s", nume);
if (!(s.nume=(char *)malloc(strlen(nume)+1)))
eroare();
http://labs.cs.utt.ro/labs/pc/html/node60.html (5 of 7) [22.07.2003 16:18:18]

Problema rezolvata

strcpy(s.nume,nume);
cauta(&s, tabel, n, comp1);
free(s.nume); /* elibereaza spatiul alocat pentru nume */
break;
case 'l':
printf("\n dati numarul matricol:");
scanf("%d", &s.nr);
cauta(&s, tabel, n, comp2);
break;
case 'x':
exit(0);
default:
puts("comanda gresita");
}
}
}

Observatii:
Din considerente de economie de memorie, implementarea tabloului cu studenti
s-a facut dinamic; dupa ce s-a citit numarul de studenti, s-a alocat spatiul
corespunzator (vezi linia /* citeste1 */). n plus, n tablou, n cmpul
nume se pastreaza nu sirul de caractere pentru numele studentilor, ci un pointer la
sirul de caractere. Astfel, n loc de a rezerva, pentru toate numele, acelasi numar
de caractere, n momentul n care se cunoaste exact numele unui student, se aloca
dinamic un spatiu de memorie de dimensiune egala cu lungimea acestuia (vezi
linia /* citeste2 */). Adresa acestui spatiu se pastreza n cmpul nume.
Reamintim ca n limbajul C, mecanismul de transmitere a parametrilor este prin
valoare. Prin urmare, o functie nu poate modifica valoarea unui parametru actual,
chiar daca modifica parametrul formal corespondent. Pentru situatiile n care se
doreste sa se transmita informatie de la functia apelata la cea apelanta prin
intermediul parametrilor se procedeaza in felul urmator: la apelul functiei se
transmite adresa obiectului care urmeaza sa se modifice, iar, n cadrul functiei,
parametrul corespondent se declara de tipul pointer. Astfel, functia apelata
cunoaste adresa obiectului respectiv si l poate modifica, opernd indirect asupra
lui, prin intermediul pointerului. Din aceste considerente, deoarece citirea
numarului de studenti si alocarea spatiului pentru tablou se face n functia citeste,
parametrii formali corespunzatori int *n si pstud *tab vor fi de tipul
pointer. La apelul functiei citeste se vor transmite nu valorile lui n si tabel, ci
http://labs.cs.utt.ro/labs/pc/html/node60.html (6 of 7) [22.07.2003 16:18:18]

Problema rezolvata

adresele acestora: &n, &tabel.


La accesarea elementelor tabloului de studenti s-a folosit att lucrul cu pointeri n
functiile citeste si afiseaza, ct si varianta cu indici n functia elibereaza.
Pentru compararea, dupa nume, a doi studenti s-a implementat functia comp1.
Similar, functia comp2 realizeaza compararea dupa numarul matricol.
Pentru sortarea tabloului se apeleaza functia de biblioteca qsort. Aceasta are
urmatorul prototip:
void qsort(void *tab, int nr_elem, int nr_oct_elem,
int (*fcmp)(void *, void *));
Parametrii indica adresa tabloului de sortat, numarul elementelor tabloului,
marimea n octeti a fiecarui element si adresa functiei de comparare.
Dupa sortarea tabloului, cautarea unui student se face cu functia de cautare binara
bsearch:
void *bsearch(void *cheie, void *tab, int nr_elem, int
nr_octeti_elem, int (*fcmp)(void *,void *));
Parametrii indica cheia cautata, adresa tabloului, numarul elementelor tabloului,
marimea n octeti a fiecarui element si adresa functiei de comparare. Functia
returneaza adresa primului element care corespunde cheii, respectiv valoarea
NULL daca nu exista un astfel de element.
n functia cauta, pentru a afla numarul de ordine al unui student n tabela, se
scade din adresa elementului de tablou corespunzator acestuia (t) adresa de
nceput a tabelei (tab).
Pentru ca programul sa functioneze corect, comenzile f si l trebuie date dupa ce n
prealabil s-au dat comenzile n si respectiv r. (Se utilizeaza pentru cautarea unui
student o functie de cautare binara, deci tabela trebuie sa fie anterior sortata!)
next

up

previous

contents

Next: Problema propusa Up: Pointeri Previous: Folosirea neadecvata a operatiilor Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node60.html (7 of 7) [22.07.2003 16:18:18]

Problema propusa

next

up

previous

contents

Next: Liste liniare simplu nlantuite Up: Pointeri Previous: Problema rezolvata Cuprins

Problema propusa
Sa se realizeze un program pentru evidenta abonatilor telefonici dintr-o localitate.
Pentru fiecare abonat se memoreaza numele, adresa, numarul de telefon.
Programul trebuie sa permita:

adaugarea unui nou abonat;


stergerea unui abonat;
modificarea datelor unui abonat;
afisare numarului de telefon al unui abonat;
stergerea ntregii evidente.

Implementarea listei de abonati sa se faca folosind ct mai putina memorie.


Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node61.html [22.07.2003 16:18:18]

Liste liniare simplu nlantuite

next

up

previous

contents

Next: Aspecte ale implementarii listelor Up: carte Previous: Problema propusa Cuprins

Liste liniare simplu nlantuite


Subsections
Aspecte ale implementarii listelor liniare

Problema rezolvata

Codul sursa

Comentarea programului

Problema propusa

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node62.html [22.07.2003 16:18:19]

Aspecte ale implementarii listelor liniare

next

up

previous

contents

Next: Problema rezolvata Up: Liste liniare simplu nlantuite Previous: Liste liniare simplu nlantuite
Cuprins

Aspecte ale implementarii listelor liniare


O solutie de implementare a listelor liniare este sub forma unei nlantuiri de
elemente cu aceeasi structura, aflate n memorie la diverse adrese si legate ntre
ele prin intermediul pointerilor. Scopul utilizarii listelor este de a economisi
spatiu de memorie, motiv pentru care se foloseste alocarea dinamica n locul celei
statice (utilizata n cazul tablourilor). Accesul la un element al listei se poate face
doar secvential, parcurgnd elementele aflate naintea sa n nlantuire.
Pentru a exploata avantajul listelor n ceea ce priveste economia de spatiu de
memorie, trebuie acordata o atentie deosebita operatiilor asupra listei. n general,
asupra unei liste se pot face operatii de insertie/adaugare de noduri, stergere de
noduri si parcurgerea nodurilor.
Pentru a putea folosi o lista, este necesar sa fie retinuta adresa de nceput a listei
(adresa primului nod). Ne vom referi n continuare la aceasta adresa prin
pointerul prim.
n cazul parcurgerii listei, operatia este relativ simpla. Cu ajutorul unui pointer
auxiliar se pleaca de la prim si se urmareste legatura spre nodul urmator,
pointerul auxiliar primind pe rnd adresa nodului urmator.
O operatie mai complicata este introducerea unui nod nou n lista. Se disting trei
situatii: introducere la nceputul listei, introducere la sfrsit si introducere ntre
doua noduri. Dupa alocarea spatiului de memorie necesar noului nod,
presupunem ca acesta este referit prin pointerul temp. n figurile 8.1, 8.2 si 8.3 se
prezinta cele trei cazuri de adaugare a noului nod. Ordinea operatiilor a fost
marcata prin 1, 2, 3.

http://labs.cs.utt.ro/labs/pc/html/node63.html (1 of 4) [22.07.2003 16:18:20]

Aspecte ale implementarii listelor liniare

\begin{figure}\begin{center}
\epsfig{file=adaugare_inc.eps, height=5cm}
\end{center}\end{figure}

Figura 8.1: Adaugarea unui nod la nceputul


listei

\begin{figure}\begin{center}
\epsfig{file=adaugare_sf.eps, height=5cm} \end{center}\end{figure}

Figura 8.2: Adaugarea unui nod la sfrsitul listei

http://labs.cs.utt.ro/labs/pc/html/node63.html (2 of 4) [22.07.2003 16:18:20]

Aspecte ale implementarii listelor liniare

\begin{figure}\begin{center}
\epsfig{file=adaugare_mijl.eps, height=5cm} \end{center}\end{figure}

Figura 8.3: Adaugarea unui nod la mijlocul listei

n situatia stergerii unui nod din lista apar de asemenea cele trei situatii anterior
descrise (nod de la nceputul, de la sfrsitul sau din mijlocul listei). Principala
grija a programatorului n cazul stergerii unui nod trebuie sa fie eliberarea
spatiului de memorie alocat nodului care a fost sters si mentinerea integritatii
listei (prin stergerea nodului, sa nu se "rupa" lista). n figurile 8.4, 8.5 si 8.6 se
prezinta cele trei situatii de stergere.

\begin{figure}\begin{center}
\epsfig{file=stergere_inc.eps, height=3.5cm}
\end{center}\end{figure}

Figura 8.4: Stergerea unui nod de la nceputul listei

http://labs.cs.utt.ro/labs/pc/html/node63.html (3 of 4) [22.07.2003 16:18:20]

Aspecte ale implementarii listelor liniare

\begin{figure}\begin{center}
\epsfig{file=stergere_sf.eps, height=4cm} \end{center}\end{figure}

Figura 8.5: Stergerea unui nod de la sfrsitul listei

\begin{figure}\begin{center}
\epsfig{file=stergere_mijl.eps, height=3.5cm} \end{center}\end{figure}

Figura 8.6: Stergerea unui nod de la mijlocul listei


next

up

previous

contents

Next: Problema rezolvata Up: Liste liniare simplu nlantuite Previous: Liste liniare simplu nlantuite
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node63.html (4 of 4) [22.07.2003 16:18:20]

Problema rezolvata

next

up

previous

contents

Next: Codul sursa Up: Liste liniare simplu nlantuite Previous: Aspecte ale implementarii listelor
Cuprins

Problema rezolvata
Sa se realizeze un program care raspunde la urmatoarele comenzi:

a - Se citeste o linie de forma:


identificator numar

unde numar este un numar ntreg. Ca rezultat, se retine n evidenta identificatorul mpreuna cu
numarul asociat lui.
t - Se citeste o linie ce contine un identificator. Daca acesta apare n evidenta, se tipareste valoarea
asociata lui; n caz contrar se tipareste un mesaj de eroare.
s - Se citeste o linie ce contine un identificator si l sterge din evidenta.
l - Se tiparesc identificatorii din evidenta n ordine alfabetica mpreuna cu valorile asociate lor.

$+$ - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii se afla n

evidenta se tipareste suma lor. n caz ca unul sau ambii identificatori lipsesc din evidenta, se
afiseaza un mesaj de eroare.

$-$ - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii se afla n

evidenta se tipareste diferenta lor. n caz ca unul sau ambii identificatori lipsesc din evidenta, se
afiseaza un mesaj de eroare.
$*$

- Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii se afla n
evidenta se tipareste produsul lor. n caz ca unul sau ambii identificatori lipsesc din evidenta se
afiseaza un mesaj de eroare.

$/$ - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii se afla n

evidenta se tipareste rezultatul mpartirii lor. n caz ca unul sau ambii identificatori lipsesc din
evidenta se afiseaza un mesaj de eroare.
f - Se termina programul.

http://labs.cs.utt.ro/labs/pc/html/node64.html (1 of 2) [22.07.2003 16:18:20]

Problema rezolvata

Observatie: Identificatorii sunt pastrati n tabela n mod ordonat.


Subsections
Codul sursa

next

Comentarea programului
up

previous

contents

Next: Codul sursa Up: Liste liniare simplu nlantuite Previous: Aspecte ale implementarii listelor
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node64.html (2 of 2) [22.07.2003 16:18:20]

Codul sursa

next

up

previous

contents

Next: Comentarea programului Up: Problema rezolvata Previous: Problema rezolvata Cuprins

Codul sursa
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#define Max 100
/* lungimea maxima a unei linii */
/* tipul pentru nodul listei */
typedef struct elem
{
char *id;
int valoare;
struct elem *urm;
} nod;
nod *radacina=NULL;

/* pastreaza inceputul listei */

/*---------------------------------------------------------*/
/*
*/
/* Functia caut cauta sirul s in lista al carei inceput
*/
/* e indicat de parametrul lista. Daca sirul apare in lista*/
/* atunci functia returneaza pointerul la nodul respectiv, */
/*
in caz contrar returneaza NULL
*/
/*
*/
/*---------------------------------------------------------*/
nod *caut(nod *lista, char *s)
{
nod *q1;
for (q1=lista; q1!=NULL && strcmp(q1->id, s)<0; q1=q1->urm);
/* caut 1 */
if (q1!=NULL && strcmp(q1->id, s)==0) /* caut 2 */
return q1; /* daca sirul s a fost gasit in lista */

http://labs.cs.utt.ro/labs/pc/html/node65.html (1 of 9) [22.07.2003 16:18:21]

Codul sursa

return NULL;
}
/*---------------------------------------------------------*/
/*
*/
/*
Functia listez parcurge lista si pentru fiecare nod
*/
/*afiseaza identificatorul memorat si valoarea atasata lui.*/
/*Deoarece lista este ordonata, afisarea identificatorilor*/
/*
este in ordine alfabetica
*/
/*
*/
/*---------------------------------------------------------*/
void listez(void)
{
nod *q;
for (q=radacina; q!=NULL; q=q->urm)
printf("Identificator: %s Valoare: %d\n",q->id,q->valoare);
}
/*---------------------------------------------------------*/
/* Functia sterg elimina din lista indicata de pointerul
*/
/* lista, nodul ce are campul id egal cu argumentul s
*/
/*
*/
/*---------------------------------------------------------*/
nod *sterg(nod *lista, char *s)
{
nod *q1, *q2;
for (q1=q2=lista; q1!=NULL && strcmp(q1->id, s)<0;
q2=q1,q1=q1->urm); /* sterg 1 */
/* se parcurge lista cautandu-se nodul avand */
/* campul id egal cu sirul s */
if (q1!=NULL && strcmp(q1->id, s)==0) /* sterg 2 */
{
/* daca s-a gasit un astfel de nod */
if (q1!=q2) /* daca nodul nu este la inceputul listei */
/* sterg 3 */
q2->urm = q1->urm; /* elimina nodul din lista */
else /* nodul apare la inceputul listei */
lista = lista->urm; /* sterg 4 */
free(q1->id);
/* se elibereaza memoria ocupata de nodul eliminat */
free(q1);

http://labs.cs.utt.ro/labs/pc/html/node65.html (2 of 9) [22.07.2003 16:18:21]

Codul sursa

return lista;
/*returneaza pointerul catre inceputul listei modificate*/
}
else
{
printf("Eroare: identificatorul %s nu apare in lista\n", s);
return lista;
}
}

/*---------------------------------------------------------*/
/*
*/
/* Functia introduc insereaza un nod in lista ordonata,
*/
/* indicata de parametrul lista. Lista ramine ordonata si */
/* dupa inserare. Nodul nou are campul id egal cu sirul
*/
/* indicat de parametrul s, iar campul valoare egal cu
*/
/* parametrul v. Functia returneaza pointerul catre
*/
/* inceputul listei modificate
*/
/*
*/
/*---------------------------------------------------------*/
nod *introduc(nod *lista, char *s, int v)
{
nod *q1, *q2, *aux;
if ((aux=(nod *)malloc(sizeof(nod)))==NULL ||
(aux->id=(char *)malloc(strlen(s)+1))==NULL)
/* introduc 1 */
{
/* daca nu e memorie suficienta pentru a crea un nod nou,
respectiv pentru a memora sirul s, se da un mesaj de eroare
dupa care executia e incheiata */
printf("Eroare: memorie insuficienta\n");
exit(1);
}
strcpy(aux->id, s);
/* se salveaza s in nodul nou */
aux->valoare=v;
/* se salveaza v in nodul nou */
/* nodul nou este inserat in lista ordonata astfel incat ea
ramane ordonata si dupa inserare. Lista este parcursa
cautandu-se primul nod avand campul id mai mare
sau egal cu s */
for (q2=q1=lista; q1!=NULL && strcmp(q1->id, s)<0;
q2=q1, q1=q1->urm); /* introduc 2 */
http://labs.cs.utt.ro/labs/pc/html/node65.html (3 of 9) [22.07.2003 16:18:21]

Codul sursa

if (q1!=NULL && strcmp(q1->id, s)==0) /* introduc 3 */


/* daca in lista apare un nod avand campul id egal cu s,
atunci se afiseaza un mesaj de eroare si se pastreaza
lista nemodificata*/
{
printf("Eroare: %s apare in tabela\n", s);
return lista;
}
if (q1!=q2) /* daca inserarea nu se face la inceputul listei*/
/* introduc 4 */
{
q2->urm=aux;
aux->urm=q1;
return lista ;
}
/* daca inserarea se face la inceputul listei */
/* introduc 5 */
aux->urm=lista;
return aux;
}
/*-------------------------------------------------------------*/
/*
*/
/*Functia citesc_linie citeste urmatoarea linie de la tastatura */
/*si recunoaste identificatorul si valoarea asociata lui.
*/
/*Identificatorul este returnat in parametrul s,
*/
/*iar valoarea in parametrul val
*/
/*
*/
/*-------------------------------------------------------------*/
void citesc_linie(char *s, int *val)
{
int i, j;
char temp[Max];
/* citeste urmatoarea linie de la tastatura */
gets(temp); /* citesc_linie 1 */
s[0]='\0'; /* initializeaza valorile argumentelor */
for (i=0; temp[i]!='\0'; )
/* atata timp cat nu a fost atins sfarsitul sirului */
/* citesc_linie 2 */
{
if (isalpha(temp[i])) /* daca incepe un identificator */
http://labs.cs.utt.ro/labs/pc/html/node65.html (4 of 9) [22.07.2003 16:18:21]

Codul sursa

/* citesc_linie 3 */
{
j=0;
/* memoreaza identificatorul in s */
while (isalnum(temp[i]))
s[j++]=temp[i++]; /* citesc_linie 4 */
/* memoreaza sfarsitul de sir */
s[j]='\0'; /* citesc_linie 5 */
continue;
}
if (isdigit(temp[i])) /* daca incepe un numar */
/* citesc_linie 6 */
{
*val=0;
while (isdigit(temp[i])) /* citesc_linie 7 */
{
/* calculeaza valoarea numarului */
*val=*val*10+temp[i]-'0' ; /* citesc_linie 8 */
i++;
}
continue;
}
/* altfel se trece peste caracterul curent */
i++; /* citesc_linie 9 */
} /* while */
}
/*----------------------------------------------------------*/
/*
*/
/* Functia comanda_a realizeaza functionalitatea comenzii a */
/*
*/
/*----------------------------------------------------------*/
void comanda_a(void)
{
int val;
char s[Max];
citesc_linie(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)!=0) /* daca linia e corecta */
radacina=introduc(radacina, s, val);
else
http://labs.cs.utt.ro/labs/pc/html/node65.html (5 of 9) [22.07.2003 16:18:21]

Codul sursa

printf("Eroare : linie incorecta\n");


}
/*---------------------------------------------------------*/
/*
*/
/* Functia comanda_t realizeaza functionalitatea comenzii t */
/*
*/
/*---------------------------------------------------------*/
void comanda_t(void)
{
int val;
char s[Max];
nod *p;
citesc_linie(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)==0) /* daca linia e incorecta */
{printf("Eroare: linie incorecta\n"); return;}
if ((p=caut(radacina, s))!=NULL) /* cauta nodul in lista */
printf("Identificator:%s Valoare:%d\n", p->id, p->valoare);
else
printf("Eroare: Identificator nedefinit\n");
}
/*---------------------------------------------------------*/
/*
*/
/*
Functia comanda_s realizeaza comanda s
*/
/*
*/
/*---------------------------------------------------------*/
void comanda_s(void)
{
char s[Max];
int val;
citesc_linie(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)==0) /* daca linia citita e incorecta */
{printf("Eroare: linie incorecta\n"); return;}
radacina=sterg(radacina, s); /* sterge nodul din lista */
}
/*---------------------------------------------------------*/
/*
*/
/*
Functia comanda_oper executa operatiile legate de
*/
/*
comenzile +, -, *, /
*/
http://labs.cs.utt.ro/labs/pc/html/node65.html (6 of 9) [22.07.2003 16:18:21]

Codul sursa

/*
Se citesc cei doi operatori si se executa operatia
*/
/*
dorita. Rezultatul este afisat.
*/
/*
*/
/*---------------------------------------------------------*/
void comanda_oper(char c)
{
char s1[Max], s2[Max];
int val;
nod *p1, *p2;
/* se citeste primul operand */
citesc_linie(s1, &val); /* comanda_oper 1 */
/* se citeste al doilea operand */
citesc_linie(s2, &val); /* comanda_oper 2 */
if (strlen(s1)!=0 && strlen(s2)!=0)
if(((p1=caut(radacina, s1))!=NULL) &&
((p2=caut(radacina, s2))!=NULL)) /* comanda_oper 3 */
/* se verifica daca operanzii apar in lista */
{
switch(c) /* functie de tipul comenzii */
{
case '+':
val=p1->valoare+p2->valoare;
break;
case '-':
val=p1->valoare-p2->valoare;
break;
case '*':
val=p1->valoare*p2->valoare;
break;
case '/':
if (p2->valoare!=0)
val=p1->valoare/p2->valoare;
else
printf("Eroare: Impartire la 0\n");
break;
}
printf("Rezultatul operatiei e %d\n", val);
}
else
printf("Operand nedefinit\n");
else
printf("Eroare: linie eronata\n");
}
http://labs.cs.utt.ro/labs/pc/html/node65.html (7 of 9) [22.07.2003 16:18:21]

Codul sursa

/*-----------------------------------------------------------*/
/*
*/
/* Functia meniu afiseaza meniul programului,citeste comanda */
/* si apeleaza subrutina corespunzatoare
*/
/*
*/
/*-----------------------------------------------------------*/
void meniu(void)
{
char o;
while(1) /* meniu 1 */
{
clrscr();
/* se afiseaza meniul programului */
puts("a : adauga un identificator si valoarea asociata");
puts("t : tipareste valoarea asociata unui identificator");
puts("s : sterge un identificator");
puts("l : listeaza identificatorii si valorile asociate");
puts("+ : calculeaza suma pentru 2 identificatori");
puts("- : calculeaza diferenta pentru 2 identificatori");
puts("* : calculeaza produsul pentru 2 identificatori");
puts("/ : calculeaza impartirea pentru 2 identificatori");
puts("f : termina programul");
printf("\nOptiunea: ");
o=getche(); /* meniu 2 */
printf("\n\n");
switch (tolower(o)) /* meniu 3 */
{
case 'a':
comanda_a(); break;
case 't':
comanda_t(); break;
case 's':
comanda_s(); break;
case 'l':
listez(); break;
case '+': case '-': case '*': case '/':
comanda_oper(o);
break;
case 'f':
return;
default:
printf("Eroare : Comanda inexistenta\n");
}
http://labs.cs.utt.ro/labs/pc/html/node65.html (8 of 9) [22.07.2003 16:18:21]

Codul sursa

printf("\nApasa orice tasta...");


getch();
}
}
/*----------------------------------------------------*/
/*
*/
/*
Functia main apeleaza functia meniu
*/
/*
*/
/*----------------------------------------------------*/
void main(void)
{
meniu();
}

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node65.html (9 of 9) [22.07.2003 16:18:21]

Comentarea programului

next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Codul sursa Cuprins

Comentarea programului
Programul memoreaza identificatorii si valorile asociate lor ntr-o evidenta, pe
care o foloseste conform functionalitatii cerute. Evidenta este realizata printr-o
lista simplu nlantuita ordonata. Fiecare nod al listei contine un cmp pentru
pastrarea identificatorului, care este indicat de char *id, un cmp pentru
memorarea valorii asociate identificatorului, cmpul int valoare, si un cmp
pentru a crea nlantuirea cu nodul urmator din lista, cmpul struct elem
*urm. Lista este ordonata crescator functie de cmpurile id ale nodurilor.
Functia main apeleaza functia meniu. Aceasta afiseaza n mod repetat, datorita
instructiunii while(1) de pe linia /* meniu 1 */, optiunile pe care le ofera
programul. n continuare, meniu citeste de la tastatura optiunea dorita (linia /*
meniu 2 */) si caracterul $<$Return $>$. n functie de optiunea aleasa (linia /*
meniu 3 */) se selecteaza rutina ce implementeaza functionalitatea dorita.
Rutina comanda_a citeste un identificator si valoarea asociata lui, dupa care l
introduce n evidenta. Citirea se face apelnd functia citesc_linie. n cazul n care
lungimea identificatorului citit este 0, se afiseaza un mesaj de eroare. n caz
contrar, identificatorul si valoarea asociata lui sunt introduse n lista ordonata prin
apelarea rutinei introducere.
comanda_t citeste un identificator folosind citesc_linie. Daca lungimea
identificatorului este 0, atunci se afiseaza mesajul ca linia este incorecta. Daca
nsa lungimea este diferita de 0, atunci identificatorul este cautat n lista (apelnd
functia caut). Daca identificatorul apare n lista, atunci se afiseaza valoarea
asociata lui, n caz contrar se tipareste un mesaj de eroare adecvat.

http://labs.cs.utt.ro/labs/pc/html/node66.html (1 of 4) [22.07.2003 16:18:21]

Comentarea programului

Functia comanda_s citeste o linie ce contine un identificator (folosind


citesc_linie). Daca linia citita este corecta (adica lungimea identificatorului este
nenula), atunci identificatorul este eliminat din evidenta prin apelarea lui sterg.
comanda_oper citeste doi identificatori (liniile /* comanda_oper 1 */ si
/* comanda_oper 2 */) si efectueaza o operatie aritmetica cu acesti
operanzi. Felul operatiei dorite este transmis prin parametrul char c al rutinei
comanda_oper. Daca identificatorii sunt corecti (au lungimile diferite de 0),
atunci ei sunt cautati n evidenta (linia /* comanda_oper 3*/). Daca ambii
apar, atunci, functie de c, se efectueaza operatia dorita, iar rezultatul este afisat.
Citirea unei linii de la tastatura se face prin rutina citesc_linie. Linia /*
citesc_linie 1 */ citeste n variabila locala temp o linie de la tastatura.
Ciclul while de pe linia /* citesc_linie 2 */ parcurge tabloul temp.
Daca gaseste o litera (linia /* citesc_linie 3 */), atunci nseamna ca a
descoperit nceputul unui identificator. Ciclul while de pe linia /*
citesc_linie 4 */ preia ntregul identificator si l memoreaza n tabloul al
carui nceput este indicat de parametrul char *s. Linia /*citesc_linie 5
0'' ce indica sfrsitul identificatorului. Daca la
*/ memoreaza caracterul '' $\backslash$
parcurgerea lui temp este ntlnita o cifra (linia /* citesc_linie 6 */),
atunci a fost descoperit nceputul numarului care apare n linia de text. Acest
numar este preluat prin ciclul while de pe linia /* citesc_linie 7 */,
calculndu-se simultan si valoarea numerica asociata lui. Linia /*
citesc_linie 8 */ face conversia, din sirul de caractere asociat numarului
ntreg, n valoarea lui. Calcularea valorii numerice se face folosind variabila
ntreaga a carei adresa este transmisa prin parametrul int *val. Linia /*
citesc_linie 9 */ "sare" peste acele caractere care nu fac parte din
identificator sau numar.
caut parcurge lista al carei nceput este transmis prin parametrul nod *lista,
cautnd nodul al carui identificator este egal cu sirul indicat de parametrul char
*s. Daca un astfel de nod este gasit, atunci caut returneaza pointerul catre el. n
caz contrar, returneaza NULL. Parcurgerea listei se face prin ciclul for de pe linia
/* caut 1 */. Variabila q1 este initializata astfel nct sa indice nceputul
listei. La sfrsitul fiecarei iteratii, q1 este mutat catre urmatorul nod. Conditia de
reluare a ciclului este ca lista sa nu fi fost parcursa n ntregime (conditia q1 !=
http://labs.cs.utt.ro/labs/pc/html/node66.html (2 of 4) [22.07.2003 16:18:21]

Comentarea programului

NULL de pe linia /* caut 1 */) si identificatorul sa nu fi fost gasit. Deoarece


lista este ordonata crescator este suficient sa testam ca strcmp(q1- $>$id,s)
$<$

0 (linia /* caut 1 */). Linia /* caut 2 */ verifica daca

identificatorul a fost gasit. Pentru aceasta este necesar ca q1 != NULL (altfel


s-ar fi parcurs toata lista) si sirul memorat n nodul curent sa fie egal cu cel
indicat de s.
Rutina listez parcurge toate nodurile din lista si, pentru fiecare, afiseaza
identificatorul retinut si valoarea atasata lui.
Rutina sterg elimina, din lista referita prin parametrul nod *lista, nodul al
carui identificator este egal cu sirul indicat de parametrul char *s. sterg
returneaza pointerul catre nceputul listei modificate. Dupa eliminare, lista
ramne ordonata. Pentru eliminarea unui nod sunt folositi doi pointeri care
parcurg lista. q1 indica nodul curent, n timp ce q2 pe cel anterior lui. Acest lucru
este necesar deoarece la eliminarea nodului indicat de q1, nlantuirea urm a
nodului anterior (care este indicat de q2) se modifica spre nodul urmator lui q1.
Ciclul for de pe linia /* sterg 1 */ parcurge lista. Pointerii q1 si q2 sunt
initializati sa indice spre nceputul listei din care se face stergerea. La fiecare
reluare a ciclului, q2 ia vechea valoare a lui q1, n timp ce q1 se muta spre nodul
urmator. Conditia de reluare a ciclului for este ca lista sa nu fi fost parcursa n
ntregime (q1 != NULL) si nodul sa nu fi fost gasit (strcmp(q1- $>$id, s)
$<$

0). Daca nodul a fost gasit (linia /* sterg 2 */), atunci se verifica daca

el este sau nu primul nod al listei. Daca nodul nu este chiar nceputul listei (linia
/* sterg 3 */), atunci nlantuirea urm a nodului anterior celui indicat de q1
se modifica spre nodul urmator celui indicat de q1. Daca nsa nodul indicat de q1
este primul din lista, atunci variabila lista este schimbata spre al doilea nod.
Memoria ocupata de nodul eliminat este eliberata. Daca nsa nu exista un nod
care sa aiba identificatorul egal cu sirul indicat de s, atunci sterg tipareste un
mesaj de eroare.

http://labs.cs.utt.ro/labs/pc/html/node66.html (3 of 4) [22.07.2003 16:18:21]

Comentarea programului

introduc creeaza un nod nou care contine sirul indicat de parametrul char *s,
iar cmpul lui de valoare este egal cu parametrul int v. Nodul este inserat n
lista indicata de parametrul nod *lista, astfel nct dupa introducere, lista
ramne ordonata. introduc returneaza nceputul listei modificate. Linia /*
introduc 1 */ aloca memorie pentru noul nod. Daca alocarea nu este
posibila, se afiseaza un mesaj de eroare si executia programului este ncheiata. n
caz contrar, cmpurile id si valoare sunt initializate corespunzator. Linia /*
introduc 2 */ parcurge lista cautnd pozitia n care noul nod trebuie
introdus. Pentru introducerea unui nod ntr-o lista ordonata sunt necesari doi
pointeri; unul indica nodul n fata caruia se face inserarea, iar al doilea pe cel
anterior lui. Daca noul nod nu este inserat ca primul nod n lista (linia /*
introduc 4 */), atunci nlantuirea de la nodul anterior (indicat de q2) se
schimba catre nodul nou, iar nlantuirea noului nod se schimba spre nodul indicat
de q1. Daca nodul devine primul n lista (linia /* introduc 5 */) atunci
nlantuirea lui urm este modificata spre nodul indicat de q1. n acest caz valoarea
returnata de introduc (care este nceputul listei modificate) este tocmai pointerul
spre nodul recent introdus. Daca n lista apare deja un nod al carui identificator
este egal cu cel care se doreste a fi introdus (linia /* introduc 3 */), atunci
se afiseaza un mesaj de eroare si se pastreaza lista nemodificata.
next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Codul sursa Cuprins Cristian Gavrila
2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node66.html (4 of 4) [22.07.2003 16:18:21]

Problema propusa

next

up

previous

contents

Next: Liste liniare multiplu nlantuite Up: Liste liniare simplu nlantuite Previous: Comentarea
programului Cuprins

Problema propusa
Sa se implementeze un set de functii care sa realizeze urmatoarele operatii:

adaug (t,id) - introduce identificatorul id n tabela de simboluri t;


prezent (t,id) - returneaza 1 sau 0 dupa cum identificatorul id este sau nu prezent n tabela
t;
sterg (t,id) - elimina id din tabela t;
reuniune (t1,t2,t) - t va contine identificatorii prezenti n t1 sau t2;
intersectie (t1,t2,t) - t va contine identificatorii prezenti att n t1 ct si in t2;
diferenta (t1,t2,t) - t va contine identificatorii prezenti n t1 si absenti n t2;
scriu(t) - tipareste n ordine alfabetica identificatorii din t.

Folosind functiile de mai sus sa se realizeze un program care citeste doua


secvente consecutive de text, care se termina fiecare cu caracterul `.`. Dupa citirea
textelor se cere sa se tipareasca, n ordine alfabetica, identificatorii prezenti doar
n primul text, apoi cei doar n al doilea text. n continuare se vor tipari n ordine
alfabetica identificatorii care sunt prezenti att n primul ct si n al doilea text. n
final se afiseaza identificatorii care apar n cel putin unul din cele doua texte.
next

up

previous

contents

Next: Liste liniare multiplu nlantuite Up: Liste liniare simplu nlantuite Previous: Comentarea
programului Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node67.html [22.07.2003 16:18:22]

Liste liniare multiplu nlantuite

next

up

previous

contents

Next: Implementarea listelor multiplu nlantuite Up: carte Previous: Problema propusa Cuprins

Liste liniare multiplu nlantuite


Subsections
Implementarea listelor multiplu nlantuite

Problema rezolvata

Sursa programului

Comentarea programului

Problema propusa

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node68.html [22.07.2003 16:18:22]

Implementarea listelor multiplu nlantuite

next

up

previous

contents

Next: Problema rezolvata Up: Liste liniare multiplu nlantuite Previous: Liste liniare multiplu nlantuite
Cuprins

Implementarea listelor multiplu nlantuite


Listele multiplu nlantuite sunt similare cu cele simplu nlantuite, diferenta
constnd n prezenta n structura unui nod a mai multor legaturi logice, n locul
uneia singure. Astfel, o asemenea lista poate fi privita ca mai multe liste simplu
nlantuite "suprapuse", dupa cum se arata n Figura 9.1. Problemele de la liste
simplu nlantuite referitoare la inserare/stergere sunt aceleasi, doar ca operatia
trebuie efectuata pentru fiecare nlantuire logica a listei. Parcurgerea se face ca la
liste simplu nlantuite, urmarind legaturile logice, cu deosebirea ca exista mai
multe "nceputuri" ale listei, egale cu numarul de liste logice existente.

\begin{figure}\begin{center}
\epsfig{file=lista.eps, width=\textwidth} \end{center}\end{figure}

Figura 9.1: Liste multiplu nlantuite

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node69.html [22.07.2003 16:18:22]

Problema rezolvata

next

up

previous

contents

Next: Sursa programului Up: Liste liniare multiplu nlantuite Previous: Implementarea listelor multiplu
nlantuite Cuprins

Problema rezolvata
Sa se realizeze un program care raspunde la urmatoarele comenzi:

''a'' - Se citesc trei linii ce contin datele asociate unei persoane. Prima linie contine numele, a doua
locul de munca, iar a treia vrsta. Persoana si datele asociate ei sunt retinute ntr-o evidenta. Daca
persoana este deja prezenta atunci se actualizeaza datele asociate ei.
''t'' - Se citeste o linie ce contine un nume. n cazul n care acesta este prezent n evidenta, se
tiparesc datele asociate lui. n caz contrar, se afiseaza un mesaj de atentionare.
''l'' - Se citeste o linie ce contine un loc de munca si se tiparesc n ordine alfabetica numele tuturor
persoanelor ce au locul de munca respectiv.
''p'' - Se citeste o valoare ntreaga si se tiparesc, n ordinea crescatoare a vrstei, numele si datele
asociate tuturor persoanelor care au vrsta mai mare sau egala cu valoarea citita.
''s'' - Se citeste o linie ce contine un nume. Persoana cu numele respectiv este eliminata din
evidenta.
''d'' - Se citeste o linie ce contine un loc de munca si se elimina din evidenta toate persoanele care
au locul de munca respectiv.
''n'' - Se tiparesc n ordine alfabetica toate persoanele din evidenta si datele asociate lor.
''v'' - Se tiparesc n ordine descrescatoare a vrstei, persoanele din evidenta.
''f'' - Se termina programului.

Subsections
Sursa programului

next

Comentarea programului
up

previous

contents

Next: Sursa programului Up: Liste liniare multiplu nlantuite Previous: Implementarea listelor multiplu
nlantuite Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node70.html [22.07.2003 16:18:23]

Sursa programului

next

up

previous

contents

Next: Comentarea programului Up: Problema rezolvata Previous: Problema rezolvata Cuprins

Sursa programului
Fisierul tip.h
/* tipul unui nod al listei ce implementeaza evidenta */
typedef struct nod_lista
{
char *nume; /* nume */
char *loc_munca; /* locul de munca */
int varsta; /* varsta */
struct nod_lista *alf; /* inlantuirea in ordine alfabetica */
struct nod_lista *varcr; /* inlantuirea in ordinea
crescatoarea a varstei */
struct nod_lista *vardes; /* inlantuirea in ordinea
descrescatoarea a varstei */
} nod;

/* operatiile asupra listei */


nod *cauta(char *);
void introdu(char *, char *, int);
void afis_alf(void);
void afis_des(void);
void afis_loc_munca(char *);
void afis_varsta(int);
void elimin(char *);
void elimin_loc_munca(char *);

Fisierul lista.c
#include
#include
#include
#include

<stdio.h>
<string.h>
<stdlib.h>
"tip.h"

static nod *inc1=NULL, *inc2=NULL, *inc3=NULL ;


/* nodurile listei sunt inlantuite dupa cele trei

http://labs.cs.utt.ro/labs/pc/html/node71.html (1 of 12) [22.07.2003 16:18:24]

Sursa programului

/*
/*
/*
/*

criterii de ordonare */
cele trei liste sunt indicate
inc1 indica lista ordonata in
inc2 indica lista ordonata in
inc3 indica lista ordonata in

de inc1, inc2 si inc3 */


ordine alfabetica */
ordinea crescatoare a varstei */
ordinea descrecatoare a varstei*/

static nod *auxp; /* variabila auxiliara


folosita la eliminarea unui nod */
/*---------------------------------------------------------*/
/*
*/
/*
cauta in lista ordonata alfabetic nodul care are
*/
/*
numele egal cu parametrul n;
*/
/*
returneaza pointerul la nod sau NULL
*/
/*
*/
/*---------------------------------------------------------*/
nod *cauta(char *n)
{
nod *l;

for(l=inc1; l!=NULL && strcmp(l->nume, n) < 0; l=l->alf);


/* parcurge lista cautand nodul cu nume egal cu n */
if (l!=NULL && strcmp(l->nume, n)==0)
/* daca nodul a fost gasit */
return l;
return NULL;
} /* cauta */
/*---------------------------------------------------------*/
/*
*/
/*
scot1 elimina din lista ordonata alfabetic nodul
*/
/*
care are numele egal cu parametrul l
*/
/*
*/
/*---------------------------------------------------------*/
nod *scot1(nod *p, char *l)
/* p este inceputul listei din care se face eliminarea */
{
nod *l1, *l2;
for(l1=l2=p; l1!=NULL && strcmp(l1->nume, l) < 0;
l2=l1, l1=l1->alf); /* se parcurge lista ordonata alfabetic
cautand nodul cu numele egal cu l */
if (l1!=NULL && strcmp(l1->nume, l) == 0)
http://labs.cs.utt.ro/labs/pc/html/node71.html (2 of 12) [22.07.2003 16:18:24]

Sursa programului

/*daca s-a gasit nodul*/


if(l1 == l2 ) /* daca este primul nod in lista */
return p->alf;
else
{
l2->alf=l1->alf;
return p;
}
else /* nodul nu a fost gasit in lista */
{
printf("Eroare: %s nu apare in evidenta\n", l);
return p;
}
} /* scot1 */
/*---------------------------------------------------------*/
/*
*/
/*
scot2 elimina din lista ordonata crescator dupa
*/
/* varsta, nodul care are numele egal cu parametrul l
*/
/*
*/
/*---------------------------------------------------------*/
nod *scot2(nod *p, char *l)
/* p este inceputul listei din care se face eliminarea */
{
nod *l1, *l2;
for (l1=l2=p; l1!=NULL && strcmp(l1->nume, l)!=0;
l2=l1, l1=l1->varcr); /* se parcurge lista ordonata
crescator functie de varsta cautand
nodul cu numele egal cu l */
if (l1!=NULL && strcmp(l1->nume, l)==0)
/* daca s-a gasit nodul */
if(l1 == l2 ) /* daca este primul nod in lista */
return p->varcr;
else
{
l2->varcr=l1->varcr;
return p;
}
else
{
printf("Eroare: %s nu apare in evidenta\n",l);
return p;
}
} /* scot2 */
http://labs.cs.utt.ro/labs/pc/html/node71.html (3 of 12) [22.07.2003 16:18:24]

Sursa programului

/*---------------------------------------------------------*/
/*
*/
/*
scot3 elimina din lista ordonata descrescator dupa
*/
/* varsta nodul care are numele egal cu parametrul l
*/
/*
*/
/*---------------------------------------------------------*/
nod *scot3(nod *p, char *l)
/* p este inceputul listei din care se face eliminarea */
{
nod *l1, *l2;
for (l1=l2=p; l1!=NULL && strcmp(l1->nume, l)!=0;
l2=l1, l1=l1->vardes); /* se parcurge lista ordonata
descrescator functie de varsta
cautand nodul cu numele egal cu l*/
if (l1!=NULL && strcmp (l1->nume, l)==0)
/* daca s-a gasit nodul */
{
auxp=l1; /* auxp indica spre nodul care se elimina */
if (l1==l2) /* daca este primul nod in lista */
return p->vardes;
else
{
l2->vardes=l1->vardes;
return p;
}
}
else
{
printf("Eroare: %s nu apare in evidenta\n", l);
return p;
}
} /* scot3 */
/*---------------------------------------------------------*/
/*
*/
/*
intr1 introduce nodul indicat de l in lista
*/
/*
ordonata alfabetic, cu adresa de inceput in p
*/
/*
*/
/*---------------------------------------------------------*/
nod *intr1(nod *p, nod *l)
/* p este inceputul listei in care se face introducerea */
/* l este nodul care este inserat */
{
http://labs.cs.utt.ro/labs/pc/html/node71.html (4 of 12) [22.07.2003 16:18:24]

Sursa programului

nod *l1, *l2;


for(l1=l2=p; l1!=NULL && strcmp(l1->nume, l->nume)<0;
l2=l1, l1=l1->alf);
l->alf=l1;
if (l1==l2) /* daca nodul este inserat la inceputul listei */
return l;
else
{
l2->alf=l;
return p;
}
} /* intr1 */
/*----------------------------------------------------------*/
/*
*/
/*
intr2 introduce nodul indicat de l in lista ordonata
*/
/*
crescator functie de varsta, cu adresa de inceput in p */
/*
*/
/*----------------------------------------------------------*/
nod *intr2( nod *p, nod *l)
/* p este inceputul listei in care se face introducerea */
/* l este nodul care este inserat */
{
nod *l1, *l2;
for (l1=l2=p; l1!=NULL && l1->varsta<l->varsta;
l2=l1, l1=l1->varcr);
l->varcr=l1;
if (l1==l2) /* daca nodul este inserat la inceputul listei */
return l;
else
{
l2->varcr=l;
return p;
}
} /* intr2 */
/*---------------------------------------------------------*/
/*
*/
/*
intr3 introduce nodul indicat de l in lista ordonata */
/*
descrescator functie de varsta,
*/
/*
cu adresa de inceput in p
*/
http://labs.cs.utt.ro/labs/pc/html/node71.html (5 of 12) [22.07.2003 16:18:24]

Sursa programului

/*
*/
/*---------------------------------------------------------*/
nod *intr3(nod *p, nod *l)
/* p este inceputul listei in care se face introducerea */
/* l este nodul care este inserat */
{
nod *l1, *l2;
for (l1=l2=p; l1!=NULL && l1->varsta>l->varsta;
l2=l1, l1=l1->vardes);
l->vardes=l1;
if (l1==l2) /* daca nodul este inserat la inceputul listei */
return l;
else
{
l2->vardes=l;
return p;
}
} /* intr3 */
/*---------------------------------------------------------*/
/*
*/
/* introdu creeaza un nod nou pentru o persoana noua si il */
/* inlantuie in cele trei evidente
*/
/*
*/
/*---------------------------------------------------------*/
void introdu(char *n, char *lm, int v)
/* n reprezinta numele persoanei */
/* lm reprezinta locul de munca */
/* v reprezinta varsta */
{
nod *t;
if ((t=cauta(n))!=NULL)
/* daca exista deja o persoana cu numele n */
{
/* actualizeaza locul de munca */
free(t->loc_munca);
if ((t->loc_munca=(char*)malloc(strlen(lm)+1))==NULL)
{
printf("Eroare: memorie insuficienta\n");
exit(1);
}
else
{
http://labs.cs.utt.ro/labs/pc/html/node71.html (6 of 12) [22.07.2003 16:18:24]

Sursa programului

strcpy(t->loc_munca, lm); /* noul loc de munca */


t->varsta=v; /* noua varsta */
inc2=scot2(inc2, t->nume);
/* elimina nodul din lista ordonata crescator dupa varsta */
inc2=intr2(inc2, t);
/* introdu nodul in lista ordonata crescator dupa varsta */
inc3=scot3(inc3, t->nume);
/*elimina nodul din lista ordonata descrescator dupa varsta*/
inc3=intr3(inc3, t);
/* introdu nodul in lista ordonata crescator dupa varsta */
}
}
else /* daca nodul nu apare in evidenta */
/* aloca memorie pentru nod */
if ((t=(nod*)malloc(sizeof(nod)))==NULL ||
(t->nume=(char*)malloc(strlen(n)+1))==NULL ||
(t->loc_munca=(char*)malloc(strlen(lm)+1))==NULL)
{
printf("Eroare: memorie insuficienta\n");
exit(1);
}
else
{
/* initializeaza campurile nodului nou */
strcpy(t->nume, n);
strcpy(t->loc_munca, lm);
t->varsta=v;
inc1=intr1(inc1, t); /* nodul este introdus in lista 1 */
inc2=intr2(inc2, t); /* nodul este introdus in lista 2 */
inc3=intr3(inc3, t); /* nodul este introdus in lista 3 */
}
} /* introdu */
/*---------------------------------------------------------*/
/*
*/
/* parcurge lista ordonata alfabetic si afiseaza evidenta */
/*
*/
/*---------------------------------------------------------*/
void afis_alf(void)
{
nod *p;
for (p=inc1; p!=NULL ; p=p->alf)
/* parcurge lista ordonata alfabetic */
{
printf("Nume: %s\n", p->nume);
http://labs.cs.utt.ro/labs/pc/html/node71.html (7 of 12) [22.07.2003 16:18:24]

Sursa programului

printf("Loc de munca: %s\n", p->loc_munca);


printf("varsta: %d\n\n", p->varsta);
}
} /* afis_alf */
/*---------------------------------------------------------*/
/*
*/
/* afiseaza evidenta in ordinea descrescatoare a varstei */
/*
*/
/*---------------------------------------------------------*/
void afis_des(void)
{
nod *p;
for (p=inc3; p!=NULL; p=p->vardes)
/*parcurge lista ordonata descrescator in functie de varsta*/
printf("Nume: %s\n", p->nume);
} /* afis_des */
/*---------------------------------------------------------*/
/*
*/
/*
afiseaza ordonat alfabetic persoanele cu locul
*/
/*
de munca lm
*/
/*
*/
/*---------------------------------------------------------*/
void afis_loc_munca(char *lm)
{
nod *l;
for (l=inc1; l!=NULL; l=l->alf)
/* parcurge lista ordonata alfabetic */
if (strcmp(l->loc_munca, lm)==0)
/* daca are locul de munca egal cu lm */
printf(" Nume: %s\n", l->nume);
} /* afis_loc_munca */
/*---------------------------------------------------------*/
/*
*/
/* afis_varsta parcurge lista ordonata crescator functie */
/* de varsta si afiseaza toate persoanele care au
*/
/* varsta >= ca si v
*/
/*
*/
/*---------------------------------------------------------*/
void afis_varsta(int v)
{
nod *l;
http://labs.cs.utt.ro/labs/pc/html/node71.html (8 of 12) [22.07.2003 16:18:24]

Sursa programului

for (l=inc2; l!=NULL; l=l->varcr)


/* se parcurge lista ordonata functie de varsta */
if (l->varsta>=v) /* daca varsta este >= ca si limita v */
printf("Nume: %s\n", l->nume);
} /* afis_varsta */
/*---------------------------------------------------------*/
/* elimin scoate persoana cu numele egal cu s din evidenta */
/*
*/
/*---------------------------------------------------------*/
void elimin(char *s)
{
if (cauta(s)) /* daca s apare in evidenta */
{
inc1=scot1(inc1, s); /* scoate nodul din lista 1 */
inc2=scot2(inc2, s); /* scoate nodul din lista 2 */
inc3=scot3(inc3, s); /* scoate nodul din lista 3 */
/* elibereaza memoria ocupata de nodul eliminat */
free (auxp->nume);
free (auxp->loc_munca);
free (auxp);
}
else
printf("Persoana %s nu apare in evidenta\n");
} /* elimin */
/*---------------------------------------------------------*/
/*
*/
/* elimin_loc_munca elimina persoanele avind locul
*/
/*
de munca egal cu s
*/
/*
*/
/*---------------------------------------------------------*/
void elimin_loc_munca(char *s)
{
nod *l, *aux;
for (l=inc1; l!=NULL; )
if (strcmp(l->loc_munca, s)==0)
/* s-a gasit o persoana cu locul de munca cautat */
{
aux=l->alf;
elimin(l->nume); /* elimina persoana gasita */
l=aux;
http://labs.cs.utt.ro/labs/pc/html/node71.html (9 of 12) [22.07.2003 16:18:24]

Sursa programului

}
else
l=l->alf;
} /* elimin_loc_munca */

Fisierul main.c
#include <stdio.h>
#include <conio.h>
#include "tip.h"
/*---------------------------------------------------------*/
/*
*/
/*
Functia meniu afiseaza meniul programului, citeste
*/
/*
comanda si apeleaza rutina care implementeaza
*/
/*
functionalitatea comenzii respective
*/
/*
*/
/*---------------------------------------------------------*/
void meniu(void)
{
char c, s[30], lm[30];
int v;
nod *t;
while (1)
{
clrscr();
printf("aprintf("tprintf("lprintf("p-

Introducerea unei persoane noi in evidenta\n");


Cautarea unui nume in evidenta\n");
Tipareste persoanele cu un anumit loc de munca\n");
Afiseaza persoanele de varsta mai mare sau
egala cu o valoare citita\n");
printf("s- Elimina o persoana din evidenta\n");
printf("d- Elimina persoanele cu un anumit loc de munca\n");
printf("n- Afiseaza alfabetic persoanele din evidenta\n");
printf("v- Afiseaza persoanele in ordinea descrescatoare
a varstei\n");
printf("f- Termina programul\n\n\n");
printf(" Introduceti optiunea: ");
c=getchar(); getchar(); /* citeste optiunea */
switch( c )
{
case 'a':
printf("Numele persoanei: "); gets(s); /* citeste numele */
printf(" Locul de munca: "); gets(lm);

http://labs.cs.utt.ro/labs/pc/html/node71.html (10 of 12) [22.07.2003 16:18:24]

Sursa programului

/* citeste locul de munca */


printf(" Varsta: "); scanf("%d", &v); getchar();
/* citeste varsta */
introdu(s, lm, v);
/* persoana si datele aferente sunt introduse in evidenta */
break;
case 'v':
afis_des();
/* tipareste evidenta in ordinea descrescatoare a varstei */
break;
case 't':
printf("Numele persoanei: "); gets(s); /* citeste numele */
if ((t=cauta(s))!=NULL) /*daca persoana apare in evidenta*/
{
printf("Nume: %s\n", t->nume);
printf("Loc de munca: %s\n", t->loc_munca);
printf("varsta: %d\n", t->varsta);
}
else
printf("%s nu apare in evidenta\n",s);
break;
case 'l':
printf(" Locul de munca: "); gets(lm); /* citeste numele */
afis_loc_munca(lm);
/* afiseaza persoanele cu locul de munca citit */
break;
case 'p':
printf(" varsta limita: ");
scanf("%d", &v);
/* citeste varsta */
getchar();
afis_varsta(v);
/* afiseaza persoanele cu varsta >= ca limita */
break;
case 's':
printf(" Numele persoanei: "); gets(s); /* citeste numele */
elimin(s); /* elimina persoana cu numele s din evidenta */
break;
case 'd':
printf(" Locul de munca: "); gets(lm); /* citeste numele */
elimin_loc_munca(lm);
/* elimina persoanele cu un anumit loc de munca */
break;
case 'n':
afis_alf();
http://labs.cs.utt.ro/labs/pc/html/node71.html (11 of 12) [22.07.2003 16:18:24]

Sursa programului

/* afiseaza evidenta in ordine alfabetica */


break;
case 'f':
return; /* incheie meniu */
}
getchar();
}
} /* meniu */

/*---------------------------------------------------------*/
/*
*/
/*
Functia main apeleaza functia meniu
*/
/*
*/
/*---------------------------------------------------------*/
void main()
{
meniu();
} /* main */

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node71.html (12 of 12) [22.07.2003 16:18:24]

Comentarea programului

next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Sursa programului Cuprins

Comentarea programului
Problema cere tiparirea persoanelor din evidenta, ordonate dupa trei criterii:
ordonate dupa nume (comanda n), ordonate descrescator dupa vrsta (comanda v)
si ordonate crescator dupa vrsta (comanda p). Din acest motiv, implementam
evidenta printr-o lista multiplu nlantuita (fiecare nod fiind atasat unei persoane),
iar criteriile de nlantuire a nodurilor corespunznd celor trei moduri de afisare
cerute.
Programul este mpartit pe trei fisiere. tip.h defineste tipul nodurilor din lista si
declara operatorii pentru prelucrarea tipului abstract, lista.c defineste tipul
abstract lista multiplu nlantuita, iar main.c defineste rutina pentru interfata cu
utilizatorul si functia main.
Nodurile listei cuprind urmatoarele cmpuri:

nume - pentru numele angajatului


loc_munca - pentru locul de munca
varsta - pentru vrsta angajatului
alf - pentru nlantuirea n ordine alfabetica
varcr - pentru nlantuirea n ordine crescatoare dupa vrsta
vardes - pentru nlantuirea n ordine descrescatoare dupa vrsta.

Datorita nlantuirilor multiple, fiecare nod apare nlantuit n listele atasate celor
trei criterii de ordonare. Variabilele inc1, inc2 si inc3 (din fisierul lista.c) indica
spre nceputurile listelor ordonate alfabetic, crescator dupa vrsta si, respectiv,
descrescator dupa vrsta. Functia cauta parcurge lista ordonata alfabetic (folosind
cmpul alf) si cauta persoana cu numele egal cu parametrul n. Daca un astfel de
nod exista, atunci cauta returneaza pointerul la el, altfel NULL.

http://labs.cs.utt.ro/labs/pc/html/node72.html (1 of 3) [22.07.2003 16:18:24]

Comentarea programului

Cnd introducem un nod nou, el trebuie nlantuit dupa fiecare din cele trei criterii.
Functia intr1 introduce nodul referit prin parametrul l n lista indicata de
parametrul p, astfel nct lista sa ramna ordonata alfabetic. Functia returneaza
pointerul catre nceputul listei rezultate. n mod asemanator, intr2 si intr3
nlantuie nodul indicat de l dupa criteriile ordonat crescator si descrescator dupa
vrsta. Operatorul pentru introducerea unui nod nou n lista multiplu nlantuita
este introdu. El are trei parametri, char *n pentru numele, char *lm pentru
locul de munca si int v pentru vrsta nodului nou. introdu ncepe prin a
verifica daca n evidenta apare deja o persoana cu numele n. n caz afirmativ se
actualizeaza cmpurile loc_munca si varsta cu noile valori. n urma acestor
modificari, pozitiile nodului n listele ordonate crescator si descrescator dupa
vrsta se schimba. De aceea, scoatem nodul din pozitiile anterioare si l
reintroducem conform noilor cmpuri. Daca persoana nu apare n evidenta, atunci
se creeaza un nod nou, se initializeaza cmpurile lui, apoi nodul este nlantuit
dupa cele trei criterii de ordonare.
n mod asemanator, daca un nod trebuie eliminat din evidenta, el este scos din
toate cele trei nlantuiri. scot1 elimina nodul din nlantuirea alf (cea ordonata
alfabetic dupa nume), scot2 scoate nodul din nlantuirea dupa varcr (ordonata
crescator dupa vrsta) si scot3 elimina nodul din nlantuirea dupa vardes
(ordonata descrescator dupa vrsta). Operatorul (elimin) pentru stergerea
persoanei cu numele dat de parametrul char *s apeleaza scot1, scot2 si scot3,
dupa care elibereaza memoria ocupata de nodul sters. Pentru aceasta, foloseste
variabila globala auxp pe care o pozitioneaza functia scot3.
afis_alf este operatorul pentru afisarea persoanelor ordonate dupa nume. afis_des
tipareste persoanele ordonate descrescator dupa vrsta. afis_varsta parcurge lista
ordonata crescator dupa vrsta si afiseaza persoanele care au cmpul varsta mai
mare ca si parametrul int v.
afis_loc_munca tipareste ordonat alfabetic persoanele cu locul de munca dat de
parametrul char *lm.
elimin_loc_munca scoate din evidenta toate persoanele cu locul de munca egal cu
parametrul char *s. Rutina parcurge lista ordonata alfabetic si elimina
persoanele apelnd elimin.

http://labs.cs.utt.ro/labs/pc/html/node72.html (2 of 3) [22.07.2003 16:18:24]

Comentarea programului

Rutina meniu afiseaza meniul programului si functie de comanda selectata se


apeleaza operatorul tipului abstract ce implementeaza functionalitatea dorita.
next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Sursa programului Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node72.html (3 of 3) [22.07.2003 16:18:24]

Problema propusa

next

up

previous

contents

Next: Tipul abstract arbore binar Up: Liste liniare multiplu nlantuite Previous: Comentarea
programului Cuprins

Problema propusa
Clasamentul jucatorilor de tenis este alcatuit pe baza rezultatelor din turnee. Dupa
fiecare turneu disputat, jucatorii sunt rasplatiti cu un numar de puncte, functie de
clasificarea lor. De exemplu, locul I ia 10 puncte, locul II 8 puncte, etc. n orice
moment clasamentul ia n evidenta doar primii k jucatori (k este mai mic ca
numarul tuturor jucatorilor). Daca un jucator iese din clasament, el pierde
numarul de puncte adunate.
Sa se realizeze un program care efectueaza urmatoarele operatii: citeste
rezultatele din turneele disputate, actualizeaza clasamentul dupa fiecare turneu,
elimina dupa fiecare turneu jucatorii care sunt situati mai jos de locul k si afiseaza
situatia actualizata. De asemenea, programul va afisa toti jucatorii participanti n
ordine alfabetica. Pentru implementarea clasamentului, se va retine o lista dublu
nlantuita dupa doua criterii: ordonata alfabetic dupa numele jucatorilor si
ordonata dupa punctaj (doar pentru primii k jucatori).
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node73.html [22.07.2003 16:18:24]

Tipul abstract arbore binar ordonat

next

up

previous

contents

Next: Arbori binari Up: carte Previous: Problema propusa Cuprins

Tipul abstract arbore binar ordonat


Subsections
Arbori binari

Cautarea n arbori binari ordonati

Inserarea n arbori binari ordonati

Stergerea n arbori binari ordonati

Parcurgerea arborilor binari

Problema rezolvata

Sursa programului

Comentarea programului

Problema propusa

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node74.html [22.07.2003 16:18:24]

Arbori binari

next

up

previous

contents

Next: Cautarea n arbori binari Up: Tipul abstract arbore binar Previous: Tipul abstract arbore binar
Cuprins

Arbori binari
Un arbore este o multime de elemente numite noduri sau vrfuri pentru care:
1. exista un nod cu destinatie speciala (radacina arborelui);
2. celelalte noduri sunt repartizate n n $>=$ 0 seturi disjuncte A1, A2, ..., An fiecare set constituind
la rndul sau un arbore.

n structura ierarhica a arborelui, fiecare nod (mai putin radacina) este subordonat
unui alt nod (relatie fiu-parinte). Daca un nod nu are fii, el se numeste terminal
(sau frunza)
Un arbore binar este un arbore n care un nod are maxim doi fii. Arborii binari
ordonati reprezinta un caz particular al arborilor binari, n care fiecare nod
contine o informatie distincta numita cheie, cu proprietatea ca, pentru fiecare nod
, toate nodurile din subarborele stng au cheia mai mica dect cheia lui $t_{i}$
si
$t_{i}$
toate nodurile din subarborele drept au cheia mai mare dect cheia lui

. Arborii
$t_{i}$

binar ordonati se numesc si arbori de cautare.


Principalele operatii asupra arborilor binar ordonati, prezentate n continuare,
sunt: cautarea unui nod n arbore, inserarea unui nod n arbore, stergerea unui nod
din arbore si parcurgerea arborelui. Se vor prezenta algoritmii recursivi pentru
realizarea acestor operatii.
Subsections
Cautarea n arbori binari ordonati

Inserarea n arbori binari ordonati

Stergerea n arbori binari ordonati

http://labs.cs.utt.ro/labs/pc/html/node75.html (1 of 2) [22.07.2003 16:18:25]

Arbori binari

next

Parcurgerea arborilor binari


up

previous

contents

Next: Cautarea n arbori binari Up: Tipul abstract arbore binar Previous: Tipul abstract arbore binar
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node75.html (2 of 2) [22.07.2003 16:18:25]

Cautarea n arbori binari ordonati

next

up

previous

contents

Next: Inserarea n arbori binari Up: Arbori binari Previous: Arbori binari Cuprins

Cautarea n arbori binari ordonati


Algoritmul de cautare a unui nod dupa o cheie x:
1. daca arborele este vid, cautarea se ncheie fara succes;
2. se compara cheia x cu cheia c a radacinii, daca x=c cautarea se ncheie cu succes;
3. daca x $<$c, se reia algoritmul n subarborele stng;
4. daca x $>$c, se reia algoritmul n subarborele drept.

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node76.html [22.07.2003 16:18:25]

Inserarea n arbori binari ordonati

next

up

previous

contents

Next: Stergerea n arbori binari Up: Arbori binari Previous: Cautarea n arbori binari Cuprins

Inserarea n arbori binari ordonati


Algoritmul de inserare a unui nod cu cheia x:
1. daca arborele este vid, se creeaza un nod nou cu cheia x, care va fi radacina arborelui;
2. daca cheia c a radacinii este egala cu x, inserarea se opreste fara a modifica arborele;
3. daca x $<$c, se reia algoritmul pentru subarborele stng;
4. daca x $>$c, se reia algoritmul pentru subarborele drept;

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node77.html [22.07.2003 16:18:25]

Stergerea n arbori binari ordonati

next

up

previous

contents

Next: Parcurgerea arborilor binari Up: Arbori binari Previous: Inserarea n arbori binari Cuprins

Stergerea n arbori binari ordonati


n cazul stergerii unui nod, se disting trei situatii:
1. daca cheia x nu se gaseste n arbore, atunci nu se modifica arborele;
2. daca nodul cu cheia x are cel mult un descendent, atunci nodul cu cheia x se sterge, locul sau fiind
luat de unicul sau descendent;
3. daca nodul cu cheia x are doi descendenti, atunci nodul cu cheia x se sterge, fiind nlocuit de nodul
cu cheia cea mai mare din subarborele stng (cel mai din dreapta nod al subarborelui stng) sau
nlocuit de nodul cu cheia cea mai mica din subarborele drept (cel mai din stnga nod al
subarborelui drept).

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node78.html [22.07.2003 16:18:25]

Parcurgerea arborilor binari

next

up

previous

contents

Next: Problema rezolvata Up: Arbori binari Previous: Stergerea n arbori binari Cuprins

Parcurgerea arborilor binari


Exista trei metode de parcurgere a arborilor binari: preordine inordine si
postordine.
1. Preordine: se viziteaza radacina, dupa care se parcurge subarborele stng si apoi cel drept;
2. Inordine: se parcurge subarborele stng, dupa care se viziteaza radacina, apoi se parcurge si
subarborele drept;
3. Postordine: se parcurge subarborele stng, dupa care se parcurge subarborele drept, apoi se
viziteaza radacina.

Dintre cele trei parcurgeri, pentru un arbore binar ordonat, parcurgerea n


inordine va genera o lista a nodurilor ordonata crescator dupa cheile nodurilor.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node79.html [22.07.2003 16:18:26]

Problema rezolvata

next

up

previous

contents

Next: Sursa programului Up: Tipul abstract arbore binar Previous: Parcurgerea arborilor binari
Cuprins

Problema rezolvata
Sa se realizeze un program care raspunde la urmatoarele comenzi:
''a'' - Se citeste o linie de forma:
identificator

numar

unde numar este un numar ntreg. Ca rezultat, se retine n evidenta identificatorul


mpreuna cu numarul asociat lui.
''t'' - Se citeste o linie ce contine un identificator. Daca acesta apare n evidenta, se
tipareste valoarea asociata lui; n caz contrar se tipareste un mesaj de eroare.
''s'' - Se citeste o linie ce contine un identificator si l sterge din evidenta.
''l'' - Se tiparesc identificatorii din evidenta n ordine alfabetica mpreuna cu
valorile asociate lor.
''+'' - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii
se afla n evidenta se tipareste suma lor. n caz ca unul sau ambii identificatori
lipsesc din evidenta, se afiseaza un mesaj de eroare.
''-'' - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii
se afla n evidenta se tipareste diferenta lor. n caz ca unul sau ambii identificatori
lipsesc din evidenta, se afiseaza un mesaj de eroare.
''*'' - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii
se afla n evidenta se tipareste produsul lor. n caz ca unul sau ambii identificatori
lipsesc din evidenta se afiseaza un mesaj de eroare.

http://labs.cs.utt.ro/labs/pc/html/node80.html (1 of 2) [22.07.2003 16:18:26]

Problema rezolvata

''/'' - Se citesc doua linii, fiecare continnd un identificator. n cazul n care ambii
se afla n evidenta se tipareste rezultatul mpartirii lor. n caz ca unul sau ambii
identificatori lipsesc din evidenta se afiseaza un mesaj de eroare.
''f'' - Se termina programul.

Observatii:

Identificatorii sunt pastrati n tabela n mod ordonat.


Se vor prezenta si comenta structurile de date folosite.
Se va prezenta si comenta structura de ansamblu a programului, fisierele componente, functiile ce
compun programul si efectul lor.

Subsections
Sursa programului

next

Comentarea programului
up

previous

contents

Next: Sursa programului Up: Tipul abstract arbore binar Previous: Parcurgerea arborilor binari
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node80.html (2 of 2) [22.07.2003 16:18:26]

Sursa programului

next

up

previous

contents

Next: Comentarea programului Up: Problema rezolvata Previous: Problema rezolvata Cuprins

Sursa programului
Fisierul arbore.h
#define Max 20 /* lungimea maxima a unui identificator */

typedef struct pn
{
char *id; /* campul pemtru identificator */
int valoare; /* campul pentru valoare */
struct pn *stang, *drept; /* fiul stang si drept al nodului */
} nod; /* tipul unui nod din arborele binar ordonat */
/* functiile prin care tipul abstract arbore este prelucrat*/
void sterge(char*);
void listare(void);
nod *cauta(char*);
void introdu(char*, int);

Fisierul arbore.c
#include
#include
#include
#include
#include
#include

<stdio.h>
<string.h>
<stdlib.h>
<ctype.h>
<conio.h>
"arbore.h"

static nod *root = NULL; /* radacina arborelui */


/*---------------------------------------------------------*/
/*
*/
/* prezent verifica daca in arborele cu radacina indicata */
/* de t exista un nod avand campul id egal cu parametrul
*/
/* id
*/

http://labs.cs.utt.ro/labs/pc/html/node81.html (1 of 11) [22.07.2003 16:18:27]

Sursa programului

/*
*/
/*---------------------------------------------------------*/
nod *prezent (nod *t, char *id)
{
if (t==NULL)
return NULL; /* nodul nu a fost gasit */
if (strcmp (t->id, id)<0)
/* incearca pentru subarborele drept */
return prezent(t->drept, id);
if (strcmp (t->id, id)>0)
/* incearca pentru subarborele stang */
return prezent (t->stang, id);
return t; /* nodul a fost gasit */
} /* prezent */
/*---------------------------------------------------------*/
/*
*/
/*
adauga introduce in arborele indicat de t un nod nou */
/*
avand campul id si valoarea v
*/
/*
*/
/*---------------------------------------------------------*/
nod *adauga(nod *t, char *id, int v)
{
if (t==NULL) /* nodul nu exista si este creat */
{
if ((t=(nod*)malloc(sizeof(nod)))==NULL ||
(t->id=(char*)malloc(strlen(id)+1))==NULL)
{
printf("Eroare: memorie insuficienta\n");
exit(1);
}
/* s-a putut crea nodul */
strcpy(t->id, id);
t->valoare=v;
t->stang=t->drept=NULL;
}
else
if (strcmp(t->id, id)<0)
/* inserarea e in subarborele drept */
t->drept=adauga(t->drept, id, v);
else
if (strcmp(t->id, id)>0)
http://labs.cs.utt.ro/labs/pc/html/node81.html (2 of 11) [22.07.2003 16:18:27]

Sursa programului

/* inserarea e in subarborele stang */


t->stang=adauga(t->stang, id, v);
else
printf("Identificatorul %s apare in evidenta\n",id);
return t;
} /* adauga */
/*---------------------------------------------------------*/
/*
*/
/*
supred rutina auxiliara pentru eliminarea nodurilor
*/
/*
cu doi fii
*/
/*
*/
/*---------------------------------------------------------*/
nod *supred (nod *t, nod *p)
{
nod *q, *q_aux;
q=t;
if (q->drept!=NULL)
/* gaseste nodul cel mai mare din subarborele indicat de t */
q->drept=supred(q->drept, p);
else /* pentru nodul cel mai mare din subarborele indicat de t */
{
free(p->id);
/* muta campurile nodului indicat de q in nodul indicat de p */
p->id=q->id;
p->valoare=q->valoare;
q_aux=q;
q=q->stang; /* fiul stang este returnat */
free(q_aux); /* elibereaza memoria ocupata de nod */
}
return q;
} /* supred */

/*---------------------------------------------------------*/
/*
*/
/* elimina scoate nodul avand campul id egal cu parametrul */
/* id din arborele indicat de parametrul p
*/
/*
*/
/*---------------------------------------------------------*/
nod *elimina(nod *p, char *id)
{
nod *q, *q1;
char *s;
http://labs.cs.utt.ro/labs/pc/html/node81.html (3 of 11) [22.07.2003 16:18:27]

Sursa programului

if (p==NULL)
{
printf("Eroare: %s nu apare in evidenta\n", id);
return NULL;
}
if (strcmp(p->id, id)<0) /* nodul e in subarborele drept */
{
p->drept=elimina(p->drept, id);
return p;
}
if (strcmp(p->id, id)>0) /* nodul e in subarborele stang */
{
p->stang=elimina(p->stang, id);
return p;
}
/* s-a gasit nodul ce trebuie sters */
if (p->stang==NULL) /* daca nu are fiu stang */
{
q=p->drept;
free(p->id);
free(p);
return q;
}
if (p->drept==NULL) /* nu are fiu drept */
{
q=p->stang;
free(p->id);
free(p);
return q;
}
/* are ambii fii */
p->stang=supred(p->stang, p);
return p;
} /* elimina */

/*---------------------------------------------------------*/
/*
*/
/* parcurge in inordine arborele cu radacina indicata de t */
http://labs.cs.utt.ro/labs/pc/html/node81.html (4 of 11) [22.07.2003 16:18:27]

Sursa programului

/* si afiseaza nodurile
*/
/*
*/
/*---------------------------------------------------------*/
void tipareste (nod *t)
{
if (t!=NULL)
{
tipareste(t->stang); /* tipareste subarborele stang */
printf("%s : %d\n", t->id, t->valoare);
tipareste(t->drept); /* tipareste subarborele drept */
}
} /* tipareste */

/*---------------------------------------------------------*/
/*
*/
/*
Operatorul de listare al tipului abstract
*/
/*
*/
/*---------------------------------------------------------*/
void listare(void)
{
tipareste(root);
} /* listare */

/*---------------------------------------------------------*/
/*
*/
/*
Operatorul de cautare al tipului abstract
*/
/*
*/
/*---------------------------------------------------------*/
nod *cauta(char *s)
{
return prezent(root, s);
} /* cauta */

/*---------------------------------------------------------*/
/*
*/
/*
Operatorul de stergere al tipului abstract
*/
/*
*/
/*---------------------------------------------------------*/
void sterge(char *s)
http://labs.cs.utt.ro/labs/pc/html/node81.html (5 of 11) [22.07.2003 16:18:27]

Sursa programului

{
root=elimina(root, s);
} /* sterge */
/*---------------------------------------------------------*/
/*
*/
/*
Operatorul de introducere al tipului abstract
*/
/*
*/
/*---------------------------------------------------------*/
void introdu(char *s, int v)
{
root=adauga(root, s, v);
} /* introdu */

Fisierul main.c
#include
#include
#include
#include
#include

<stdio.h>
<ctype.h>
<string.h>
<conio.h>
"arbore.h"

/*---------------------------------------------------------*/
/*
*/
/* Functia getlin citeste urmatoarea linie de la tastatura*/
/* si recunoaste identificatorul si valoarea asociata lui.*/
/* Identificatorul este returnat in parametrul s, iar
*/
/* valoarea in parametrul val
*/
/*
*/
/*---------------------------------------------------------*/
void getlin(char *s ,int *val)
{
int i=0, j;
char temp[Max];
gets(temp);/* citeste urmatoarea linie de la tastatura */
/* getlin 1 */
s[i]='\0'; *val=0; /* initializeaza valorile argumentelor */
while (temp[i]!='\0')
/* atata timp cat nu a fost atins sfarsitul sirului */
/* getlin 2 */
if(isalpha(temp[i]))/* daca incepe un identificator */
/* getlin 3 */

http://labs.cs.utt.ro/labs/pc/html/node81.html (6 of 11) [22.07.2003 16:18:27]

Sursa programului

{
j=0;
while (isalnum(temp[i]))
s[j++]=temp[i++];
/*getlin 4*/
/* memoreaza identificatorul in s */
s[j]='\0'; /* memoreaza sfarsitul de sir */
/* getlin 5 */
}
else
if (isdigit(temp[i])) /* daca incepe un numar */
/* getlin 6 */
while (isdigit(temp[i])) /* getlin 7 */
{
*val=*val*10+temp[i]-'0'; /* calculeaza valoarea numarului */
/* getlin 8 */
i++;
}
else /* altfel se trece peste caracterul curent */
i++; /* getlin 9 */
} /* getlin */

/*---------------------------------------------------------*/
/*
*/
/*Functia comanda_a realizeaza functionalitatea comenzii a */
/*
*/
/*---------------------------------------------------------*/
void comanda_a(void)
{
int val;
char s[Max];
getlin(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)!=0) /* daca linia e corecta */
introdu(s, val);
else
printf(" Eroare : linie incorecta \n");
} /* comanda_a */
/*---------------------------------------------------------*/
/*
*/
/*Functia comanda_t realizeaza functionalitatea comenzii t */
/*
*/
http://labs.cs.utt.ro/labs/pc/html/node81.html (7 of 11) [22.07.2003 16:18:27]

Sursa programului

/*---------------------------------------------------------*/
void comanda_t(void)
{
char s[Max];
nod *p;
int val;
getlin(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)!=0) /* daca linia e corecta */
{
if ((p=cauta(s))!=NULL) /* cauta nodul in lista */
printf("Identificator: %s Valoare: %d \n",
p->id, p->valoare);
else
printf("Eroare: Identificator nedefinit \n");
}
else
printf(" Eroare: linie incorecta \n");
} /* comanda_t */
/*---------------------------------------------------------*/
/*
*/
/*Functia comanda_s realizeaza functionalitatea comenzii s */
/*
*/
/*---------------------------------------------------------*/
void comanda_s(void)
{
char s[Max];
int val;
getlin(s, &val); /* citeste o linie de la tastatura */
if (strlen(s)!=0) /* daca linia citita e corecta */
sterge(s); /* sterge nodul din lista */
else
printf(" Eroare: linie incorecta \n");
} /* comanda_s */

/*---------------------------------------------------------*/
/*
*/
/*
Functia comanda_oper executa operatiile legate de
*/
/* comenzile +, -, * si /. Se citesc cei doi operatori si */
/* se executa operatia dorita.Rezultatul este afisat
*/
/*
*/
http://labs.cs.utt.ro/labs/pc/html/node81.html (8 of 11) [22.07.2003 16:18:27]

Sursa programului

/*---------------------------------------------------------*/
void comanda_oper(char c)
{
char s1[Max], s2[Max];
int val;
nod *p1, *p2;
getlin(s1, &val); /* se citeste primul operand */
getlin(s2, &val); /* se citeste al doilea operand */
if ((strlen(s1)!=0) && (strlen(s2)!=0))
if (((p1=cauta(s1))!=NULL) && ((p2=cauta(s2))!=NULL))
/* se verifica daca operanzii apar in lista */
{
switch(c) /* in functie de tipul comenzii */
{
case '+':
val=p1->valoare+p2->valoare;
break;
case '-':
val=p1->valoare-p2->valoare;
break;
case '*':
val=p1->valoare*p2->valoare;
break;
case '/':
if (p2->valoare!=0)
val=p1->valoare/p2->valoare;
else
printf("Eroare:Impartire la 0\n");
break;
}
printf(" Rezultatul operatiei e %d \n", val);
}
else
printf("Operand nedefinit \n");
else
printf(" Eroare: linie eronata \n");
} /* comanda_oper */

/*---------------------------------------------------------*/
/*
*/
/* Functia meniu afiseaza meniul programului, citeste
*/
/* comanda si apeleaza subrutina care implementeaza
*/
http://labs.cs.utt.ro/labs/pc/html/node81.html (9 of 11) [22.07.2003 16:18:27]

Sursa programului

/* functionalitatea comenzii
*/
/*
*/
/*---------------------------------------------------------*/
void meniu(void)
{
char o;
while (1) /* meniu 1 */
{
clrscr();
/* se afiseaza meniul programului */
printf("a adauga in evidenta un id si val asociata\n");
printf("t tipareste valoarea asociata unui id \n");
printf("s sterge un id \n");
printf("l listeaza id-rii si valorile asociate lor\n");
printf("+ calculeaza suma pentru 2 id \n");
printf("- calculeaza diferenta pentru 2 id \n");
printf("* calculeaza produsul pentru 2 id \n");
printf("/ calculeaza impartirea pentru 2 id \n");
printf("f termina programul \n");
printf("\n Introduceti optiunea :");
o=getchar(); getchar(); /* meniu 2 */
switch (tolower(o)) /* meniu 3 */
{
case 'a':
comanda_a();
break;
case 't':
comanda_t();
break;
case 's':
comanda_s();
break;
case 'l':
listare();
break;
case '+': case '-': case '*': case '/':
comanda_oper(o);
break;
case 'f':
return;
default:
printf(" Eroare : Comanda inexistenta \n");
}
getchar();
http://labs.cs.utt.ro/labs/pc/html/node81.html (10 of 11) [22.07.2003 16:18:27]

Sursa programului

}
}

/*---------------------------------------------------------*/
/*
*/
/*
Functia main apeleaza functia meniu
*/
/*
*/
/*---------------------------------------------------------*/
void main(void)
{
meniu();
}

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node81.html (11 of 11) [22.07.2003 16:18:27]

Comentarea programului

next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Sursa programului Cuprins

Comentarea programului
Programul este compus din trei fisiere:
Primul fisier, arbore.h contine definitia de tip pentru un nod al arborelui, precum
si declaratiile functiilor ce apartin tipului abstract arbore binar ordonat.
Al doilea fisier, arbore.c contine definitia tipului abstract arbore binar ordonat.
Functia prezent cauta nodul din arborele indicat de parametrul t, care are cmpul
id egal cu sirul indicat de parametrul id. prezent returneaza pointerul catre nodul
n care s-a gasit identificatorul sau NULL daca acest nod nu exista.
tipareste parcurge arborele n inordine si afiseaza continutul lui. tipareste afiseaza
nti subarborele stng (apelndu-se recursiv pentru fiul stng al nodului curent),
apoi nodul curent si n final subarborele drept (apelndu-se recursiv pentru fiul
drept al nodului curent).
elimina sterge din arborele cu radacina p nodul al carui cmp id este egal cu
parametrul id. elimina returneaza radacina arborelui modificat. Daca p este NULL
nseamna ca nu exista nodul cautat n arbore si se afiseaza un mesaj de eroare.
Daca nodul curent are cmpul id mai mic dect parametrul id, atunci cautarea
nodului continua n subarborele drept. Din acest motiv, elimina este apelata
recursiv pentru fiul drept al nodului curent. n mod asemanator, daca cmpul id al
nodului curent este mai mare ca si parametrul id, atunci elimina este apelata
pentru fiul stng. Cnd nodul ce trebuie eliminat a fost gasit, distingem trei
situatii. n prima, nodul nu are fiu stng. Se elibereaza memoria ocupata de nod si
returnam fiul sau drept. Situatia a doua este cnd nodul nu are fiu drept si atunci
returnam fiul sau stng. Al treilea caz este cnd nodul are ambii fii si atunci
cautam pe cel mai mare nod care este mai mic ca cel care trebuie sters. El va fi
mutat n locul celui care trebuie eliminat si apoi l stergem din vechea pozitie.
ntotdeauna, acest nod nu are fiu drept (daca ar avea, acesta ar fi mai mare ca el),
http://labs.cs.utt.ro/labs/pc/html/node82.html (1 of 2) [22.07.2003 16:18:27]

Comentarea programului

iar eliminarea lui se face ca pentru un nod doar cu fiu stng. Pentru a gasi nodul
precizat, vom parcurge n subarborele stng nlantuirile pentru fiul drept. Rutina
supred realizeaza acest lucru.
adauga introduce un nod nou n arborele indicat de parametrul t. Nodul are
cmpul id egal cu parametrul id si cmpul valoare egal cu v. Rutina returneaza
radacina arborelui modificat.
Toate aceste functii au ca si parametru formal radacina arborelui prelucrat,
radacina care nu este vizibila n exteriorul fisierului n care a fost definita (din
cauza clasei de memorare static). Folosind aceste functii se definesc cauta,
sterge, listare si introdu, operatorii prin care tipul abstract arbore ordonat este
prelucrat.
Al treilea fisier, main.c contine functia main, functia pentru citirea comenzilor,
rutina de afisare si prelucrare a meniului si rutinele auxiliare pentru
implementarea comenzilor.
next

up

previous

contents

Next: Problema propusa Up: Problema rezolvata Previous: Sursa programului Cuprins Cristian
Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node82.html (2 of 2) [22.07.2003 16:18:27]

Problema propusa

next

up

previous

contents

Next: Probleme propuse spre rezolvare Up: Tipul abstract arbore binar Previous: Comentarea
programului Cuprins

Problema propusa
O baza de date pastreaza informatii despre marfurile dintr-un magazin. Baza de
date e realizata folosind un arbore binar ordonat. Sa se scrie un program care
realizeaza urmatoarele:
- introduce o noua marfa n baza de date;
- tipareste baza de date ordonata dupa numele marfii si separat dupa pret;
- sterge toate marfurile cu termenul de garantie expirat;
- creeaza un arbore binar ordonat dupa pret, arbore care va contine doar marfurile
cu un pret mai mic ca o valoare data p. Valoarea p se citeste.
Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node83.html [22.07.2003 16:18:27]

Probleme propuse spre rezolvare

next

up

previous

contents

Next: Setul 1 Up: carte Previous: Problema propusa Cuprins

Probleme propuse spre rezolvare


Subsections
Setul 1

Setul 2

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node84.html [22.07.2003 16:18:28]

Setul 1

next

up

previous

contents

Next: Setul 2 Up: Probleme propuse spre rezolvare Previous: Probleme propuse spre rezolvare
Cuprins

Setul 1
1. Sa se realizeze un editor de texte. Textul initial este ncarcat dintr-un fisier, iar
textul modificat este salvat ntr-un fisier nou. Editarea se face prin urmatoarele
comenzi:
I, m - insereaza o linie dupa linia m;
D, m, n - sterge liniile ntre liniile m si n;
R, m, n - nlocuieste liniile ntre m si n cu linii noi;
E - termina procesul de editare.

2. Sa se genereze toate posibilitatile de planificare a unui turneu la care participa


n concurenti, stiind ca doi concurenti se ntlnesc o singura data si un concurent
disputa un singur joc pe zi.

3. Pentru elaborarea unui test de aptitudini se dispune de un set de n ntrebari.


Fiecare ntrebare este cotata cu un numar de puncte. Sa se elaboreze toate
chestionarele posibile care au un numar de ntrebari cuprins ntre a si b (a si b se
citesc de la tastatura), astfel nct numarul total de puncte pe chestionar sa fie
cuprins ntre p si q (p si q se citesc de la tastatura).

http://labs.cs.utt.ro/labs/pc/html/node85.html (1 of 8) [22.07.2003 16:18:29]

Setul 1

4. ntr-un grup de persoane, fiecare persoana cunoaste eventual alte persoane din
grup. Sa se formeze toate echipele posibile, astfel nct pentru o echipa, fiecare
persoana este cunoscuta de cel putin un membru al acelei echipe.

5. Se da un grup de orase si conexiunile ntre ele. Sa se gaseasca toate drumurile


care trec prin toate orasele parcurgndu-le o singura data.

6. Pozitiile oraselor unei tari sunt date prin coordonatele lor carteziene. Sa se
gaseasca configuratia retelei telefonice care ndeplineste conditiile:
- orice oras este conectat la reteaua telefonica;
- costul retelei (proportional cu lungimea liniilor telefonice) este minim.

7. O harta cuprinde n tari. Sa se gaseasca numarul minim de culori cu care pot fi


colorate tarile, astfel nct doua tari vecine sa nu fie colorate cu aceeasi culoare.

8. Se considera o cale ferata de forma celei din Figura 11.1. Pe linia de intrare se
afla n vagoane numerotate de la 1 la n. Notam cu I operatia de introducere a
vagoanelor de pe prima pozitie pe linia de intrare n stiva, si cu S cea de extragere
din vrful stivei catre iesire. Alte operatii nu sunt permise.

http://labs.cs.utt.ro/labs/pc/html/node85.html (2 of 8) [22.07.2003 16:18:29]

Setul 1

\begin{figure}\begin{center}
\epsfig{file=stiva.eps, height=6cm}\end{center}\end{figure}

Figura 11.1:

Pentru un anumit numar de vagoane dat, programul va realiza urmatoarele:


a) Dndu-se la intrare o secventa de forma : ISSI... sa se raspunda daca
secventa respectiva de operatii poate fi executata.
b) Dndu-se o permutare oarecare a numerelor 1...n, sa se spuna daca ea poate fi
obtinuta pe linia de iesire, pornind de la n vagoane aflate n ordine pe linia de
intrare. n caz afirmativ, sa se dea succesiunea de operatii I si S care duce la
configuratia respectiva.
c) Sa se tipareasca toate secventele de vagoane, care pot fi obtinute pe linia de
iesire, pentru n dat initial.

9. Problema "Descendentilor dupa parinte":


Petre stie ca este fiul lui Ion si mai stie ca este frate cu Virgil si Matei. Copiii lui
Petre sunt Ilie si Marcu, iar ai lui Virgil sunt: Ionel si Petrica. Filip stie ca este fiul
lui Matei si frate cu Ioana. Sabin este fiul lui Ionel.

http://labs.cs.utt.ro/labs/pc/html/node85.html (3 of 8) [22.07.2003 16:18:29]

Setul 1

Ion doreste sa stie numele tuturor nepotilor sai.


Filip vrea sa stie daca pe bunicul lui l cheama Ilie.
Ionel vrea sa stie daca este var cu Alexandru.
Sa se scrie programul, care pe baza unor informatii de acest tip, este n masura sa
raspunda la urmatoarele genuri de ntrebari:
1) Care sunt nepotii bunicului "nume"?
2) "nume1" este bunicul lui "nume2"?
3) "nume1" este var primar cu "nume2"?
Se va verifica daca datele de intrare sunt consistente. Se considera ca doua
persoane sunt diferite daca au nume diferite.
Datele de intrare se citesc dintr-un fisier cu numele REGULI.DAT, avnd cte o
regula pe fiecare linie. Regulile sunt de forma: "nume1"=FIU("nume2") sau
"nume1"=FRATE("nume2") unde "nume1" si "nume2" sunt siruri de maxim
20 de litere (literele mici si cele mari se considera identice). Este permisa
folosirea unor separatori de forma spatiu si tab. Detectarea caracterului $ la
nceputul unei linii reprezinta sfrsitul sirului de reguli. Dupa ce s-au citit toate
regulile, de pe liniile urmatoare se citesc tipul ntrebarii (1, 2 sau 3) si informatiile
aferente acestuia, separate prin virgula. Fiecare ntrebare se citeste de pe o linie.
Datele de iesire se vor scrie sub forma:
"nume1"=BUNIC("nume2",...,"numep") pentru primul tip de ntrebare,
sau ESTE, NU ESTE sau EROARE pentru celalalte doua tipuri de ntrebari.
Raspunsurile sunt scrise pe linii distincte.

10. Un dictionar este scris ntr-un alfabet pentru care nu se stie daca exista sau nu
o ordine ntre litere. Sa se stabileasca pe baza ordinii n care apar cuvintele n
dictionar, daca exista sau nu ordine ntre literele alfabetului.

http://labs.cs.utt.ro/labs/pc/html/node85.html (4 of 8) [22.07.2003 16:18:29]

Setul 1

11. Un dreptunghi D, cu laturile paralele cu axele de coordonate este precizat prin


coordonatele (ntregi) a doua vrfuri opuse. Sa se scrie un program care
calculeaza si afiseaza aria si perimetrul conturului reuniunii D1 U D2 U ...de
dreptunghiuri. Datele de test se citesc dintr-un fisier text, ce contine pe linii
coordonatele vrfurilor unui dreptunghi n ordinea x1, y1, x2, y2.

12. Un numar de 2n + 1 persoane participa la discutii ce dureaza K zile. Sa se


gaseasca toate variantele de asezare a persoanelor la masa de discutii, astfel nct
o persoana sa nu aiba n 2 zile diferite aceiasi vecini.

13. Sa se scrie un program care citeste de la tastatura n mod repetat expresii cu


doi operanzi ntregi si un operator (+, -, *, /). Operanzii sunt exprimati n cifre
romane, iar numerele negative sunt precedate de caracterul minus. Programul
afiseaza rezultatele exprimate tot n cifre romane.

14. Se da o expresie n notatie poloneza, care contine operatorii


, AND si OR. Sa se verifice daca expresia
$+, -, *, /, <, <=, >, >=, =, <>$
furnizata este corecta:
a) Fiecarui operator sa-i corespunda doi operanzi.
b) Sa nu existe operanzi carora sa nu le corespunda operatori.
c) Sa fie respectate urmatoarele restrictii legate de tip:
Pentru

$+, -, *, /$

ambii operanzi trebuie sa fie numere. Rezultatul este tot un

numar.

http://labs.cs.utt.ro/labs/pc/html/node85.html (5 of 8) [22.07.2003 16:18:29]

Setul 1

Pentru

$<, <=, >, >=, =, <>$

operanzii sunt numere, iar rezultatul este

boolean.
Pentru AND si OR operanzii sunt de tipul boolean, iar rezultatul este tot boolean.

15. Se da n plan un poligon oarecare P cu vrfurile P1, P2, P3, P4, ...Pn ale caror
coordonate (numere ntregi) sunt citite dintr-un fisier. Sa se determine daca un
punct dat A(p,q) este n interiorul, pe laturile, sau n exteriorul poligonului P.

16. Se da o succesiune de mase, fiecare sub forma a doua numere ntregi, ce


reprezinta numarul de kilograme, respectiv de grame. Sa se tipareasca masele n
cifre si cuvinte ca n exemplul de mai jos:
871 25 opt sute saptezeci si unu kilograme si douazeci
si cinci grame
0 0 nimic
0 35 treizeci si cinci grame
113 0 o suta treisprezece kilograme

17. Studentii unui an pot alege 10 cursuri facultative: muzica, literatura, pictura,
sanscrita, arheologie, canto, poetica, gastronomie, albaneza si puericultura.
Optiunile fiecarui student se citesc de pe o linie cu urmatoarea structura: numele
studentului (ca o succesiune de caractere care se ncheie cu un punct) si n
continuare, pe zece pozitii, sunt spatii sau X. Fiecare pozitie se asociaza unui
curs, n ordinea enumerarii de mai sus, iar X pe pozitia respectiva nseamna ca
studentul a ales cursul respectiv. Un student poate alege oricte cursuri. De
exemplu:
Dumitrescu Dumitru. X

XX

http://labs.cs.utt.ro/labs/pc/html/node85.html (6 of 8) [22.07.2003 16:18:29]

Setul 1

Studentul Dumitrescu Dumitru a ales pictura, canto si poetica. La nceputul


dialogului se afla numarul studentilor, care nu depaseste 100. Sa se tiparesca,
pentru fiecare curs, lista studentilor nscrisi. Cursurile vor aparea n ordinea
descrescatoare a numarului de studenti nscrisi, iar listele de studenti sunt afisate
n ordine alfabetica.

18. Dintr-o bara de lungime L se taie m repere de lungime l1, l2, ..., lm. Sa se
gaseasca toate variantele de debitare a barei astfel nct pierderile de material sa
fie minime. Se impune ca printr-o debitare sa se obtina cel putin cte un exemplar
din fiecare reper. Valorile lui L si l1, l2, ..., lm sunt ntregi si sunt citite de la
tastatura.

19. Un nume de fisier poate contine si caracterele ? si *. Sa se scrie un program


care citeste o descriere pentru numele de fisiere si listeaza toate fisierele care
corespund descrierii. Daca astfel de fisiere nu exista atunci se afiseaza numele
cele mai apropiate de descrierea citita. Apropierea (distanta) ntre doua nume de
fisiere este stabilita de numarul minim de operatii de stergere/ inserare/ nlocuire
de caractere, necesare pentru a transforma primul cuvnt n al doilea.
Exemplu:
Pentru numele de fisiere:
DIST.BAK
DIST.EXE
DIST.PAS
RANDUL.1
RANDUL.2
RANDUL.3
C
FLORINLL
PAS
PLANIFIC
si descrierea *L*I*.*?* se va afisa (ntre paranteze este specificata distanta):
DIST.BAK (1)
DIST.EXE (1)
http://labs.cs.utt.ro/labs/pc/html/node85.html (7 of 8) [22.07.2003 16:18:29]

Setul 1

DIST.PAS
RANDUL.1
RANDUL.2
RANDUL.3
FLORINLL
PLANIFIC

(1)
(1)
(1)
(1)
(1)
(1)

20. Un automat finit consta dintr-o multime de stari (care sunt numere ntregi n
intervalul 1...n) si o matrice de tranzitie. Matricea de tranzitie precizeaza, pentru
fiecare stare si fiecare caracter de intrare, starea urmatoare. Presupunem ca
intrarile pot lua doua valori 0 sau 1. Anumite stari sunt stari finale. Presupunem
ca n cazul nostru, starile finale sunt cele al caror numar este divizibil cu 7. Doua
stari x si y sunt echivalente daca ele sunt identice sau daca ndeplinesc simultan
conditiile:
(1) Ambele sunt finale sau nefinale.
(2) Pentru o intrare 0, ambele trec n stari echivalente.
(3) Pentru o intrare 1, ambele trec n stari echivalente.
Programul calculeaza multimea starilor echivalente, pentru un automat finit dat.
next

up

previous

contents

Next: Setul 2 Up: Probleme propuse spre rezolvare Previous: Probleme propuse spre rezolvare
Cuprins Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node85.html (8 of 8) [22.07.2003 16:18:29]

Setul 2

next

up

previous

contents

Next: Bibliografie Up: Probleme propuse spre rezolvare Previous: Setul 1 Cuprins

Setul 2
1. Sa se realizeze un program pentru rezervarea locurilor la o companie de zbor.
Programul are urmatoarele comenzi:
ZBOR

$<$numar

zbor $> <$ numar total locuri $>$

adauga n evidenta cursa


ANULARE

$<$numar

$<$numar

zbor $>$ n cazul n care aceasta nu exista deja.

zbor $>$

anuleaza cursa. Pasagerii (daca vor) si rezerva locuri la o alta cursa.


LOC

$<$numar

Pasagerul
cursa

zbor $>$

$<$nume

$<$numar

$<$nume

pasager $>$

pasager $>$ si rezerva (daca mai exista loc) un loc pentru

zbor $>$. Se permit pasageri cu acelasi nume.

RENUNT

$<$numar

Pasagerul

$<$nume

zbor $>$

$<$nume

pasager $>$

pasager $>$ renunta la locul sau din cursa

$<$numar

$>$.

PRINT

$<$numar

zbor $>$

Afiseaza n ordine alfabetica lista pasagerilor cursei

http://labs.cs.utt.ro/labs/pc/html/node86.html (1 of 13) [22.07.2003 16:18:30]

$<$numar

zbor $>$.

zbor

Setul 2

Daca s-a introdus o comanda eronata se afiseaza "eroare" si se asteapta o noua


comanda.

2. Se considera o structura de date abstracta de tip arbore binar ordonat asupra careia
sunt executate urmatoarele operatii: adaugare, cautare si suprimare. Nodurile sunt
ordonate functie de valoarea unui cmp cheie. Fiecarui nod i este atasat un contor de
acces la nodul respectiv. La anumite intervale de timp, structura se reorganizeaza
ntr-o noua structura de arbore binar ordonat, n care ordinea de creare a nodurilor
este corespunzatoare valorilor descrescatoare ale contoarelor de acces. Se cere:
a. Sa se precizeze structurile de date aferente structurii de arbore.
b. Sa se defineasca rutinele care gestioneaza structura de date arbore (adauga, cauta,
suprima ).
c. Sa se defineasca rutina pentru reorganizarea arborelui.

3. Sa se realizeze un program pentru corectarea erorilor de ortografie dintr-un text.


Cuvintele textului sunt introduse de la tastatura. Fiecare cuvnt este prelucrat astfel:
a. Daca figureaza n dictionar el este copiat n fisierul de iesire.
b. Daca nu figureaza n dictionar, atunci cuvntul este afisat la terminal si se cere
utilizatorului una din urmatoarele optiuni:
- Daca cuvntul este corect, atunci el trebuie adaugat n dictionar si n fisierul de
iesire.
- Daca cuvntul este incorect, atunci se introduce o noua forma corecta a cuvntului
care se adauga la fisierul de iesire.
- Daca cuvntul este incorect, atunci se introduce o noua forma corecta a cuvntului
care se adauga la fisierul de iesire si n plus forma incorecta este retinuta, urmnd ori
de cte ori este ntlnita, sa fie nlocuita automat cu forma corecta.

4. Un polinom P(x) se reprezinta ca o succesiune de tupleti (coeficient, putere),


ambii ntregi. Sa se realizeze un program care executa nmultiri si adunari ntre
http://labs.cs.utt.ro/labs/pc/html/node86.html (2 of 13) [22.07.2003 16:18:30]

Setul 2

polinoame. Polinoamele se introduc sub forma unei succesiuni de numere ntregi.


Primul indica numarul termenilor, iar urmatoarele N perechi de numere reprezinta
fiecare cte un tuplet. Un polinom este urmat de + sau * , functie de operatia dorita.
Dupa calcularea si afisarea rezultatului se citeste o valoare reala x, pentru care se
evalueaza derivata polinomului.
Observatie: La intrare, polinoamele se dau cu termenii n ordinea oarecare a puterii si
pot aparea mai multi termeni pentru aceeasi putere a lui x.

5. Sa se realizeze un program care raspunde la urmatoarele comenzi:


i - Citeste o linie cu urmatoarea structura:
identificator numar
numar este de forma: secventa_de_cifre sau
secventa_de_cifre.secventa_de_cifre Ca raspuns la comanda,
identificatorul este introdus n evidenta mpreuna cu valoarea asociata lui. Daca
identificatorul apare n evidenta, se tipareste un mesaj de eroare si comanda este
ncheiata.
t - Tipareste n ordine alfabetica identificatorii din evidenta.
s - Preia din intrare un identificator. Daca el exista n evidenta el este sters, n caz
contrar se tipareste un mesaj de eroare.
m - Preia din intrare o linie de forma:
identificator numar
Daca identificatorul apare n evidenta, valoarea lui este actualizata la noua valoare,
n caz contrar, el este luat n evidenta.
v - Tipareste identificatorii n ordinea inversa a valorii asociate lor.
e - Citeste din intrare o expresie n notatie postfix. Operanzii pot fi identificatori sau
numere avnd forma precizata, iar operatorii sunt $+ - * /$ . Valoarea asociata
identificatorilor este extrasa din evidenta. Daca n expresie apare un identificator
http://labs.cs.utt.ro/labs/pc/html/node86.html (3 of 13) [22.07.2003 16:18:30]

Setul 2

neluat n evidenta, se tipareste un mesaj de eroare si se abandoneaza evaluarea


expresiei. Se va calcula expresia, iar valoarea obtinuta se afiseaza.
f - Termina programul.

6. Sa se realizeze un program pentru o tabela de referinte ncrucisate dupa cum


urmeaza: citeste un text oarecare, ce se ncheie cu EOF. Dupa receptionarea
sfrsitului de text se tipareste, n ordine alfabetica, lista identificatorilor ntlniti si,
pentru fiecare identificator, numerele liniilor n care apare.
Observatie: Tabela identificatorilor este organizata sub forma unei liste. Dupa fiecare
5 operatii n lista, aceasta se va reorganiza n ordinea descrescatoare a numarului de
referiri ale nodurilor.

7. Sa se realizeze urmatorul program: Se citeste un text oarecare, care se ncheie cu


caracterul `.`. n continuare, programul raspunde la un numar de comenzi dupa cum
urmeaza:
t - Tipareste n ordine alfabetica identificatorii din evidenta si pentru fiecare numarul
de aparitii.
l - Tipareste, n ordinea lungimii identificatorilor, identificatorii din evidenta si
pentru fiecare numarul de aparitii.
s - Citeste o valoare n ntreaga. Elimina din evidenta toti identificatorii care contin n
vocale.
a - Tipareste identificatorii din evidenta n ordinea descrescatoare a numarului de
vocale continut.
v - Se citeste o vocala c si un numar ntreg n. Se cere sa se tipareasca, n ordinea
lungimii identificatorilor, acei identificatori care contin vocala c cel putin de n ori.

8. Sa se scrie un program care realizeaza urmatoarele: citeste un prim text care se


ncheie cu caracterul `.` si memoreaza identificatorii prezenti n acel text. n cazul n
http://labs.cs.utt.ro/labs/pc/html/node86.html (4 of 13) [22.07.2003 16:18:30]

Setul 2

care un identificator apare de mai multe ori n acest prim text, el se retine o singura
data. n continuare, se citeste un al doilea text care se ncheie cu EOF. Se cere sa se
tipareasca lista identificatorilor prezenti n primul text si pentru fiecare identificator
sa se mentioneze liniile din cel de-al doilea text n care este prezent. Lista este
tiparita n ordine alfabetica.

9. Se citeste un text format din linii de forma:


nume; loc_de_munca; adresa;
Textul se ncheie cu EOF. Dupa citirea textului se cere sa se tipareasca n ordine
alfabetica:
a. Lista nominala de forma: nume adresa loc_de_munca
b. Lista locurilor de munca n forma: loc_de_munca numar_angajati

10. Se citeste o succesiune de linii care se ncheie cu caracterul `.`. Aceste linii au ca
prim caracter fie #, fie * si n rest contin un text oarecare. Se vor construi trei
evidente separate continnd: identificatorii prezenti exclusiv n linii care ncep cu #,
cei prezenti exclusiv n linii care ncep cu *, si cei prezenti n linii ce ncep cu #, ct
si n linii ce ncep cu *. Fiecare identificator apare o singura data n evidenta. n
continuare se citeste un text oarecare, format din mai multe linii, care se ncheie de
asemenea cu caracterul `.`. Se cere sa se tipareasca separat, n ordine alfabetica, cele
trei evidente, si, pentru fiecare identificator, sa se specifice de cte ori apare n textul
citit. Apoi se citeste un al doilea text care se ncheie cu EOF. Se cere sa se tipareasca
o lista unica cuprinznd toti identificatorii din cele trei liste, si, pentru fiecare
identificator, sa se specifice de cte ori apare n ultimul text citit. Lista se va tipari n
ordinea numarului de aparitii.

11. Se citesc dintr-un fisier datele corespunzatoare rezultatelor obtinute de candidatii


la examenul de admitere. Datele se introduc ca o succesiune de linii de forma:

http://labs.cs.utt.ro/labs/pc/html/node86.html (5 of 13) [22.07.2003 16:18:30]

Setul 2

nume; sectie; medie


Succesiunea de linii se ncheie cu EOF. Sectia este: "calculatoare" sau "automatica",
iar media este un numar real. Daca dupa citirea liniei se constata ca sectia nu s-a dat
corect, se cere rectificarea pna cnd operatorul raspunde cu una din cele doua
variante acceptate. Daca dupa citirea liniei se constata ca numele este deja prezent n
evidenta, se actualizeaza vechea nregistrare conform noilor informatii. Dupa
ncheierea citirii se vor tipari:
a. Lista candidatilor admisi, n ordinea mediilor n forma:
nume sectia medie
Se stie ca numarul de locuri este 40 la calculatoare si 40 la automatica. Sunt admisi
primii 80 de candidati n ordinea mediilor, indiferent de sectia pentru care au optat.
Repartizarea pe sectii se face n limita locurilor, n functie de optiunea candidatului,
cu prioritate pentru cei cu medie mai mare.
b. Lista candidatilor respinsi n ordine alfabetica, sub forma:
nume medie

12. Se citeste o secventa de linii de forma:


obiect atribut1 atribut2 ...
prin care se asociaza unui obiect o secventa de atribute. Acelasi obiect poate aparea
pe mai multe linii. Acelasi atribut poate aparea de mai multe ori pe liniile ce
caracterizeaza acelasi obiect. Atributul multiplu este retinut o singura data. Secventa
de linii se ncheie cu caracterul `.`. Se va scrie un program care raspunde interactiv la
urmatoarele comenzi:
a - Citeste un atribut si afiseaza n ordine alfabetica toate obiectele care au acel
atribut.
s - Citeste un atribut si l elimina pentru toate obiectele din evidenta. Daca un obiect
nu mai are nici un atribut, el este eliminat din evidenta.

http://labs.cs.utt.ro/labs/pc/html/node86.html (6 of 13) [22.07.2003 16:18:30]

Setul 2

l - Citeste o linie care contine doar atribute. Se afiseaza toate obiectele care contin
atributele de pe linie. Listarea obiectelor se face astfel: nti obiectele care contin
doar atributele din secventa, apoi pe cele care au un atribut suplimentar, apoi cele
care au doua atribute suplimentare, etc.
b - Afiseaza n ordine alfabetica toate atributele si, pentru fiecare, numarul obiectelor
care contin acel atribut.
p - Citeste o linie ce contine doar atribute. Se elimina din evidenta obiectele ce
contin atributele specificate.
e - Termina programul.

13. Se citeste un fisier care contine linii de forma:


nume prenume materia1 nota1 materia2 nota2 ...
Secventa de linii se ncheie cu o linie vida. Fiecare linie contine numele, prenumele,
materiile si notele obtinute de studentii unui an de studiu. Daca un student nu s-a
prezentat la un examen, linia corespunzatoare va contine doar numele materiei fara a
aparea si nota. De exemplu:
Mihailescu Ion proiectare 5 compilatoare algoritmi 6.
n continuare, programul raspunde interactiv la urmatoarele comenzi:
afiseaza_top - Afiseaza lista ordonata functie de medie, a studentilor care au
promovat toate examenele. Studentii restantieri sunt afisati ntr-o lista separata,
ordonata functie de nume, pentru fiecare student indicndu-se numarul restantelor.
restante - Calculatorul afiseaza prompterul

$>$ asteptnd

introducerea unui nume

de materie. Dupa ce s-a citit numele materiei sunt afisati, ordonat alfabetic, toti
studentii care au acea materie restanta. n continuare, este afisat prompterul $>$ si se
asteapta introducerea unei noi materii. Comanda se ncheie atunci cnd se tasteaza o
linie vida.

http://labs.cs.utt.ro/labs/pc/html/node86.html (7 of 13) [22.07.2003 16:18:30]

Setul 2

modifica - Citeste numele si prenumele unui student. Apoi calculatorul afiseaza


prompterul $>$ si asteapta introducerea unei materii si a notei. Pentru materia
specificata se modifica nota studentului. Prompterul

$>$ este

afisat pna la

introducerea unei linii vide.


elimina - Citeste un numar. Din evidenta sunt eliminati toti studentii cu un numar
de restante mai mare sau egal cu numarul din comanda.
terminare - Termina programul.

14. Se citeste o secventa de linii de forma:


id = cuvant1, cuvant2, ...
prin care unui cuvnt i se asociaza o lista de sinonime. Exista posibilitatea ca un
identificator sa apara de mai multe ori n partea stnga a semnului $=$, caz n care
noua lista a sinonimelor se adauga la cea veche. Secventa de linii se ncheie cu
caracterul `.`. n continuare, programul raspunde repetat la urmatoarele comenzi:
c - Citeste un cuvnt si afiseaza ordonat alfabetic lista sinonimelor atasate lui.
v - Afiseaza ordonat functie de numarul de consoane toti identificatorii din evidenta
(cei care apar n stnga semnului $=$).
s - Citeste un cuvnt si elimina din evidenta acel cuvnt mpreuna cu lista atasata de
sinonime.
x - Se citeste un cuvnt si se cere afisarea tuturor cuvintelor cu care el este sinonim.
e - Termina programul.

15. Se citesc linii cu urmatoarele forme:

http://labs.cs.utt.ro/labs/pc/html/node86.html (8 of 13) [22.07.2003 16:18:30]

Setul 2

(1) numar: expresie n forma poloneza


(2) delete: numar
(3) afis: numar
(4) evalueaza: numar
(5) identificator: numar
Pentru o linie cu forma (1) se construieste o lista nlantuita, cu un nod pentru fiecare
element (operand sau operator) astfel: pentru un operator se construieste un nod nou,
iar pentru un operand se verifica daca a aparut ntr-o expresie anterioara. n caz
afirmativ, se considera nodul deja existent, iar n caz negativ se construieste un nod
nou.
Pentru o linie de forma (2), se sterge expresia cu numarul numar. Se sterg nodurile
corespunzatoare operatorilor, precum si referintele spre nodurile operanzilor. Daca
spre un operand nu mai indica nici o referinta atunci se sterge si nodul.
Linia (3) afiseaza expresia cu numarul numar.
Linia (4) evalueaza expresia cu numarul numar, iar linia (5) asociaza unui
identificator o valoare.

16. Sa se realizeze un program pentru traducerea unui text dintr-o limba n alta. n
plus, programul are facilitatea de a nlocui un cuvnt printr-un sinonim. Programul
citeste dintr-un fisier linii de forma:
cuvnt, echivalent strain, sinonim, sinonim, ...
Secventa de linii se ncheie cu caracterul `.`. n continuare, se citeste un text care se
ncheie tot cu caracterul `.`. Textul este parcurs cuvnt cu cuvnt si pentru fiecare
cuvnt se afiseaza lista sinonimelor sale. Utilizatorul poate selecta sinonimul dorit,
care este nlocuit automat n textul initial. Textul astfel obtinut este tradus automat.
Daca nu exista un echivalent strain pentru un cuvnt atunci se afiseaza un mesaj de
eroare la care utilizatorul raspunde cu:

http://labs.cs.utt.ro/labs/pc/html/node86.html (9 of 13) [22.07.2003 16:18:30]

Setul 2

A - cuvnt strain, daca cuvntul necunoscut este corect.


C - cuvnt corect, daca cuvntul necunoscut este incorect.
Textul tradus este afisat.

17. Dintr-un fisier se citesc linii avnd forma:


identificator identificator numar identificator numar ...
Secventa de linii se ncheie cu o linie vida. Fiecare linie introduce o unitate de
masura noua, precum si subunitatile ei si relatiile de conversie ntre acestea si
unitatea de baza. Numerele au forma:
secventa_de_cifre.secventa_de_cifre. Exemplu de linie:
m cm 0.01 mm 0.001.
Aceeasi unitate de masura poate fi definita prin mai multe linii, dar toate unitatile si
subunitatile se retin o singura data. Dupa citirea liniilor, programul raspunde
interactiv la urmatoarele comenzi:
(1) identificator

$<=$

numar unitate_de_masura

comanda asociaza unui identificator o valoare si o unitate de masura. n cazul n care


identificatorul are deja o valoare asociata si daca unitatile apartin aceleiasi unitati de
baza, dupa ce s-a dat un mesaj de atentionare, se retine pentru identificator ultima
valoare citita. n caz contrar, se da un mesaj de eroare si comanda se ncheie.
(2) identificator conversie unitate_de_masura
converteste valoarea asociata identificatorului n unitatea specificata.
(3) identificator tiparire pi pf
pi si pf sunt doua numere ntregi. Afiseaza valoarea asociata identificatorului cu pi
cifre la partea ntreaga si pf cifre pentru partea zecimala. De exemplu, daca a este
1305 cm, comanda:
a tiparire 1 2
va afisa: a = 1.30 E3 cm.

http://labs.cs.utt.ro/labs/pc/html/node86.html (10 of 13) [22.07.2003 16:18:30]

Setul 2

(4) stergere valoare unitate_de_masura


Sterge din evidenta toti identificatorii care au o valoare mai mica dect cea din linia
de comanda, iar unitatile apartin aceleiasi unitati de baza.
(5) afisare
Afiseaza identificatorii din evidenta n urmatoarea forma:
unitate_de_baza : unitati de masura apartinnd unitatii
de baza
Identificatorii sunt afisati ordonat alfabetic.

18. Sa se scrie un program care rezolva urmatoarea problema. Se citesc dintr-un


fisier linii de forma:
identificator = numar
unde numar are o parte ntreaga, care este eventual urmata de o parte zecimala.
Partea ntreaga si cea zecimala sunt secvente de cifre care sunt separate prin punct.
Secventa de linii se ncheie cu caracterul `.`. Fiecare identificator este retinut ntr-o
evidenta mpreuna cu valoarea asociata lui. Daca identificatorul apare deja n
evidenta, de fiecare data se retine si noua lui valoare. n continuare, programul
raspunde interactiv la urmatoarele comenzi:
s numar - unde numar are forma prezentata anterior. Se elimina din evidenta toti
identificatorii care au asociata valoarea din comanda.
talf - afiseaza n ordine alfabetica toti identificatorii si pentru fiecare identificator
valorile asociate lui.
c identificator - cauta identificatorul si, daca l gaseste, afiseaza toate
valorile atasate lui.
tval - afiseaza, n ordinea valorii, identificatorii care au valoarea respectiva.
e - termina programul.

19. Se citeste o secventa de reguli (o regula pe linie) cu forma:


identificator = identificator; identificator; ...
Secventa de linii se ncheie cu carcaterul `.`. Prin aceste reguli se asociaza fiecarui
http://labs.cs.utt.ro/labs/pc/html/node86.html (11 of 13) [22.07.2003 16:18:30]

Setul 2

identificator din stnga semnului = o secventa de identificatori. Un identificator


poate fi definit prin mai multe reguli. Regulile sunt memorate ntr-o evidenta. n
continuare programul raspunde interactiv la urmatoarele comenzi:
a - Afiseaza ordonat, functie de identificatorul care apare n stnga lui =, toti
identificatorii si secventele asociate lor.
c - Citeste un cuvnt. Pentru acest cuvnt se afiseaza toti identificatorii atasati. n
cazul n care nu exista identificatori atasati, programul afiseaza un mesaj de eroare
corespunzator.
s - Citeste un cuvnt, dupa care se sterg din evidenta toate regulile pentru care
cuvntul citit apare n partea stnga a semnului =.
f - Citeste un cuvnt. Pentru cuvntul citit, pe baza regulilor atasate, se formeaza un
grup astfel: doua reguli apartin grupului daca partea din dreapta semnului = ncepe
cu cel putin un identificator comun. Acest grup este afisat mpreuna cu partea
comuna.
e - Termina programul.

20. Sa se scrie un program care implementeaza diferite operatiuni bancare.


Programul citeste de la tastatura numele clientului (un singur cuvnt, doar litere
mici) si o parola (parola trebuie "ascunsa" la citire). Parola este criptata (algoritmul
de criptare aplica un XOR ntre fiecare caracter al parolei si o cheie de criptare, cheia
reprezentnd un numar ntreg pe 8 biti (tipul char) care reprezinta media codurilor
ASCII ale literelor numelui) si este confruntata cu parola criptata aflata n fisierul
"passwd.txt" sub forma:
nume_client_1 parola_criptata_1
nume_client_2 parola_criptata_2
......
Daca parola e corecta, se afiseaza un prompt (: sau
comenzile:

http://labs.cs.utt.ro/labs/pc/html/node86.html (12 of 13) [22.07.2003 16:18:30]

$>$)

si se asteapta una din

Setul 2

restituire suma - se restituie suma specificata (daca soldul acopera suma


ceruta);
depunere suma - depunere suma n cont;
sold - afisare sold.
Informatiile bancare sunt memorate ntr-un fisier de conturi; la ncheierea fiecarei
operatii, se actualizeaza fisierul de conturi.
next

up

previous

contents

Next: Bibliografie Up: Probleme propuse spre rezolvare Previous: Setul 1 Cuprins Cristian Gavrila
2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node86.html (13 of 13) [22.07.2003 16:18:30]

Bibliografie

next

up

previous

contents

Next: About this document ... Up: carte Previous: Setul 2 Cuprins

Bibliografie
6
Brian W. Kernighan, Denis M. Ritchie, Le Langage C, Dunod, Paris, 2000
6
Niklaus Wirth, Algorithms & Data Structures, Prentice-Hall, Englewood Cliffs, 1986
6
Herbert Schildt, Teach Yourself C, McGraw-Hill, Berkeley, 1995
6
Alina Ilin, Alexa Doboli, Tehnici de Programare - ndrumator de laborator, Universitatea
"Politehnica", Timisoara, 1996
6
Samuel P. Harbison, Guy L. Steele, C - A Reference Manual, Prentice Hall, Englewood Cliffs,
1991
6
Steve Oualine, Practical C Programming (Nutshell Handbook), O''Reilly, Cambridge, 1997

Cristian Gavrila 2001-10-02

http://labs.cs.utt.ro/labs/pc/html/node87.html [22.07.2003 16:18:31]

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