Documente Academic
Documente Profesional
Documente Cultură
next
up
previous
Cuprins
Comparatie C - Pascal
Probleme propuse
Functii de biblioteca
Functii de intrare-iesire
Functii matematice
Functii de conversie
Exemple rezolvate
Probleme propuse
Utilizarea operatorilor
Probleme rezolvate
Probleme propuse
Operatii cu caractere
Tablouri unidimensionale
Siruri de caractere
Cuprins
Probleme rezolvate
Probleme propuse
Prelucrarea fisierelor
Tratarea fisierelor n C
Probleme rezolvate
Probleme propuse
Preprocesarea
Compilarea
Link-editare
Probleme propuse
Pointeri
Introducere
Operatii cu pointeri
Pointeri si tablouri
Cuprins
Pointeri la functii
Problema rezolvata
Problema propusa
Problema rezolvata
Comentarea programului
Problema propusa
Problema rezolvata
Sursa programului
Comentarea programului
Problema propusa
Codul sursa
Arbori binari
Problema rezolvata
Sursa programului
Comentarea programului
Problema propusa
Setul 1
Setul 2
Cuprins
Bibliografie
next
up
previous
contents
Comparatie C - Pascal
Probleme propuse
next
up
previous
contents
Next: Comparatie C - Pascal Up: Introducere. Operatori. Expresii. Previous: Introducere. Operatori.
Expresii. Cuprins
#include <stdio.h>
void main(void)
{
printf("Hello, World !\n");
}
up
previous
contents
Next: Comparatie C - Pascal Up: Introducere. Operatori. Expresii. Previous: Introducere. Operatori.
Expresii. Cuprins Cristian Gavrila 2001-10-02
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
tip nume_var ;
integer
int
real
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
set of
nu exista
while conditie do
while (conditie)
sintaxa unor
if conditie then
if (conditie)
instructiuni
case
switch
:=
Comparatie C - Pascal
=
operatori
$<>$
AND OR NOT
modulo
next
up
==
!=
&& $\vert\vert$
!
%
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
next
up
previous
contents
Next: Operatii aritmetice, expresii si Up: Introducere. Operatori. Expresii. Previous: Comparatie C Pascal Cuprins
#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.
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
next
up
previous
contents
Next: Probleme propuse Up: Variabile. Operatori. Expresii Previous: Variabile. Operatori. Expresii
Cuprins
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);
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*/
$--$
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;
up
previous
contents
Next: Probleme propuse Up: Variabile. Operatori. Expresii Previous: Variabile. Operatori. Expresii
Cuprins Cristian Gavrila 2001-10-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.
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;
}
next
up
previous
contents
Next: Functii definite de utilizator Up: carte Previous: Probleme propuse Cuprins
Functii de biblioteca
Functii de intrare-iesire
declarate n stdio.h
declarate n conio.h
Functii matematice
Functii de conversie
Exemple rezolvate
Probleme propuse
next
up
previous
contents
Next: Functii de biblioteca Up: Functii. Functii de biblioteca Previous: Functii. Functii de biblioteca
Cuprins
#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);
}
b)
diferit de 0,
0 (a este
*/
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]
#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);
}
up
previous
contents
Next: Functii de biblioteca Up: Functii. Functii de biblioteca Previous: Functii. Functii de biblioteca
Cuprins Cristian Gavrila 2001-10-02
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
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
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
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
declarate n stdio.h
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
declarate n stdio.h
Caracter
Valoare
d,i
ntreg zecimal
x, X
caracter
sir de caractere
lf
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:
declarate n stdio.h
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
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
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
arccosinus de x
arcsinus de x
arctangenta de x
arctangenta de y/x
cosinus de x
next
up
exponentiala $e^x$
ln de x
lg de x
x la puterea y
sinus de x
radicalul lui 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
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
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
Exemple rezolvate
up
previous
contents
Next: Probleme propuse Up: Functii de biblioteca Previous: Functii de conversie Cuprins Cristian
Gavrila 2001-10-02
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.
next
up
previous
contents
Utilizarea operatorilor
Probleme rezolvate
Probleme propuse
next
up
previous
contents
Next: Utilizarea operatorilor Up: Operatii la nivel de Previous: Operatii la nivel de Cuprins
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
Utilizarea operatorilor
). De exemplu,
$\vert\vert$
fi 1.
Operatorii de deplasare
$<<$
si
$>>$
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
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}
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));
}
secventa
$x >> (p+1-n)$
<< n)$
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}
Probleme propuse
up
previous
contents
Next: Caractere, siruri de caractere. Up: Operatii la nivel de Previous: Probleme rezolvate Cuprins Cristian
Gavrila 2001-10-02
next
up
previous
contents
Tablouri unidimensionale
Siruri de caractere
Probleme rezolvate
Probleme propuse
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:
Operatii cu caractere
r, $\backslash$
t, $\backsl
n,
$\backslash$
f, $\backslash$
v);
$\backslash$
Operatii cu caractere
up
previous
contents
Next: Tablouri unidimensionale Up: Caractere, siruri de caractere. Previous: Caractere, siruri de
caractere. Cuprins Cristian Gavrila 2001-10-02
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
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.
Siruri de caractere
$>0$
daca s1
$<0$ ,
daca sirul s1
$<$ sirul
s2, 0
$>$ s2.
Siruri de caractere
up
previous
contents
Next: Observatii asupra sirurilor de Up: Caractere, siruri de caractere. Previous: Tablouri
unidimensionale Cuprins Cristian Gavrila 2001-10-02
next
up
previous
contents
Next: Probleme rezolvate Up: Siruri de caractere Previous: Siruri de caractere Cuprins
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
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.
Probleme rezolvate
}
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
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}
up
previous
contents
Next: Prelucrarea fisierelor Up: Caractere, siruri de caractere. Previous: Probleme rezolvate Cuprins
Cristian Gavrila 2001-10-02
Prelucrarea fisierelor
next
up
previous
contents
Prelucrarea fisierelor
Subsections
Tratarea fisierelor n C
Deschiderea/nchiderea fisierelor
Probleme rezolvate
Probleme propuse
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
next
up
previous
contents
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;
Deschiderea/nchiderea fisierelor
a+
deschide pentru actualizare la sfrsitul fisierului.
up
previous
contents
Next: Alte functii referitoare la Up: Operatii asupra fisierelor Previous: Operatii asupra fisierelor
Cuprins Cristian Gavrila 2001-10-02
next
up
previous
contents
next
up
previous
contents
Next: Transferul caracterelor si al Up: Operatii asupra fisierelor Previous: Alte functii referitoare la
Cuprins
next
up
previous
contents
Next: Citirea si scrierea cu Up: Operatii asupra fisierelor Previous: Citirea si modificarea indicatorului
Cuprins
next
up
previous
contents
Next: Probleme rezolvate Up: Operatii asupra fisierelor Previous: Transferul caracterelor si al Cuprins
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++;
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
/*----------------------------------------------*/
/*
*/
/*
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
/*-----------------------------------------------*/
/*
*/
/*
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
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
next
up
previous
contents
Next: Etapele compilarii unui program Up: carte Previous: Probleme propuse Cuprins
Preprocesarea
Compilarea
Link-editare
Probleme propuse
next
up
previous
contents
Compilarea
Link-editare
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
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
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
next
up
previous
contents
Next: De ce mai multe Up: Compilarea independenta a fisierelor Previous: Link-editare Cuprins
next
up
previous
contents
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
up
previous
contents
Next: Lucrul n modul "project" Up: Structurarea programelor C pe Previous: De ce mai multe
Cuprins
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]
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;
}
up
previous
contents
Next: Lucrul n modul "project" Up: Structurarea programelor C pe Previous: De ce mai multe
next
up
previous
contents
Next: Tipuri de date abstracte Up: Structurarea programelor C pe Previous: Reguli de structurare pe
Cuprins
next
up
previous
contents
Next: Definirea tipului abstract stiva Up: Compilarea independenta a fisierelor Previous: Lucrul n
modul "project" Cuprins
next
previous
contents
Next: Definirea tipului abstract stiva Up: Compilarea independenta a fisierelor Previous: Lucrul n
modul "project" Cuprins Cristian Gavrila 2001-10-02
next
up
previous
contents
Next: Evaluarea unei expresii n Up: Tipuri de date abstracte Previous: Tipuri de date abstracte
Cuprins
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.
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 */
Stiva este plina atunci cnd vrful stivei indica spre ultimul element din stiva (cel
de indice MAX-1).
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.
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.
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.
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
next
up
previous
contents
Next: Probleme propuse Up: Tipuri de date abstracte Previous: Definirea tipului abstract stiva
Cuprins
up
previous
contents
Next: Probleme propuse Up: Tipuri de date abstracte Previous: Definirea tipului abstract stiva
Cuprins Cristian Gavrila 2001-10-02
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
contents
Next: Pointeri Up: Compilarea independenta a fisierelor Previous: Evaluarea unei expresii n Cuprins
Cristian Gavrila 2001-10-02
Pointeri
next
up
previous
contents
Pointeri
Subsections
Introducere
Operatii cu pointeri
Pointeri si tablouri
Pointeri la functii
Problema rezolvata
Problema propusa
Introducere
next
up
previous
contents
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
Fac_ETC
Fac_Mate
Bd. V. Prvan 4
Cladire "U"
contents
Next: Operatii cu pointeri Up: Pointeri Previous: Pointeri Cuprins Cristian Gavrila 2001-10-02
Operatii cu pointeri
next
up
previous
contents
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 */
Operatii cu pointeri
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;
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
next
up
previous
contents
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
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]++.
Pointeri si tablouri
up
previous
contents
Next: Pointeri la functii Up: Pointeri Previous: Pointeri ca argumente ale Cuprins Cristian Gavrila
2001-10-02
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
next
up
previous
contents
obiect_ptr = obiect;
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
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:
#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
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
/*--------------------------------------------------------*/
/*
*/
/* 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
*/
/*
*/
/*--------------------------------------------------------*/
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
up
previous
contents
Next: Problema propusa Up: Pointeri Previous: Folosirea neadecvata a operatiilor Cuprins Cristian
Gavrila 2001-10-02
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:
next
up
previous
contents
Next: Aspecte ale implementarii listelor Up: carte Previous: Problema propusa Cuprins
Problema rezolvata
Codul sursa
Comentarea programului
Problema propusa
next
up
previous
contents
Next: Problema rezolvata Up: Liste liniare simplu nlantuite Previous: Liste liniare simplu nlantuite
Cuprins
\begin{figure}\begin{center}
\epsfig{file=adaugare_inc.eps, height=5cm}
\end{center}\end{figure}
\begin{figure}\begin{center}
\epsfig{file=adaugare_sf.eps, height=5cm} \end{center}\end{figure}
\begin{figure}\begin{center}
\epsfig{file=adaugare_mijl.eps, height=5cm} \end{center}\end{figure}
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}
\begin{figure}\begin{center}
\epsfig{file=stergere_sf.eps, height=4cm} \end{center}\end{figure}
\begin{figure}\begin{center}
\epsfig{file=stergere_mijl.eps, height=3.5cm} \end{center}\end{figure}
up
previous
contents
Next: Problema rezolvata Up: Liste liniare simplu nlantuite Previous: Liste liniare simplu nlantuite
Cuprins Cristian Gavrila 2001-10-02
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:
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.
Problema rezolvata
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
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;
/*---------------------------------------------------------*/
/*
*/
/* 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 */
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);
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
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
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
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.
Comentarea programului
Comentarea programului
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.
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
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:
up
previous
contents
Next: Liste liniare multiplu nlantuite Up: Liste liniare simplu nlantuite Previous: Comentarea
programului Cuprins Cristian Gavrila 2001-10-02
next
up
previous
contents
Next: Implementarea listelor multiplu nlantuite Up: carte Previous: Problema propusa Cuprins
Problema rezolvata
Sursa programului
Comentarea programului
Problema propusa
next
up
previous
contents
Next: Problema rezolvata Up: Liste liniare multiplu nlantuite Previous: Liste liniare multiplu nlantuite
Cuprins
\begin{figure}\begin{center}
\epsfig{file=lista.eps, width=\textwidth} \end{center}\end{figure}
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
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;
Fisierul lista.c
#include
#include
#include
#include
<stdio.h>
<string.h>
<stdlib.h>
"tip.h"
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
Sursa programului
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
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
Sursa programului
Sursa programului
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-
Sursa programului
Sursa programului
/*---------------------------------------------------------*/
/*
*/
/*
Functia main apeleaza functia meniu
*/
/*
*/
/*---------------------------------------------------------*/
void main()
{
meniu();
} /* main */
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:
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.
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.
Comentarea programului
up
previous
contents
Next: Problema propusa Up: Problema rezolvata Previous: Sursa programului Cuprins Cristian
Gavrila 2001-10-02
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
next
up
previous
contents
Problema rezolvata
Sursa programului
Comentarea programului
Problema propusa
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}$
Arbori binari
next
previous
contents
Next: Cautarea n arbori binari Up: Tipul abstract arbore binar Previous: Tipul abstract arbore binar
Cuprins Cristian Gavrila 2001-10-02
next
up
previous
contents
Next: Inserarea n arbori binari Up: Arbori binari Previous: Arbori binari Cuprins
next
up
previous
contents
Next: Stergerea n arbori binari Up: Arbori binari Previous: Cautarea n arbori binari Cuprins
next
up
previous
contents
Next: Parcurgerea arborilor binari Up: Arbori binari Previous: Inserarea n arbori binari Cuprins
next
up
previous
contents
Next: Problema rezolvata Up: Arbori binari Previous: Stergerea n arbori binari Cuprins
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
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:
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
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"
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
/*---------------------------------------------------------*/
/*
*/
/* 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 */
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();
}
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
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
next
up
previous
contents
Setul 2
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.
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.
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.
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.
Setul 1
\begin{figure}\begin{center}
\epsfig{file=stiva.eps, height=6cm}\end{center}\end{figure}
Figura 11.1:
Setul 1
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.
Setul 1
$+, -, *, /$
numar.
Setul 1
Pentru
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.
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
Setul 1
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.
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
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
$<$numar
$<$numar
zbor $>$
$<$numar
Pasagerul
cursa
zbor $>$
$<$nume
$<$numar
$<$nume
pasager $>$
RENUNT
$<$numar
Pasagerul
$<$nume
zbor $>$
$<$nume
pasager $>$
$<$numar
$>$.
$<$numar
zbor $>$
$<$numar
zbor $>$.
zbor
Setul 2
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.
Setul 2
Setul 2
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.
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.
Setul 2
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.
$>$ asteptnd
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.
Setul 2
$>$ este
afisat pna la
Setul 2
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:
Setul 2
$<=$
numar unitate_de_masura
Setul 2
Setul 2
$>$)
Setul 2
up
previous
contents
Next: Bibliografie Up: Probleme propuse spre rezolvare Previous: Setul 1 Cuprins Cristian Gavrila
2001-10-02
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