Professional Documents
Culture Documents
doc
CUPRINS
CUPRINS_________________________________________________________________________i
Cap 1 INTRODUCERE N LIMBAJUL C______________________________________________4
1.1 Scurt istoric__________________________________________________________________4
1.2 Forma unui program C________________________________________________________8
1.3 Compilarea unui program C____________________________________________________9
Cap 2 Tipuri, operatori, expresii______________________________________________________11
2.1. Tipuri simple_______________________________________________________________11
2.2. Literali____________________________________________________________________12
2.3. Declararea unei variabile i a unei constante_____________________________________13
2.4. Operatori__________________________________________________________________14
2.4.1. Operatori aritmetici_______________________________________________________15
2.4.2. Operatorii relaionali (de comparaie)__________________________________________15
2.4.3. Operatori logici___________________________________________________________16
2.4.4. Operatori la nivel de bit____________________________________________________16
2.4.5. Operatorul de asignare_____________________________________________________17
2.4.6. Operatorul condiional_____________________________________________________17
2.4.7. Operatorul virgul________________________________________________________18
2.4.8. Precedena operatorilor____________________________________________________18
Cap 3 FUNCTII__________________________________________________________________20
3.1. Definirea unei funcii________________________________________________________20
3.2. Returnarea unui apel________________________________________________________21
3.3. Funcii cu un numr variabil de parametri______________________________________21
3.4. Sfritul execuiei unui program_______________________________________________21
3.5. Apelul i transmiterea parametrilor_____________________________________________22
3.6. Funcia principal main______________________________________________________23
Cap 4 FUNCII DE INTRARE IEIRE_______________________________________________25
4.1.Fluxuri i fiiere_____________________________________________________________25
Semnificaia____________________________________________________________________27
4.2. Funcii de intrare/ieire pentru caractere________________________________________28
4.3. Scrierea cu format___________________________________________________________29
4.5. Citirea cu format____________________________________________________________33
Cap 5 INSTRUCIUNI DE CONTROL_______________________________________________36
5.1. Instruciunea if_____________________________________________________________37
5.3. Instruciunea while_________________________________________________________39
5.4. Instruc]iunea do ... while__________________________________________________40
5.5. Instruciunea for___________________________________________________________40
i
Gheorghe GRIGORA
ii
369709427.doc
iii
Cap 1 INTRODUCERE N LIMBAJUL C
Strmoii limbajului C sunt limbajele de programare CPL, BCPL, B i Algol 68. CPL a fost dezvoltat
la Universitile Cambridge i London n anii 1960-1963. BCPL a fost proiectat de Martin Richards n
1967 i face parte din categoria low-level languages, sau systems programming languages. n anii 60,
la Bell Laboratories n USA, Ken Thomson a nceput proiectarea sistemului de operare Unix. Primul limbaj
de nivel nalt implementat sub acest sistem de operare a fost limbajul B, un limbaj bazat pe BCPL care a
fost proiectat de asemenea de ctre Ken Thompson n 1970. Asemnarea cu BCPL a fost mai degrab
semantic; sintaxa este total diferit. Proiectarea limbajului B a fost influienat de limitele mainii pe care a
fost implementat: un PDP-7 cu capacitatea 4K ( cuvinte de 18 bii).
Limbajele BCPL i B sunt limbaje de nivel sczut fa de limbajul Pascal i nici unul din ele nu este
tipizat: toate datele sunt considerate cuvinte main nct, exemple simple de programe duc la complicaii
nebnuite. n una din implementrile BCPL-ului, operanzii flotani din expresii trebuiau precedai de punct;
restul operanzilor erau considerai ntregi.
Problemele create n jurul limbajelor BCPL i B au dus la dezvoltarea unui nou limbaj, bazat pe B,
care la nceput s-a numit NB dar numele su a fost stabilit C. Numele C, considerat la nceput a proveni
de la Cambridge, este oficial din Combined dar neoficial se consider a fi iniiala pronumelui lui
Cristopher Strachey, cel care a condus echipa ce a proiectat CPL-ul. Limbajul a fost proiectat i
implementat de ctre Dennis Ritchie la Bell Laboratories n 1972. n mare parte ( construciile for i
switch, tratarea pointerilor etc.) limbajul a fost influienat i de Algol 68. Genealogia limbajului C este
prezentat n Figura 1.1.
369709427.doc
Ritchie a lucrat pe un calculator DEC PDP-11 sub sistemul de operare Unix. Din acest motiv varianta
clasic a limbajului C a fost asociat sistemului de operare Unix - versiunea 5 i mult vreme a constituit
un standard (neoficial de altfel) al limbajului KeR 78.
Odat cu cretere popularitii calculatoarelor personale, au aprut numeroase alte implementri ale
limbajului C i astfel a crescut i popularitatea acestuia. Un fapt cu totul inedit a fost acela c, mare parte
din implementrile C -ului s-au dovedit de un mare grad de compatibilitate: un program scris pentru una
din variante putea fi compilat cu succes folosind o alt variant. Se nelege c au existat i neconcordane
n multitudinea de dialecte ale limbajului. Pentru eliminarea acestora n 1983 a fost creat o comisie care
s stabileasc un standard al acestui limbaj. Standardul ANSI ( American National Standard Institute) a fost
redactat abia n decembrie 1989 i a fost pus la dispoziia celor interesai la nceputul lui 1990. Firma
Borland a folosit acest standard n faza de proiect i a realizat implementrile Turbo C care se bucur de un
succes remarcabil. De altfel, n prezent , toate compilatoarele C sunt compatibile cu standardul ANSI C;
unele din acestea au adugate o serie de faciliti sau extensii proprii care nu mpiedic compilarea unui
program standard.
FORTRAN I (1957)
FORTRAN II (1958)
ALGOL 60 (1960)
CPL (1963)
ALGOL 68 (1968)
BCPL (1967)
B (1970)
C (1972)
C++ (1984)
Figura 1.1.
Limbajul C este privit ca un limbaj de nivel mediu ntruct combin cele mai reuite elemente ale
limbajelor de nivel nalt ( Pas-cal, Fortran, Algol, Modula, Ada) cu gradul de control i flexibilitatea oferite
de ctre limbajul de asamblare. C permite manevrarea biilor, a octeilor i a adreselor de memorie, adic a
elementelor de baz n funcionarea unui calculator. n ciuda acestui fapt , programele scrise n C au un
grad mare de portabilitate: uurina de a adapta programele scrise pentru o anumit categorie de
calculatoare sau sisteme de operare la alte calculatoare sau sisteme de operare.
Limbajul C are structuri de control adecvate precum i faciliti de structurare a datelor care l fac s
fie folosit ntr-o diversitate de domenii. Are de asemenea o mulime bogat de operatori care-i dau un nalt
grad de expresivitate. Unul din motivele pentru care limbajul C este n acelai timp agreat de mare parte
din programatori i dezagreat de alt mare parte din programatori, este lipsa total a verificrii tipului
(type checking). De exemplu, o variabil de un tip scalar oarecare poate apare n aceeai expresie cu o
5
Gheorghe GRIGORA
variabil de un alt tip scalar. Cei care agreaz limbajul C i apreciaz flexibilitatea sa, cei care nu-l agreaz l
consider un limbaj lipsit de siguran.
Ceea ce este sigur, este c datorit faptului c face parte din sistemul de operare Unix, limbajul a
cptat o mare popularitate n lumea academic i nu numai. Compilatoarele oferite mpreun cu sistemul
Unix sunt relativ ieftine (uneori chiar gratuite) i pot fi folosite pe o diversitate de maini.
O nou versiune a limbajului C, numit C++, a aprut n 1984. Originea acestui limbaj STR 94
trebuie cutat n proiectul care a nceput n Aprilie 1979 la Computing Research Center of Bell
Laboratories n Murray Hill, New Jersey, USA, proiect ce trebuia s realizeze distribuirea nucleului UNIX
ntr-o reea de computere conectate LAN. Pentru realizarea acestui proiect, Bjarne Stroustrup a realizat n
Octombrie 1979 un preprocesor, numit Cpre, care a adugat la limbajul C conceptul de clas folosit pentru
prima dat de limbajul Simula ( dezvoltat n anii 1962-1967 de norvegienii Kristen Nyagaard i Ole-Johan
Dahl). n martie 1980 preprocesorul mbuntit era implementat pe 16 sisteme iar limbajul acceptat de
acesta a fost numit C cu Clase. Motivele pentru care a fost ales limbajul C (n faa altor limbaje ale
vremii: Modula-2, Ada, Smalltalk, Mesa, Clu) pentru acest proiect sunt expuse chiar de creatorul noului
limbaj:
C este un limbaj flexibil: se poate folosi n orice domeniu i permite utilizarea oricror tehnici de
programare;
C este un limbaj eficient: semantica sa este low level ceea ce nseamn c pot fi folosite cu
eficien resursele hardware pentru programele C. Aa cum vom vedea pe parcursul prezentrii
limbajului, acesta oglindete conceptele fundamentale ale unui computer tradiional;
C este un limbaj disponibil: un limbaj pentru care se poate gsi cu uurin un compilator,
indiferent de ce calculator dispunem;
C este un limbaj portabil: chiar dac un program C nu este automat portabil de la o main la alta,
acest lucru este posibil n general fr un efort deosebit.
Cele mai mari influiene asupra noului limbaj le-au avut: Simula care a dat clasele, Algol 68 care a dat
suprancrcarea operatorilor, referinele i abilitatea de a declara variabile oriunde n cadrul unui bloc i
BCPL de unde a fost luat forma de prezentare a comentariilor cu //. Dup numele C cu clase limbajul a
fost botezat C84. Asta pentru scurt timp ns deoarece comitetul ANSI pentru standardizarea C-ului a
atras atenia c se poate crea o confuzie cu aceast denumire; era vorba totui de un nou limbaj, chiar dac
era cldit pe C. Numele C++ a fost sugerat de Rick Mascitti, un membru al echipei lui Stroustrup, i a fost
folosit pentru prima dat n Decembrie 1983.Iat ce spune Stroustrup despre aceast alegere: <<I picked
C++ because it wos short, had a nice interpretation, and wasnt of the form adjective C. In C++, ++
can, depending on context, be read as next, succesor or increment , tough it is always
pronounced plus plus.>>
n figura 1.2. este prezentat genealogia limbajului C++ iar figura 1.3. prezint etapele importante din
proiectarea limbajului.
Datele care apar n parantez se refer la prima implementare disponibil pentru limbajul
respectiv(dup [STR 94]). C++arm reprezint The Annotated C++ Reference Manual iar C++std este
standardul ANSI C++.
Fortran(1956)
Algol 60(1960)
CPL(1963)
6
369709427.doc
BCPL(1967)
Simula 67(1969)
Algol 68(1977)
C cu Clase (1980)
Ada (1983)
C++ (1984)
ANSI C ML(1976)
(1986)
Clu(1978)
C++arm(1990)
C++std (1995)
Figura 1.2.
7
Gheorghe GRIGORA
Figura 1.3.
Programul 1
/* Calculul celui mai mare divizor comun (cmmdc) a doua numere intregi
pozitive a si b. Metoda care se aplica pentru a determina cmmdc este
urmatoarea:
- se calculeaza restul impartirii intregi a lui a prin b;
- daca acest rest este nul, b este valoarea cautata. In caz
contrar, a capata valoarea lui b, b capata valoarea restului si
procedeul se repeta.
*/
include <stdio.h>
int cmmdc (int x, int y)
int rest;
do
rest = x%y;
x = y;
y = rest;
while (rest!=0);
return x;
int main ()
int a,b;
char raspuns;
do
printf (" Introduceti 2 valori intregi pozitive -->");
scanf ("%d%d", &a, &b);
if (b>a)
int c = a;a = b;b = c;
printf (" Cmmdc al celor doua numere este:
%d\n",cmmdc (a,b));
printf (" Continuati ? d)a n)u -->");
scanf ("%c", &raspuns);
while (raspuns!=n);
return 0;
8
369709427.doc
9
Gheorghe GRIGORA
Un program C compilat creeaz i folosete patru zone de memorie disjuncte, care ndeplinesc funcii
distincte (figura 1.4.).
Prima regiune este aceea care stocheaz codul programului.Urmeaz o zon de memorie n care sunt
stocate variabilele globale. Celelalte dou zone reprezint aa zisa stiv a programului i zona de manevr.
Stiva este folosit n timpul execuiei programului n scopurile:
memoreaz adresele de revenire ale apelurilor la funcii;
memoreaz argumentele funciilor;
memoreaz variabilele locale;
memoreaz starea curent a unitii centrale de prelucrare.
STIVA
ZONA DE MANEVR
VARIABILE GLOBALE
CODUL PROGRAMULUI
Figura 1.4.
Zona de manevr (heap) este o regiune de memorie liber pe care programul , prin intermediul
funciilor de alocare dinamic ale limbajului C, le folosete pentru stocarea unor articole de genul listelor
nlnuite i arborilor.
S mai precizm , n ncheierea acestei scurte introduceri , c n general, compilatoarele existente pe
pia, sunt compilatoare C++. Aa cum vom vedea n partea a doua a acestei cri, C++ este o versiune
extins a limbajului C, care a fost conceput pentru programarea orientat pe obiecte. De aceea C++
accept limbajul C: orice program C va putea fi compilat de un compilator C++.Dup unii autori,
programarea n limbajul C va dinui mult vreme de acum ncolo, aa cum dinuie de cnd a fost creat
limbajul i, un programator care nu tie C nu va putea programa n C++.
10
369709427.doc
Tipurile simple (sau tipurile de baz) ale limbajului C definesc dimensiunea zonei de memorie
ocupat de valoarea unei variabile precum i modul n care va fi interpretat coninutul acestei zone.
Limbajul C ofer de asemenea un mecanism de conversie a tipului care va fi prezentat mai trziu n lucrare.
Tipurile de baz ale limbajului C pot fi grupate n trei mulimi:
Tipuri ntregi: char, short, int i long. Aceste tipuri sunt utilizate pentru reprezentarea numerelor
ntregi. Diferenta dintre acestea const n dimensiunea zonei de memorie ocupat de o variabil de
acest tip i implicit de mrimea domeniului de valori. Acest lucru este sintetizat n Tabela 1.
Tipul vid: void. Este un tip folosit pentru reprezentri de dimensiune nul. Pentru tipurile ntregi se pot
folosi specificrile signed i unsigned. Specificarea signed tip este echivalent cu tip iar unsigned tip are
semnificaia din Tabela 2.
11
Gheorghe GRIGORA
2.2. Literali
Literalii (sau constantele literale) sunt valori constante; ele reprezint valori care nu pot fi
modificate pe parcursul execuiei unui program. n limbajul C se folosesc diferite reguli sintactice pentru
reprezentarea constantelor. Tabela 3 sintetizeaz unele din aceste reguli.
Exist i caractere speciale (de control) care sunt compuse din caracterul \ i din alt caracter.
Acestea sunt:
\n - interlinie (linie nou); \t - tabulare;
\\ - caracterul \ (backslash); \f - retur de linie;
\o - caracterul NULL; \ - caracterul
\ - caracterul ; \r - retur de car;
\u - tabulare vertical; \b - backspace;
\ddd - caracter de cod octal ddd;
\xhh - caracter de cod hexazecimal hh.
Toate variabilele unui program trebuiesc declarate nainte de a fi utilizate. Variabilele sunt obiectele
de baz ale limbajului i au un nume care este un identificator.
Un identificator n limbajul C este un ir de caractere care trebuie s ndeplineasc condiiile:
- primul caracter este liter sau _ (underscore);
- urmtoarele caractere sunt caractere alfanumerice (litere sau cifre) sau _.
- Nu trebuie s coincid cu vreun cuvnt cheie (vezi Tabela 4)
12
369709427.doc
tip nume;
tip nume = valoare;
Exemple:
int i, j, k;
float eps = 1.e-4, pi = 3.14159;
char n1='\n';
const double e = 2.71828182845905;
const float pi = 3.14159;
const char mesaj = "Eroare";
Variabilele se declar la nceputul funciilor (variabile locale) sau n exteriorul tuturor funciilor
(variabile globale). n afar de tipul variabilei i eventual o valoare iniial pentru aceasta, ntr-o declaraie
se specific clasa de alocare (implicit sau explicit). Clasele principale de alocare sunt automatic i static.
Variabilele din clasa automatic sunt definite n interiorul funciilor fiind locale funciei n care au fost
definite, avnd durata de via pe parcursul execuiei funciei. Aceast clas este implicit; explicit se poate
specifica prin cuvntul cheie aut:
aut int x;
Tot n interiorul unei funcii variabilele mai pot fi definite i n clasa register care este asemntoare
cu cea automatic cu deosebirea c, dac e posibil, alocarea se face n registrele unitii centrale i nu n
memoria RAM. Variabilele din clasele auto i register nu i pstreaz valoarea de la un apel la altul al
funciei n care sunt definite.
Variabilele din clasa static difer de cele din clasa auto sau register prin aceea c sunt memorate n
locaii fixe de memorie (au o adres fix, permanent). Dac se definesc n interiorul unei funcii trebuie s
aib neaprat n fa cuvntul rezervat static (se mai spune c sunt n clasa static internal).
Variabilele definite n exteriorul tuturor funciilor fr vreun specificator de clas sunt n clasa
extern i au alocate adrese fixe. Tabelul 5 sintetizeaz clasele de alocare.
13
Gheorghe GRIGORA
2.4. Operatori
Operatorii se folosesc la constituirea de expresii pornind de la constante i variabile. Evaluarea
expresiilor se face nlocuind operanzii prin valorile sale i efectund operaiile conform cu specificaiile
acestora. Am vzut c operanzii pot fi variabile, constante sau apeluri la funcii (despre care se va vorbi
mai trziu). Fiecare dintre acetia au un tip declarat. Dac tipul operanzilor este acelai ntr-o expresie,
evaluarea se face n mod natural. Spre exemplu, dac se declar:
float alpha = 20.45;
float beta = 25;
atunci evaluarea expresiei:
alpha + sqrt (beta),se face n ordinea indicat mai jos:
alpha + sqrt (25)
alpha + 5.0
20.45 + 5.0
25.45
Dac operanzii au tipuri diferite , se aplic conversii implicite de tip: unul din operanzi se convertete
la tipul celuilalt iar tipul rezultatului va fi tipul comun.
Operatorii ce pot apare ntr-un program C sunt de patru feluri:
operatori primari de parantetizare; acetia delimiteaz subexpresii i pot schimba asociativitatea
operatorilor. De pild expresiile
x * y +z i x * (y + z)
vor fi evaluate diferit pentru aceleai valori ale variabilelor, ca i perechea:
x+y*z ; (x + y) * z.
operatori binari cu notaie infixat adic:
operand operator operand.
Exemplu: x+y x % y.
operatori unari cu notaie prefixat sau postfixat:
-x, ++x, y--, x++.
operatorul ternar condiional
operand 1 ? operand 2 : operand 3.
14
369709427.doc
postfixai: variabila este incrementat (decrementat) dup evaluarea expresiei n care se afl iar
asociativitatea este de la stnga la dreapta..
Exemple: Fie declaraia
int i = 10, j, k, l, m;
atunci: j = i ++/* j = 10 apoi i = 10 */
k = ++i/* i = 12 apoi k = 12 */
l = i-- /* l = 12 apoi i = 11 */
m = --i /* i = 10 apoi m = 10 */
Operatorii binari sunt urmtorii
+ adunare * nmulire
- scdere / mprire
% modulo
La aceti operatori se adaug funciile din biblioteca matematic - prezentate n Anexa care sunt
operatori cu scriere prefixat:
- funciile trigonometrice uzuale: sin, cos, tan, asin, acos, atan;
- funcia de ridicare la putere pow;
- funciile exponenial, logaritmic etc.
15
Gheorghe GRIGORA
Semnificaia primilor trei operatori binari (&, |, ^) este cea natural (aminitm c 1 reprezint valoarea
logic adevrat iar 0 valoarea fals). Exemplele urmtoare sunt edificatoare.
op1 =01100100
op2 =10111010
~ op1 = 10011011
Operatorii binari de decalare ( << i >>) servesc la decalarea cu un anumit numr de bii (dat de cel de-
al doilea operand) la stnga sau la dreapta n cadrul primului operand. n particular se poate obine (rapid!)
nmulirea cu 2op2 (op1 << op2) sau cu 2-op2 (op1 >> op2).
Exemple:
x = 13;
y = x << 2;
z = x >> 2;
x = 0000 0000 0000 1101(= 13)
y = 0000 0000 0011 0100(= 13.4)
z = 0000 0000 0000 0011(= 13/4)
variabila = expresie;
Pe lng acest tip de asignare, limbajul C permite compunerea asignrii (#) cu un operator binar (op)
obinndu-se operatori de asignare compus:
e1 = (e1) op (e2);
16
369709427.doc
prin care cele n variabile capt valoarea expresiei din partea dreapt.
Spre exemplu
i = j = k = l = 1;
este o construcie valid n C; prin aceasta cele patru variabile i, j, k, l capt valoarea 1.
unde op1,op2,op3 sunt operanzi. Dac op1 are valoarea adevrat, expresia este egal cu op2 iar dac op1
are valoarea fals, expresia este egal cu op3.
Exemplu:
max = (a > b) ? a : b;
if (a > b)
max = a;
else
max = b;
Operatorul condiional se noteaz cu ?: i are asociativitatea de la dreapta la stnga.
Expresiile sunt evaluate de la stnga la dreapta iar valoarea ntregii expresii este valoarea (i tipul, se
nelege) expresiei ultime ce apare n acest ir.
O asemenea construcie apare frecvent n instruciuni for pentru realizarea mai multor aciuni:
Tabelul nr.6.
17
Gheorghe GRIGORA
18
Cap 3 FUNCTII
n limbajul C - spre deosebire de Pascal sau alte limbaje - nu exist noiunile distincte de procedur
i de funcie. n C exist doar funcii care returneaz o valoare. Este posibil definirea de funcii care s
retuneze valoarea vid: n acest caz tipul valorii returnate este void.
n general, utilizarea unei funcii permite:
- descompunerea unei secvene lungi de procesare a informaiei ntr-o mulime de secvene mici de
transformri de baz ale informaiei;
- furnizarea ctre ali programatori a unor elemente de baz de nivel nalt; detaliile acestor elemente
rmn ascunse pentru utilizator. Aceste elemente de nivel nalt ofer o claritate n plus programului
global i permite - relativ uor - modificri ulterioare ale acestuia.
n aceast definiie, tip este unul din cuvintele rezervate care definete tipul funciei, respectiv tipul
valorii returnate de un apel la aceast funcie. Dac aceast specificare lipsete, tipul implicit al funciei este
int. Funciile care returneaz n programul apelant valoarea vid se declar de tip void.
Numele unei funcii este un identificator i acesta trebuie s respecte aceleai reguli ca cele
referitoare la numele unei variabile. S precizm c nu se poate defini o funcie n interiorul altei
funcii.
Mulimea funciilor unui program poate fi partiionat n mai multe fiiere care pot fi compilate
separat. Limbajul C permite de asemenea utilizarea unor funcii predefinite (printf, getc, etc.), funcii ce se
gsesc n bibliotecile sistemului. Apelurile la aceste funcii sunt gestionate n faza de editare a legturilor.
Aa cum o variabil trebuie declarat nainte de a fi utilizat ntr-o expresie, o funcie trebuie
declarat nainte de a fi apelat. Declararea unei funcii const n a da signatura funciei. Signatura unei
funcii definete att tipul su (tipul valorii returnabile) ct i numrul i tipul argumentelor sale. Exist
dou moduri de a declara o funcie:
- implicit: n definiia funciei, linia de nceput conine tipul su i argumentele sale (numr i tip);
Gheorghe GRIGORA
- explicit: printr-o instruciune ce descrie signatura sa n cazul n care se face apel la o funcie descris
ntr-un fiier separat sau n cazul n care apelul la funcia respectiv precede declaraia funciei n acelai
fiier.
Iat cteva instruciuni de declarare a unei funcii:
long int cod (const char *, int);
char* decod (long int);
void schimbare (int , int);
int strlen (const char* s);
int funct ( );
n ultima linie avem un exemplu de funcie fr parametri (numrul parametrilor este zero).
return expresie;
O funcie f returneaz o valoare n corpul funciei din care s-a fcut apel la f, prin instruciunea
return (plasat n corpul lui f). Valoarea expresiei "expresie" va fi returnat i poate fi utilizat n programul
apelant. Tipul acestei expresii trebuie s fie acelai cu tipul funciei. O funcie care returneaz valoarea vid
(funcie de tip void) poate conine instruciunea "return" fr argument sau poate omite aceast
instruciune.
Exist funcii care pot avea un numr nedeterminat de parametri. Un exemplu la ndemn l ofer
funciile sistemului: printf, scanf, etc.:
printf ("Un apel cu un singur argument \n");
printf("x\%f\n",x);/*Un apel cu 2 argumente */
printf ("a\%d,b\%d\n",a,b); /*3 argumente */.
exit(valoare);
Funcia "exit" este o funcie sistem care termin execuia unui program. Acesta este singurul exemplu
de apel la o funcie care nu returneaz nimic: sistemul oprete execuia programului i raporteaz valoarea
transmis la apel. Aceast valoare poate fi util atunci cnd programul este executat n interiorul unei linii
de comand a interpretorului de comenzi. Prin convenie, valoarea nul (0) semnific faptul c programul
se termin normal iar o valoare nenul (1 sau -1) semnific faptul c s-a produs o eroare. n absena unei
instruciuni exit, valoarea implicit a codului returnat la sfritul execuiei unui program este 0.
20
369709427.doc
dac funcia este declarat fr tip i prin folosirea numelui funciei urmat de lista de parametri actuali ntr-
o expresie (n care este permis tipul ei) atunci cnd funcia este declarat cu tip .
Ordinea evalurii parametrilor este n general de la stnga la dreapta dar acest lucru nu este
garantat de orice compilator, nct trebuiesc luate msurile corespunztoare. De pild, secvena:
int n = 10;
printf ("%d %d \n", n++, n);
tiprete (cu unele compilatoare) 10 10 i nu 10 11.
S precizm c n C nu exist dect un singur mod de transmitere a parametrilor i anume
transmiterea prin valoare. Asta nseamn c parametrul actual (de la apel) i parametrul formal
corespunztor (declarat n antetul funciei) sunt dou variabile distincte. Modificrile efectuate asupra
parametrilor formali nu au dect un efect local care nu este vizibil n afara funciei. Asta nseamn c o
funcie nu poate modifica parametrii actuali..
Un exemplu clasic al consecinei acestui mod de transfer al parametrilor este ilustrat mai jos:
21
Gheorghe GRIGORA
0 nume - program
1 p1
:
.
n pn
0
Programul 2
main (int argc, char* argv )
if (argc<2)
printf ("Nu exista argumente in aceasta executie ! \n");
else
printf ("Argumentele executiei sunt: \n");
for (i 1; i < argc; i++)
printf ("%s", argv i );
prg2
22
369709427.doc
23
!
4.1.Fluxuri i fiiere
Sistemul de fiiere al limbajului C este conceput pentru a lucra cu o mare varietate de dispozitive,
inclusiv cu terminale, uniti de disc sau de band etc.. Dei fiecare dintre acestea este foarte diferit de
celelalte, sistemul de fiiere le transform pe fiecare ntr-un dispozitiv logic numit flux. Fluxurile sunt
independente de dispozitivele iniiale , nct aceeai funcie care scrie date pe un fiier de pe disc poate fi
folosit pentru a scrie date pe o alt categorie de dispozitive: consola, imprimanta. Aadar dispozitivul
fizic pe care se scriu datele se numete fiier iar abstractizarea acestuia se numete flux (sau stream). Exist
dou tipuri de fluxuri:
*3 Fluxul text este o scven de caractere. Standardul ANSI C permite organizarea unui flux text n
linii care se ncheie cu un caracter linie nou(n). Acesta din urm este opional pe ultima linie i este
determinat de modul de implementare. Datorit posibilelor conversii s-ar putea ca numrul de caractere
scrise/citite s difere de numrul de caractere existente pe dispozitivul extern.
*4 Fluxul binar este o secven de octei cu coresponden biunivoc fa de octeii existeni pe
dispozitivul extern: numrul de octei scrii/citii este acelai cu numrul acestora de pe dispozitivul extern.
Un fiier n limbajul C poate fi un terminal, o imprimant sau o zon (fiier) pe disc. Un flux se
poate asocia unui fiier executnd o operaie de deschidere: odat deschis, pot avea loc transferuri
de informaii ntre fiier i programul curent n execuie. Unificarea sistemului de intrare/ieire n C
se face prin pointerii de fiier. Un pointer de fiier este un pointer ctre informaia care definete
diverse caracteristici ale unui fiier(nume, stare, poziie curent etc). Pointerul de fiier identific un
anumit fiier i este folosit de ctre fluxul asociat pentru a conduce operaia de intrare/ieire.
Pentru a putea utiliza ntr-un program funciile standard de intrare/ieire trebuie scris la nceputul
acestui program o directiv "include" care are ca argument numele fiierului antet ce conine definiiile
acestor funcii: stdio.h .
include <stdio.h>
Orice program C ncepe execuia prin deschiderea unitilor de intrare/ieire standard:
stdin : unitatea standard de intrare
stdout : unitatea standard de ie[ire
stderr : unitatea de eroare
stdprn : unitatea standard de ie[ire prn
(imprimant\)
369709427.doc
Aceste uniti standard sunt asociate, n lipsa altor indicaii, tastaturii calculatorului (intrare) i
ecranului (ieire i eroare). Sistemul de fiiere ANSI C este compus din mai multe funcii legate una de alta.
Cele mai frecvent folosite dintre acestea sunt date n Tabelul 5 i vor fi prezentate n continuare.
Tabelul 5
NUME OPERA}IE
fopen( ) Deschide un fiier
fclose( ) nchide un fiier
putc( ) Scrie un caracter ntr-un fiier
fputc( ) Analog lui putc()
puts( ) Scrie un ir pe ecran
fputs( ) Scrie un ir pe fiier
getc( ) Citete un caracter dintr-un fiier
fgetc( ) Analog lui getc( )
gets( ) Citete un ir de la tastatur
fgets( ) Citete un ir din fiier
fseek( ) Caut un anumit octet ntr-un fiier
printf( ) Scrie la ieirea standard
fprintf( ) Analogul pentru fiiere al funciei printf( )
scanf( ) Citete din intrarea standard
fscanf( ) Analogul pentru fiiere al funciei scanf( )
feof( ) Returneaz adevrat dac se atinge sfritul fiierului
ferror( ) Returneaz adevrat dac survine o eroare
rewind( ) Iniializeaz indicatorul de poziie al fiierului la nceput
remove( ) terge un fiier
fflush( ) Golete coninutul unui fiier
Aici, fiier este un ir de caractere (identificator) ce desemneaz numele extern al fiierului iar mod este un
ir de caractere ce descrie modul de deschidere al fiierului. Modurile posibile de deschidere (deci irurile
de caractere ce constituie parametrul lui fopen) sunt date n Tabelul 6.
Tabelul 6.
25
Gheorghe GRIGORA
mod
Semnificaia
"r" Citire
"w" Creare (schimbare) pentru scriere
"a" Adugare la sfritul fiierului (existent)
"r+" Actualizare (citire/scriere)
"w+" Schimbare pentru actualizare
"a+" Actualizare cu scriere la sfritul fiierului (existent)
Facem precizarea c, deschiderea unui fiier existent n modurile "w" sau "w+" produce pierderea
coninutului su de pn atunci. Dac funcia fopen returneaz o valoare nenul, aceasta indic faptul
c deschiderea s-a efectuat corect. Valoarea returnat este un pointer la un descriptor de fiier valid,
valoare ce va fi utilizat n apelul la funciile de intrare/ieire. Dac deschiderea nu s-a efectuat corect
valoarea returnat este NULL(pointer la informaia nul) . Acest lucru poate fi folosit pentru tratarea
erorilor la deschiderea fiierului.
nchiderea unui fiier se face prin apelul la funcia fclose:
Funcia returneaz EOF n caz de eroare i 0 n caz normal. Prin nchidere se elibereaz descriptorul de
fiier, se actualizeaz fiierul pe disc i nceteaz conexiunea logic ntre pointer i fiier.
Apelul la fclose se poate face prin:
int cod;
FILE*pointer_la_fi[ier
cod = fclose
(pointer_la_fi[ier)
Fiierele pot fi reasignate prin program folosind funcia freopen:
FILE* freopen (const char*nume_fisier,
const char*mod,FILE*pf);
Apelul la aceast funcie nchide fiierul cu pointerul "pf", deschide fiierul cu numele
nume_fiier n modul de acces "mod", atribuind pointerul "pf" la acest fiier. Aceasta permite
redireciona-rea dispozitivelor periferice prin program. Programul urmtor ilustreaz acest fapt.
Programul 3
include <stdio.h>
main ( )
printf ("Mesaj scris pe monitor \n");
if(freopen("iesire.dat","w+",stdout)==NULL)
fprintf (stderr, "Eroare la reasignare \n");
exit (1);
printf ("Mesaj scris in fisierul iesire.dat \n");
fclose (stdout);
if (freopen ("CON", "wt", stdout) == NULL)
fprintf (stderr, "eroare la reasignarea lui stdout la CON\n");
exit (1);
printf ("Mesaj scris din nou pe monitor \n");
26
369709427.doc
FILE*tmpfile (void);
char c;
FILE* pointer_la_fiier;
c = fgetc(pointer_la_fiier);
Funcia fgetc returneaz valoarea ntreag a caracterului urmtor din fiierul pointat cu
pointer_la_fiier sau constanta EOF n caz de eroare sau sfrit de fiier.
Funcia fputc scrie un caracter la sfritul fiierului pointat prin pointer_la_fiier. n caz de eroare
este returnat valoarea EOF. Exist de asemenea dou funcii getchar i putchar care permit exprimarea n
C, simplificat, a scrierii apelului la fgetc i fputc n cazul n care intrarea respectiv ieirea este cea standard
: stdin respectiv stdout.
int cod;
char c;
FILE* pointer_la_fiier;
Spre exemplu:
c = getchar ( ); este echivalent cu:
c = fgetc (stdin);
iar putchar (c); este echivalent cu:
fput (c, stdout);.
Funciile de scriere cu format permit afiarea sub forma unui ir de caractere a diverselor valori.
Acestea pot fi transmise la ieirea standard, ntr-un fiier sau ntr-un ir de caractere.
27
Gheorghe GRIGORA
Funcia printf se utilizeaz pentru afiarea la ieirea standard, fprintf pentru scrierea ntr-un fiier,
iar sprintf pentru scrierea ntr-un ir de caractere.
Formatul "ir-format" este un ir de caractere ce conine fie caractere ordinare fie directive de
conversie pentru transformarea valorii unei variabile ntr-un ir de caractere
Caracterele ordinare sunt transmise la ieire aa cum apar ele pe cnd directivele de conversie
indic formatul de ieire pentru argumentele transmise n apelul funciei. O directiv se specific prin
caracterul % urmat de o secven de caractere ce identific formatul. Aceast secven conine, n ordine:
eventual unul sau mai muli indicatori ce modific semnificaia conversiei. Indicatorii disponibili n C
sunt:
eventual un numr pentru a indica dimensiunea minimal a cmpului n care se va afia. Dac
dimensiunea rezultat prin conversie este mai mic, caracterele se vor cadra la stnga (implicit) sau la
dreapta (pentru -). Se pot utiliza i dimensiuni variabile: se utilizeaz '*' n loc de numrul ce indic
dimensiunea iar variabila respectiv se pune n lista de argumente.
eventual caracterul l care precizeaz c numrul ce urmeaz a fi afiat este un "ntreg lung" (long
integer).
caracterul ce indic formatul conversiei. Formatele ce se folosesc n C sunt date n Tabelul 7.
28
369709427.doc
numrul de precizie;
p void* afieaz argumentul n notaia pointer;
n int* nu exist nici conversie nici afiare n acest caz: este vorba de
referine la un pointer la un ntreg n care se va stoca numrul de
caractere afiate pn n prezent;
% Permite afiarea caracterului %
Exemple
Urmtoarele programe ilustreaz folosirea formatelor de afiare la apelul funciei printf rezultatele
sunt ilustrate la sfritul fiecrui program.
Programul 4
include <stdio.h>
int main ( )
int i = 123;
long int l = 123456789L;
unsigned int ui = 45678U;
unsigned long int ul = 987654321UL;
double d = 123.45;
printf(" Forma zecimala:\n");
printf(" i = %d\n", i);
printf(" l = %ld\n", l);
printf(" ui = %u\n", ui);
printf(" ul = %lu\n\n", ul);
Forma octala:
ui = 131156
ul = 7267464261
printf("Scrierea hexazecimala:\n");
printf(" ui = %X\n", ui);
printf(" ul = %lX\n\n", ul);
printf("Afisarea semnului:\n");
printf("|% d| |%+d| |%d|\n",-123,-123,-123);
29
Gheorghe GRIGORA
Afisarea semnului:
|-123| |-123| |-123|
| 123| |+123| |123|
printf("|%+6.4d|\n", 123);
printf("|%+6.4o|\n", 123);
printf("|%+6.4X|\n", 123);
printf("\n");
Iat ce se va afia:
|0123|
|+0123|
|0X007B|
| 123| |123 |
| +123| |+123 |
| 0X7B| |0X7B |
| +0123|
| 0173|
30
369709427.doc
|0X007B|
31
Gheorghe GRIGORA
Directivele pentru specificarea unui format sunt utilizate pentru precizarea conversiei urmtorului
cmp citit. n general, rezultatul citirii este memorat n variabila corespunztoare din lista argumentelor
funciei. Se poate face o omisiune de afectare, punnd caracterul '*' n directiv (de ex. %*s): n acest caz
cmpul este citit dar nu-i memorat.
Cmpul ce urmeaz a fi convertit (ce este citit) se ntinde pn la primul spaiu sau numrul de
caractere din acest cmp este specificat n format.
Caracterele pentru specificarea unui format de citire sunt date n Tabelul 8.
Programul 5
#include <stdio.h>
int main(){
32
369709427.doc
33
Cap 5 INSTRUCIUNI DE CONTROL
5.1. Instruc]iunile if
5.2. Instruc]iunea switch
5.3. Instruc]iunea while
5.4. Instruc]iuneado...while
5.5. Instruc]iunea for
5.6. Instruc]iunea break
5.7. Instruc]iunea continue
5.8. Instruc]iunea go to
5.9. Exerci]ii
5.10. Solu]ii la exerci]ii
i = 1;
j = 2;
369709427.doc
s i = t j;
i ++;
j --;
s i = t j;
tip identificator;
tip identificator= valoare;
5.1. Instruciunea if
if(expresie) if ( expresie )
instruc]iune1 instruc]iune1
else
instruc]iune2
Ca [i `n alte limbaje de programare aceast\ instruc]iune permite alegerea
`ntre dou\ alternative. Tipul expresiei de dup\ cuv=ntul rezervat ifpoate fi `ntreg
(char, short, int sau long), real (float sau double) sau tip pointer. Expresia se
pune obligatoriu `ntre paranteze iar partea "else instruc]iune2;" este facultativ\.
Semantica acestei instruc]iuni este uzual\: dac\ valoarea expresiei "expresie" este
nenul\ (ceea ce `nseamn\ "true") atunci se execut\ instruc]iune1 iar dac\ aceast\
valoare este nul\ ("false") se execut\ instruc]iune2 (dac\ aceasta exist\).
Exemple:
if (x>y)
x = x-y;
else
y = y-x;
if (x>y)
printf("primul numar este cel mai mare\n");
else if (x==y)
printf("numerele sunt egale\n");
else
printf("al doilea numar este mai mare\n");
if ( a < b ) {
a += 2;
b += 1;
};
35
Gheorghe GRIGORA
else
a -=b;
Aten]ie! ~n acest ultim exemplu este o eroare de sintax\: alternativa else nu poate
fi asociat\ cu if pentru c\ `naintea sa ( dup\ } ) apare caracterul ; care reprezint\
instruc]iunea vid\! Apare [i problema ambiguit\]ii (a[a zisa problem\ dangling
else):
if ( a == 1 )
if ( b == 2 )
printf ( b este egal cu doi\n);
else
printf ( b nu este egal cu doi\n);
C\rui if `i este ata[at else? Limbajul C rezolv\ problema aceasta prin ata[area lui
else celui mai apropiat if, deci exemplul este interpretat astfel:
if ( a == 1 )
if ( b == 2 )
printf ( b este egal cu doi\n);
else
printf ( b nu este egal cu doi\n);
Exemplu:
switch (getchar ( ) )
case 'a':
printf ("s-a citit litera a\n");
break;
case 'b':
printf ("s-a citit litera b\n");
break;
36
369709427.doc
case 'c':
printf ("s-a citit litera c\n");
break;
default:
printf ("s-a citit altceva decat a, b sau c\n");
break;
while(expresie)
instruc]iune
Exemplu:
int c, n = 0;
while ((c = getchar( )) != EOF)
putchar (c);
n++
int x, y;
while (x!=y)
if (x>y)
x = x-y;
else
y = y-x;
Programul urm\tor ilustreaz\ utilizarea instruc]iunii while [i a instruc]iunii
switch. Acest program analizeaz\ un text [i num\r\ vocalele, spa]iile goale [i restul
caracterelor din acesta.
Programul 6
include <stdio.h>
int main (void)
int nvocale, naltele, nspatii;
char c;
nvocale = naltele = nspatii = 0;
printf ("Introduceti un text\n -->");
while ((c = getchar( )) != '\n')
switch (c)
37
Gheorghe GRIGORA
do
instruc]iune
while(expresie);
Exemplu:
int n = 0, c;
do
c = getchar ( );
n++;
while (c!= '\n');
printf ("Linia contine %d caractere \n", n-1);
int n = 1; c;
c = getchar ( )
while (c!= '\n')
c = getchar ( );
n++
;
38
369709427.doc
Aceasta este echivalent\ cu secven]a dat\ mai sus (2.) din care lipse[te prima
instruc]iune (expr1;)
Exemplu:
i = 0;
for(;(c = getchar( )) != '\0'; i++)
putchar (c);
printf("numarul de caractere:%d\n", i);
S\ observ\m c\ ini]ializarea lui i s-a f\cut `n afara instruc]iunii for !
Suprimarea expresiei de control:
Aceasta este o bucl\ infinit\. Singura modalitate de a ie[i din aceasta este
utilizarea instruc]iunii break.
Exemplu:
39
Gheorghe GRIGORA
if (c == '\n')
break;
Exemplu:
for( ; expr2 ; )
instruc]iune
Exemplu:
i=0
for (; (c = getchar( )) != '\0';
putchar (c)
i++
printf ("numarul de caractere: %d\n", i);
Exemplu:
Instruc]iunea break permite ie[irea dintr-o bucl\ (for, while, do) sau dintr-o
instruc]iune cu alegeri multiple (switch). Iata cateva exemple de utilizare a acestei
instructiuni (vezi [i programul de la sf=r[itul paragrafului 5.3):
1.
while ( ( c = getchar( )) != EOF)
sum++;
40
369709427.doc
if (sum>=50)
printf ("50\n");
break;
printf ("Iesire din bucla while\n");
~n acest prim exemplu, instruc]iunea break permite ie[irea din bucla while
dup\ citirea a 50 de caractere [i nu la `nt=lnirea caracterului EOF.
2.
while ( ( c = getchar( ))!= EOF)
sum++;
for (j = sum; sum <= 25; j++)
j* = 1.5;
if ( j >= 75.5) break;
printf ("Total: %d", sum);
5.8. Instruciunea go to
Instruc]iunea go to provoac\ saltul necondi]ionat la o etichet\, `n cuprinsul
go to eticheta ;
acelea[i func]ii.
Etichetele sunt nume ce se pun `n fa]a instruc]iunilor ]int\ urmate de ":". Este
recomandat s\ se evite folosirea instruc]iunii go to (a[a cer principiile program\rii
structurate) dar uneori este util\. ~n exemplul urm\tor se ilustreaz\ folosirea
instruc]iunii go to [i modul cum ea poate fi evitat\:
41
Gheorghe GRIGORA
int gasit = 0;
for (i = 0; i < n && ! gasit; i++)
for (j = 0; j < m &&! gasit; j++)
gasit = (a i == b j);
if (gasit)
printf (" a%d= b%d= %d\n",i,j,ai);
else
printf ("Tablourile nu au elemente comune \n");
5.9. Exerciii
jgjj
1. Calculul factorialului.
2. Conversie
Scrie]i un program care cite[te un num\r hexazecimal (ca o succesiune de
caractere), verific\ validitatea sa [i efectueaz\ conversia `n zecimal. Se va utiliza o
itera]ie pentru citirea caracter cu caracter a num\rului, itera]ia se opre[te dac\ se
cite[te un caracter ce nu este cifr\ hexazecimal\ [i, pe m\sur\ ce se citesc cifrele
hexazecimale se face conversia `n zecimal. Scrie]i dou\ variante ale programului:
a) programul con]ine doar func]ia principal\ main ( )
b) func]ia principal\ main face apel la o func]ie de conversie a unui caracter
reprezent=nd o cifr\ hexazecimal\ `n valoarea sa zecimal\:
int conversie (char x);
42
369709427.doc
4. Prezentare de date
Scrie]i un program care cite[te n valori `ntregi [i le afi[eaz\ c=te l pe fiecare
linie, ad\ug=nd la sf=r[itul liniei suma lor. Ultima linie va con]ine suma sumelor,
aliniat\ la sf=r[it de linie. Numerele n [i l se definesc ca valori constante.
1. Calculul factorialului
Iat\ o solu]ia incomplet\ a problemei. Programul va trebui completat cu un
test pentru a controla valoarea citit\ [i cu un test pentru a verifica dac\ rezultatul
calculului nu dep\[e[te capacitatea de reprezentare a unui num\r `ntreg.
/* Calculul lui n! */
include <stdio.h>
int main (void)
int n, i, fact;
printf ("Introduceti un numar natural ->");
scanf ("%d", &n);
fact = 1;
for (i = 2; i < = n; i++)
fact * = i;
printf (" %d ! = %d\", n, fact);
return 0;
2. Conversie
Vom construi o bucl\ while care se execut\ at=ta timp c=t ultimul caracter citit este
o cifr\ hexazecimal\: 0-9 sau a-f sau A-F. Dac\ este o astfel de cifr\, se converte[te `n
valoare `ntreag\, p\str=nd valoarea cumulat\ a num\rului zecimal ob]inut. Prima
solu]ie face conversie `n func]ia main ( ) iar a doua solu]ie folose[te o func]ie de
conversie.
a)
43
Gheorghe GRIGORA
b)
int i;
int val;
for (i = 0; i < 10; i++)
printf ("Introduceti o valoare intreaga: ");
scanf ("%d", &val);
44
369709427.doc
int numarbit(int x)
int n = 0;
while (x!=0)
if (x & 01)
n++;
x >>=1;
return n;
4. Prezentare de date
/* Se citesc n intregi si se afiseaza cate l pe **linie impreuna cu suma acestora la
sfarsit de **linie.Ultima linie contine suma sumelor */
include <stdio.h>
const n = 10;
const l = 3;
int main (void)
int val, /*ultima valoare intreaga citita */
sumap=0, /*suma din linia curenta*/
nl=0,/*numarul intregilor pe linie */
suma=0, /* suma sumelor par]iale */
nt; /*numarul total de intregi */
printf ("Introduceti%d numere intregi", n);
for (nt = 0; nt < n, nt++)
scanf ("%d", &val);
++nl;
suma p+= val;
printf ("%6d", val);
if (nl == l )
printf (" %6d\n", sumap);
nl = 0;
suma += sumap;
sumap = 0;
if (nl! = 0)
/*ultima linie este incompleta: se **completeaza cu spatii*/
int i;
for (i = nl; i < l; i++)
printf (" ");
suma += sumap;
45
Gheorghe GRIGORA
46
Cap 6 TABLOURI I POINTERI
6.1. Pointeri
6.2. Tablouri cu o dimensiune
6.3. Rela]ia `ntre pointeri [i tablouri
6.4. Opera]ii aritmetice cu pointeri
6.5. {iruri de caractere
6.6. Tablouri cu mai multe dimensiuni
6.7. Tablouri de pointeri
6.8. Pointeri [i alocarea memoriei
6.9. Operatorul sizeof
6.10. Pointeri c\tre func]ii
6.11. Exerci]ii
6.12. Solu]ii
6.1. Pointeri
tip *identificator;
int x;
x = *pi x = i;
Utilizarea operatorului "*" este destul de delicat\, chiar periculoas\ am spune:
acesta permite citirea sau scrierea `n orice zon\ de memorie. Utilizarea unui pointer
care este ini]ializat gre[it este o eroare des `nt=lnit\ `n programare [i din p\cate
consecin]ele sunt imprevizibile.
O aplica]ie important\ privind utilizarea pointerilor este transferul prin
referin]\ al parametrilor unei func]ii. A[a cum s-a precizat la capitolul
"Func]ii", `n limbajul C transferul implicit al parametrilor este prin valoare.
Dac\ se dore[te modificarea unui parametru formal, trebuie transmis\ func]iei
adresa variabilei iar `n corpul func]iei s\ se foloseasc\ operatorul de
dereferen]iere.
Exemplul clasic pentru acest procedeu este acela al func]iei de
interschimbare a dou\ variabile. Forma "clasic\" a func]iei, incorect\ (semantic) `n
limbaj C, este:
void schimbare (int a, int b)
int temp = a; a = b; b = temp;
Un apel al acestei func]ii (prin schimbare (x, y);) nu are nici un efect asupra
variabilelor x,y (actuale) pentru c\ func]ia lucreaz\ cu variabilele ei locale a [i b.
Varianta corect\ este:
void schimbare_corecta (int *p, int *q)
int temp;
temp = *p; *p = *q; *q = temp;
Apelul corespunz\tor este:
int x = 1, y = 2;
schimbare_corecta (&x, &y);
48
369709427.doc
tip nume[dim] = {
valoare_1,
valoare_2,
...
};
Exemple:
1. int a4 = 1, 2, 3, 4;
char s4 = 'a', 'b', 'c', '\o';
2.
define marime 5;
char tabmarime;
tab0 = 'a';
tab1 = tab2 = 'b';
tab3 = tab4 = 'd';
tabmarime - 1 = 'e';
tabmarime/2 = 'c';
Dupa aceste transformari structura sa va fi:
'a' 'b' 'c' 'd' 'e'
Dac\ lista de valori ini]iale (dat\ dup\ declara]ie) cuprinde mai pu]ine
elemente dec=t dimensiunea declarat\ a tabloului, atunci celelalte valori se
ini]ializeaz\ cu zero. Spre exemplu
int a10 = 5, 2, 3, 1;
are ca efect crearea tabloului:
5 2 3 1 0 0 0 0 0 0
49
Gheorghe GRIGORA
atunci expresiile a4, b1, c-2, sunt echivalente, `n sensul c\ ele reprezint\ adresa
aceleia[i zone de memorie.
50
369709427.doc
51
Gheorghe GRIGORA
tip nume[dim_1][dim_2]...[dim_n];
t[0] t t t t
00 01 02 03
t[1] t t t t
10 11 12 13
t[2] t t t t
20 21 22 23
52
369709427.doc
t 10 t t t 13
11 12
t 20 t t t 23
21 22
Elementul ha[urat (acela[i ca [i `n cazurile anterioare) se referen]iaz\ prin:
*( *t + 6)
sau prin nota]ia echivalent\:
*( &( t00 + 6))
S\ not\m c\ `n acest caz t este de tip pointer de pointer de `ntregi (dubl\
adresare indirect\).
O problem\ important\ relativ la tablourile cu mai multe dimensiuni este cea a
ini]ializ\rii acestora. A[a cum referen]ierea unui element al tabloului poate fi f\cut\
`n mai multe moduri, [i ini]ializarea unui tablou se poate face `n moduri diferite
(sintactic vorbind). S\ exemplific\m aceste moduri cu referiri la acela[i tablou pe
care l-am reprezentat mai sus, t34:
ini]ializarea prin enumerarea tuturor elementelor tabloului ( `n ordinea liniilor
dac\-i vorba de matrice):
int t34 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
ini]ializarea fiec\rei dimensiuni de tablou, separat:
int t34 =1, 2, 3, 4,5, 6, 7, 8,
9, 10, 11, 12
;
ini]ializarea numai a unor elemente din tablou:
int t34 = 1,5, 6;
Astfel t 00 va fi ini]ializat cu 1, t 10 cu 5 iar t 11 cu 6; restul
elementelor sunt ini]ializate cu zero.
53
Gheorghe GRIGORA
int i;
for (i = 0; i < n; i++)
if (tabp i != NULL)
printf ( "%s\n", tabpi );
54
369709427.doc
sortare(zi, 7);
~n corpul func]iei sortare s-a folosit un apel la func]ia strcmp care compar\ 2
[iruri de caractere s1 [i s2; rezultatul este negativ dac\ s1 < s2, pozitiv dac\ s1 > s2 [i
zero dac\ s1 # s2.
55
Gheorghe GRIGORA
tip(*nume)
(lista_arg);
tip: este tipul returnat de func]ia pointat\;
nume: este identificatorul pointerului la func]ie;
lista_arg : este lista argumentelor func]iei pointate.
De exemplu declara]ia:
char *(*p)(char*,const char*);
precizeaz\ c\ p este un pointer la o func]ie de tip char* (pointer la tipul char), are
doi parametri, unul de tip char*, cel\lalt de tipul const char*.
Este important a se pune *nume `n parantez\ deoarece declara]ia tip *nume
(lista_parametri) precizeaaz\ c\ nume este o func]ie de tip tip*.
Un exemplu de utilizare a tipului pointer la o func]ie este func]ia de comparare
cmp ce apare ca argument la func]ia de sortare qsort (vezi anexa ):
void qsort(const void* baza, size_t n, size_n t,
int(*cmp)(const void* val1, const void* val2))
Func]ia qsort este o func]ie de sortare general\ care permite sortarea unui
tablou de elemente de tip oarecare(baza) prin specificarea unei func]ii de
comparare. Iat\ un program ce utilizeaz\ func]ia qsort :
56
369709427.doc
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
6.11. Exerciii
1. A[a cum s-a mai precizat, `n C, [irurile de caractere sunt memorate `n
tablouri `n care ultimul element este un delimitator de sf=r[it de [ir: caracterul
57
Gheorghe GRIGORA
NULL(\0). ~n anex\ sunt date func]iile din biblioteca standard care se aplic\
[irurilor de caractere. S\ se scrie programe C care s\ implementeze func]iile:
a) int strlen(const char*s) : func]ie ce returneaz\ dimensiunea [irului s;
b) char* strcpy(char* dest,const char* sursa) : func]ie ce copie [irul sursa `n [irul
dest [i returneaz\ dest;
c) char* strcat(char* dest,const char* sursa): func]ie ce concateneaz\ [irul sursa
la sf=r[itul [irului dest [i returneaz\ valoarea lui dest;
d) int strcmp(const char* s1, const char* s2) : func]ie ce compar\ [irurile s1 [i s2
conform ordinii lexicografice. Dac\ are loc rela]ia s1 < s2, se returneaz\ o valoare
negativ\, dac\ s1 = s2 se returneaz\ 0 [i dac\ s1 > s2 se returneaz\ o valoare
pozitiv\.
6.12. Soluii
1. Implementarea func]iilor de la a) la d) se poate face folosind nota]ia tablou
sau aritmetica pointerilor.
58
369709427.doc
# include <stdlib.h>
# include <assert.h>
59
Cap 7 CONSTRUIREA DE NOI TIPURI
Aici tip este tipul ce se dore[te a fi redenumit iar nume_nou este numele ce se
d\ acestuia. Instruc]iunea permite redenumirea at=t a tipurilor de baz\ (deja
existente) c=t [i a tipurilor construite.
Iat\ c=teva exemple:
typedef long Mare;
typedef char Mesaj[49];
typedef char Luna[10];
Mare a,b;
369709427.doc
struct nume{
declara]ii
};
Structura este o colec]ie de una sau mai multe variabile (numite membri)
grupate sub un singur nume. ~n instruc]iunea de mai sus nume este facultativ;
el este totu[i util pentru a identifica structura definit\. Fiecare linie din partea
declara]ii define[te un c=mp al structurii. O variabil\ de tipul struct nume
poate fi definit\ `n aceea[i instruc]iune `n care este definit\ structura sau separat
Iat\ c=teva exemple:
struct Persoana{
char nume[20];
char prenume[20];
int varsta;
} amicul;
struct Data{
short ziua;
short luna;
short anul;
};
struct Student{
char *nume;
char *prenume;
struct Data data_nasterii;
int an;
char *grupa;
}
struct Student ionescu, popescu;
typedef struct{
short ziua;
short luna;
short anul;
} Data;
typedef struct {
char nume[20];
61
Gheorghe GRIGORA
char prenume[20]
Data data_nasterii;
} Persoana;
Dou\ structuri de acela[i fel pot s\ apar\ `ntr-o expresie de atribuire. O atribuire
de structuri este o copiere bit cu bit a elementelor corespunz\toare, `nc=t o astfel
de expresie are sens doar dac\ structurile sunt de acela[i tip. Are sens asfel:
necunoscut = ionescu ;
62
369709427.doc
typedef struct {
...
} valoare;
/* s-a definit tipul "valoare" pentru **informatia din nodurile arborelui*/
typedef struct Arbore{
valoare val;
struct Arbore *stang;
struct Arbore *drept;
} Arbore;
# include <stdio.h>
# include <stlib.h>
typedef int valoare;
typedef struct Arbore{
valoare val;
struct Arbore* stang;
struct Arbore* drept;
} Arbore;
Arbore* adauga(valoare v, Arbore* s, Arbore* d);
void afisare (Arbore* a);
int main( ){
Arbore* a1;
Arbore* a2;
a1=adauga(1, adauga(2, adauga(3, NULL, NULL),
NULL), adauga(4, NULL, NULL));
printf("Primul arbore este: \n");
afisare(a1);
a2=adauga(10, a1, adauga(20, NULL, NULL));
printf("\n");
printf("Al doilea arbore este: \n");
afisare(a2);
63
Gheorghe GRIGORA
printf("\n");
return 0;
}
Arbore* adauga(valoare v, Arbore* s, Arbore* d){
Arbore* c;
c=malloc (sizeof (Arbore));
c->val = v;
c->stang = s;
c->drept = d;
return c;
}
void afisare (Arbore* a){
if (a! = NULL) {
printf ("(%d", a->val , " ");
afisare (a->stang);
printf (" ");
afisare (a->drept);
printf (")");
} else
printf ("nil");
}
Execu]ia programului are ca rezultat afi[area urm\toarelor informa]ii:
Primul arbore este:
(1 (2 (3 nil nil) nil) (4 nil nil))
Al doilea arbore este:
(10(1 (2 (3 nil nil) nil) (4 nil nil)) (20 nil nil))
enum nume {
lista_de_identificatori};
Un tip enumerare permite ca, `ntr-o maniera elegant\,s\ definim un tip care nu
poate lua valori dec=t `ntr-o mul]ime precizat\ de valori constante. Primul
identificator constant din lista de identificatori cap\t\ valoarea 0, al doilea valoarea
1, etc. cu excep]ia cazului `n care programatorul ofer\ valori ini]iale acestor
identificatori.
Exemple:
enum Bool {da, nu};
Aici da are valoarea 0 iar nu are valoarea 1.
enum Bool {da=1, nu=0};
enum Bool {nu, da}
~n ambele situa]ii, nu are valoarea 0 iar da are valoarea 1.
enum Luna {ian=1, feb, mar, april, mai,
iunie, iulie, august, sept, oct, nov, dec};
Aici, pentru c\ lui ian i s-a dat valoarea ini]ial\ 1, celelalte luni vor avea respectiv
valorile 2, 3, ..., 12.
Similar cu definirea variabilelor de tip structura se definesc variabilele de tip
enumerare:
enum Bool raspuns;
enum Bool spune=da;
64
369709427.doc
7.6. Uniuni
Uniunile sunt structuri care pot con]ine (la momente de timp diferite), obiecte
de tipuri diferite. De fapt, este vorba despre zone de memorie care, la un moment
dat con]in un anume tip de variabil\ iar la alt moment acest tip se poate schimba.
Sintaxa este similar\ cu cea care define[te o structur\:
union nume {
declara]ii
};
Typedef union {
struct {
long abscisa;
long ordonata;
} cart;
struct {
float ro;
float teta;
} pol;
} Coordonate;
float pi=3.1415926;
Coordonate p1, p2;
...
printf("%d%d\n",p1.cart.abscisa,p1.cart.ordonata);
printf("%f%f\n",p2.pol.ro,p2.pol.teta);
O variabil\ de tip Coordonate, cum sunt de pild\ p1 [i p2, poate con]ine fie valori
`ntregi reprezent=nd coordonatele carteziene fie valori flotante reprezent\nd
coordonatele polare. Desigur c\ `n acest caz se presupune c\ prin program se afl\ c\
p1 este de tip cart iar p2 este de tip pol. Declara]iile precedente pot fi modificate
astfel (pentru a memora `n variabil\ `ns\[i tipul de reprezentare ales) :
65
Gheorghe GRIGORA
typedef union {
TipCoord tip;
struct {
TipCoord tip;
long abscisa;
long ordonata;
} cart;
struct {
TidCoord tip;
float ro;
float teta;
} pol;
} Coordonate;
typedef struct {
TipCoord tip;
union {
struct {
long abscisa;
long ordonata;
} cart;
struct {
float ro;
float teta;
} pol;
} val;
} Coordonate;
7.7. Exerciii
bogdan 1430
[tefan 2143
victor 2114
zeno 1442
1.2 crearea programului care realizeaz\ urm\toarele:
a) ini]ializarea unui tablou de elemente structurate prin citirea fi[ierului ce
reprezint\ agenda telefonic\;
b) consultarea agendei: la furnizarea unui nume programul ofer\ num\rul de
telefon corespunz\tor (dac\ acesta exist\).
De exemplu:
anca
tel.: 2130
anuta
persoan\ necunoscut\
[tefan
tel.: 2143
quit
2. S\ se scrie un program care s\ realizeze:
a) alc\tuirea unei liste de adrese care folose[te un tablou de structur\ pentru
stocarea informa]iilor legate de adrese (nume, strada, ora[, codul po[tal);
b) completarea tabloului de structuri cu noi adrese;
c) afi[area pe ecran a listei de adrese.
7.8. Soluii
1. Vom construi dou\ func]ii pentru c\utarea `n agenda telefonic\: caut\_secv pentru
c\utarea secven]ial\ [i caut\_dih pentru c\utarea dihotomic\(binar\).
# include <stdio.h>
# include <string.h>
# define dim_agenda 100
# define lung_nume 20
typedef char sir[lung_nume]
typedef struct {
sir nume;
int tel;
} persoana;
/* s-a definit o structura de tip persoana*/
persoana agenda[dim_agenda];
/* s-a definit agenda ca un tablou de persoane */
int n=0; /* numarul persoanelor din agenda */
/* urmeaza functia de cautare secventiala */
int cauta_secv(char cineva[ ]) {
int compar=1;
int i=0;
while ((compar>0) && (i<n)) {
compar=strcmp(cineva, agenda[i].nume);
i++;
}
return (compar==0)? i-1:-1;
}
/* urmeaza functia de cautare dihotomica */
67
Gheorghe GRIGORA
68
369709427.doc
# include <stdio.h>
# include <stdlib.h>
# define MAX 100
struct adresa {
char nume[30];
char strada[40];
unsigned long int numar;
char oras[20];
unsigned long int cod_postal;
} adresa_info[MAX];
void init_lista(void), introducere(void);
void sterge(void), afiseaza(void);
int select_meniu(void), gaseste_liber(void);
void main(void){
char optiune;
init_lista();
for(;;) {
optiune=select_meniu();
switch(optiune) {
case 1: introducere();
break;
case 2: sterge();
break;
case 3: afiseaza();
break;
case 4: exit(0);
}
}
}
void init_lista(void){
register int t;
for(t=0;t<MAX;++t)adresa_info[t].nume[0]= \0;
}
int select_meniu(void){
char s[80];
int c;
printf("1. Introduceti un nume \n");
printf("2. Stergeti un nume \n");
printf("3. Afisati fisierul \n");
printf("4. Iesire din program \n");
do {
printf("\n Introduceti optiunea dvs.: ");
gets(s);
c=atoi(s);
} while (c<0 || c>4);
69
Gheorghe GRIGORA
return c;
}
void introducere(void){
int liber;
char s[80];
liber=gaseste_liber();
if (liber==-1) {
printf("\n Lista este completa. ");
return;
}
printf("Introduceti numele: ");
gets(adresa_info[liber].nume);
printf("Introduceti numele strazii: ");
gets(adresa_info[liber].strada);
printf("Introduceti numarul: ");
gets(s);
adresa_info[liber].numar=strtoul(s, \0,10);
printf("Introduceti numele orasului: ");
gets(adresa_info[liber].oras);
printf("Introduceti codul postal: ");
gets(s);
adresa_info[liber].cod_postal=
strtoul(s, \0,10);
}
gaseste_liber(void){
register int t;
for(t=0;adresa_info[t].nume[0]&&t<MAX;++t);
if (t==MAX) return -1;
/* Nu mai este loc in lista*/
return t;
}
void sterge(void){
register int liber;
char s[80];
printf("Introduceti nr. inregistrarii: ");
gets(s);
liber=atoi(s);
if (liber>=0 & liber<MAX)
adresa_info[liber].nume[0]= \0;
}
void afiseaza(void){
register int t;
for (t=0; t<MAX; ++t) {
if (adresa_info[t].nume[0]) {
printf("%s\n",adresa_info[t].nume);
printf("%s\n",adresa_info[t].strada);
printf("%lu\n",adresa_info[t].numar);
printf("%s\n",adresa_info[t].oras);
printf("%lu\n",
adresa_info[t].cod_postal);
}
}
70
369709427.doc
printf("\n\n");
}
71
Cap 8 GESTIUNEA MEMORIEI
mem tip
identificator;
unde: mem este unul din cuvintele cheie: auto, register, static, extern;
tip este cuv=ntul cheie ce define[te tipul variabilei;
identificator este numele variabilei.
A[adar, o variabil\ este identificat\ printr-un nume (identificator), posed\ un anume
tip [i este administrat\ de un anume mecanism de memorare.
Tipul variabilei va determina:
- dimensiunea zonei de memorie alocat\ pentru a reprezenta variabila;
- interpretarea con]inutului variabilei atunci c=nd ea este supus\ unor
instruc]iuni.
Categoria de memorare (mem) c\reia-i apar]ine variabila va determina:
- vizibilitatea variabilei: identificarea p\r]ii din program capabil\ s\ foloseasc\
acea variabil\;
- durata de via]\ a variabilei: perioada de timp `n care variabila este accesibil\;
- ini]ializarea variabilei: con]inutul implicit (dac\ exist\ unul) al variabilei la
crearea sa.
Vom trece `n revist\ aceste mecanisme de memorare.
73
Gheorghe GRIGORA
O variabil\ global\ este o variabil\ static\ care poate fi referen]iat\ `n orice loc al
programului. O astfel de variabil\ se declar\ prin:
tip
identificator ;
74
369709427.doc
Exemple:
Fi[ier 1 Fi[ier 2 Fi[ier 2
int x,y; extern int x, y; extern int x,y;
char c; extern char c; extern char c;
main(void){ fun1(void){...x=...}; funct1(void)
... fun2(void){...y=...}; {
} ... x=..
... ..
}
~n cazul declar\rii func]iilor ce se definesc `n alt modul (fi[ier), cuv=ntul extern
este facultativ.
Declara]ia:
extern void functie(char);
este echivalent\ cu:
void functie (char);
~n cazul func]iilor important este s\ se descrie signatura sa, adic\ tipul rezultatului
[i al parametrilor de apel.
75
Gheorghe GRIGORA
8.8. Exerciii
8.9. Soluii
76
369709427.doc
char top_stiva(){return(stiva[index-1]);}
int stiva_vida(){return(index==0);}
int stiva_plina(){return(index==dim);}
/* prog.c : modulul principal */
# include "stiva.h"
# include "stiva.c"
# include <stdlib.h>
# include <stdio.h>
int main()
{
char element;
printf("Incarcati stiva: \n>");
while(!stiva_plina()&&scanf("%c",&element)!=EOF){
push(element); printf(">");
}
printf("\n");
printf("Iata continutul stivei: \n");
while (!stiva_vida()) {
element=top_stiva(); printf("<%c\n",element);
pop();
}
return 0;
}
2. /*stiva.h*/
# define dimensiune_sir 80
# define dimensiune_stiva 10
typedef char sir[dimensiune_sir];
void push(const sir ch);
void pop(sir ch);
int stiva_vida(void);
int stiva_plina(void);
/*modul.c
** Gestionarea unei stive de siruri de caractere.
*/
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include "stiva.h"
/*
** variabile cu clasa de memorare *static*,
**nevizibile in alte fisiere.
*/
static int index=0;
/* indicile top-ului stivei */
static sir stiva[dimensiune_stiva];
void push(const sir c){
/* Se copie c in stiva dupa care se incrementeaza **index. Inainte de aceasta se
apeleaza functia **assert care impune o conditie pentru a continua **executia:
stiva sa nu fie plina.
*/
assert(!stiva_plina());
77
Gheorghe GRIGORA
strcpy(stiva[index],c);
index++;
}
void pop(sir c){
/* se decrementeaza index apoi se copie top-ul **stivei in c */
assert(!stiva_vida());
--index;
strcpy(c,stiva[index]);
}
int stiva_vida(void){ return(index==0);}
int stiva_plina(void){
return(index==dimensiune_stiva);
}
/* test.c : programul de test ce consta din doua **iteratii: prima pentru citirea
din fisierul de **intrare si stivuirea informatiei, a doua pentru **afisarea
rezultatului destivuirii.
*/
# include <stdio.h>
# include "stiva.h"
int main(void){
sir x;
printf("Se incarca stiva: \n>");
while(!stiva_plina()&&scanf("%s",x)!=EOF) {
push(x);
printf(">");
}
printf("\n");
printf("Iata continutul stivei: \n");
while (!stiva_goala()) {
pop(x);
printf("<%s\n",x);
}
return 0;
}
78
Cap 9 CONVERSIA DE TIP
~n conversia la asignare, c=nd apar dou\ tipuri diferite, lucrurile se petrec dup\
cum urmeaz\:
1. asign\ri `n care intervin dou\ tipuri `ntregi:
(a) reprezentarea tipului surs\ este mai mare ca dimensiune dec=t
reprezentarea tipului destinatar:
char=short/int/long
short=int/long
int=long
~n acest caz bi]ii de rang superior din valoarea din partea dreapt\ a asign\rii
sunt suprima]i `nc=t exist\, poten]ial, o pierdere de informa]ie.
(b) reprezentarea tipului destinatar este mai mare ca dimensiune
dec=t cea a tipului surs\:
long=int/short/char
int=short/char
short=char
~n acest caz nu exist\ pierdere de informa]ie: bi]ii sursei sunt
completa]i cu zero (p\str=ndu-se eventualul bit semn). Dac\ destinatarul este un tip
far\ semn, mecanismul este acela[i; bitul semn `n schimb nu se mai transfer\:
unsigned long=int/short/char
unsigned=short/char
unsigned short=char
2. asignarea unei valori reale la o valoare `ntreag\:
char/short/int/long=float/double
~n acest caz sunt suprimate cifrele de la partea zecimal\: este conversie prin
trunchiere [i nu prin rotunjire. Dac\ valoarea p\r]ii `ntregi a sursei este prea mare
pentru a fi reprezentat\ `ntr-un `ntreg, apare o eroare (Floating point exception).
3. asignarea unei valori reale `n dubl\ precizie la o variabil\ real\ `n simpl\
precizie:
float=double
80
369709427.doc
i + c
(int) (char)
Faza 1: int int
Faza 2: int int
Rezultatul: int
i + (a + b)
(int) (long) (float)
Faza 1 long double
Faza 2 double double
Rezulta double
t int double
Faza 1 double double
Faza 2 double
Rezulta
t
81
Gheorghe GRIGORA
ptr1=alocare(10);
ptr2=alocare(20);
Asign\rile pentru ptr1, ptr2 sunt corecte: tabloul de pointeri alocare este de tip
void* `nc=t ace[ti pointeri pot fi asigna]i la pointeri de orice tip.
Tipul pointer universal void* este folosit frecvent `n func]iile disponibile din
bibliotecile limbajului C (Anexa) `n scopul de a realiza conversii implicite `ntre
pointeri de tipuri diferite.
83
Cap 10 PREPROCESORUL
instruc]iune
argumente
if else endif
elif include ifdif
line error pragma
define identificator
[ir_de_caractere
Exemple:
# define NULL 0L
# define TRUE 1
# define FALSE 0
# define EOF (-1)
Utilizarea constantelor simbolice are diverse scopuri. Acest mecanism permite:
a asigna unui identificator un [ir de caractere;
a defini existen]a unei constante simbolice:
# define ident
a suprima defini]ia [i existen]a unei constante simbolice:
#undefident
Vizibilitatea constantelor simbolice `ncepe cu definirea lor (directiva #define) [i
]ine p=n\ la sf=r[itul fi[ierului, cu excep]ia cazului c=nd `n acesta apare o directiv\
#undefine pentru identificatorul corespunz\tor.
Exemplu:
#defineEOF(1)
....
#defineUNU
....
#undefineUNU
....
# include<nume_fisier>
/* se caut\ fi[ierul `ncep=nd cu directoarele
standard */
sau
85
Gheorghe GRIGORA
# includenume_fisier
/* se caut\ fi[ierul `n directorul curent sau cel
indicat prin cale */
# include <math.h>
....
val=pow(M_PI, (double)n);
/* se calculeaza puterea a n-a a lui */
~n fi[ierul math.h se afl\ defini]ia constantei M_PI [i a func]iei pow( ).
# if expr_constanta
# else
# endif
# elif expr_constanta
# ifdef identificator
# ifndef identificator
# if expresie
cod;
# elif expresie1
cod1;
# elif expresie2
cod2;
....
# elif expresien
codn;
# endif
86
369709427.doc
Directivele ifdef (if defined) [i ifndef (if not defined) sunt utilizate pentru
compilarea condi]ionat\ de definirea anterioar\ a lui identificator `ntr-o directiv\
de tipul define. Ambele directive pot folosi o alternativ\ de forma else dar nu [i
elif.
~n concluzie, compilarea condi]ionat\ este folosit\ pentru:
scrierea de programe portabile: constantele simbolice ce se testeaz\ pot
reprezenta tipul [i caracteristicile ma[inilor utilizate pentru o anume por]iune
de cod;
optimizarea unor coduri utiliz=nd avantajele specifice fiec\rei ma[ini;
traseul de execu]ie al programelor `n faza de test.
10.2 Macroinstruiuni
Aici num\r este orice `ntreg pozitiv; acesta devine noua valoare a lui _LINE_ `n
punctul `n care se `nt=lne[te directiva, iar nume_fi[ier este un identificator valid
de fi[ier care devine noua valoare a lui _FILE_.
Macroinstruc]iunea _DATE_ con]ine un [ir de forma lun\/zi/an `n care lun\, zi,
an sunt compuse din c=te dou\ cifre ce reprezint\ `n ansamblu data conversiei
fi[ierului surs\ `n cod obiect. Ora la care a fost executat\ aceast\ conversie este
con]inut\ `n _TIME_ sub forma [irului ora/minute/secunde.
Macroinstruc]iunea _STDC_ con]ine constanta 1 scris\ `n baza 10. Aceasta
semnific\ faptul c\ implementarea este conform standardului ANSI C. Dac\ _STDC_
nu-i definit\ sau con]ine altceva dec=t 1, implementarea nu este `n variant\
standard.
87
Gheorghe GRIGORA
88
Cap 11 EXERCIII
1. S\ se scrie un program numit maxmin.c care s\ execute :
a. citirea unui intreg pozitiv n;
b. citirea a n numere reale;
c. determinarea valorilor maxim [i minim dintre cele n numere citite;
unde Min(Max) `nseamn\ cel mai mic(mare) dintre numerele citite p=n\ `n acel
moment, Suma [i Media fiind suma (media) numerelor citite p=n\ `n acel moment
12. S\ se scrie func]iile care implementeaz\ o stiv\ `n C(push, pop, top, etc).
S\ se foloseasc\ acestea pentru a verific\ dac\ un [ir de caractere format
numai din literele a, b, c este palindrom cu centrul c:
[irurile: aabacabaa , bababbcbbabab, c, aca, bbcbb
sunt palindroame pe c=nd [irurile:
aabbcbb. ccab, aaaaaaaacaaaabb, acb, aaaa
nu sunt palindroame.
verifica daca valoarea unei variabile din structura este o data valida.
90
369709427.doc
BIBLIOGRAFIE
1. Herbert Schildt C - Manual Complet, Bucuresti, Ed. Teora 1998
2. Liviu Negrescu Limbajele C si C++ pentru incepatori, vol I- III, Cluj-Napoca
Volumul I - Limbajul C
Volumul II - Limbajul C++
Volumul III - Limbajele C si C++ in Aplicatii
3. Cristea,V.,C.Giumale, E.Kalisz. A.P\nsiu, Limbajul C standard. Editura
Teora, 1992.
4. Grigora[, Gh. Programarea calculatoarelor:Fundamente, Editura Spiru
Haret, Ia[i, 1999.
5. P\tru], B., Aplica]ii `n C [i C++, Editura Teora, Bucure[ti, 1998.
6. Musc\, Gh. [i al]ii, Informatic\ aplicat\, manual pentru licee de informatic\,
cls.XI, Editura Didactic\, Bucure[ti 1998
91
ANEXA
Biblioteca standard C
FI{IERE HEADER
<assert. <limits.h <signal.h> <stdlib.
h> > h>
<ctype.h <locale.h <stdarg.h> <string.
> > h>
<errno.h <math.h <stddef.h> <time.h
> > >
<float.h <setjmp. <stdio.h>
> h>
Dac\ expr este zero, este tip\rit un mesaj(diagnostic) [i se iese din program.
Mai con]ine:
int tolower (int c) [i int toupper ( int c)
93
Gheorghe GRIGORA
int fsetpos (FILE *fp, const fpos_t *pos); /* Seteaz\ indicatorul la valoarea pos */
int rename (const char *from, const char *to);
94
369709427.doc
char *strncpy(char *s1, const char *s2, size_t n) /* copie cel mult n caractere din
s2 `n s1 */
char *strstr(const char *s1, const char *s2); /* caut\ `n s1 prima apari]ie a lui s2
*/
char *strtok(char *s1, const char *s2); /* caut\ tokenuri `n s1 folosind caracterele
din s2 ca separatori */
15. Fi[ierul <time.h> con]ine prototipuri ale func]iilor pentru ob]inerea datei,
orei ]i cele privind ceasul intern al calculatorului. Se folose[te structura tm care
este definit\ astfel:
struct tm {
int tm_sec; /*secunde 0..60*/
int tm_min; /*minutr 0..59 */
int tm_hour; /*ore 0..23 */
int tm_mday; /*ziua lunii 1..31 */
int tm_mon; /*luna anului 0..11 */
int tm_year; /*anul de la 1900 */
int tm_wday; /* zilele de la 0 la 6 */
int tm_yday; /*zilele din an 0..365 */
int tm_isdst; /* Indicator de timp */
};
Func]ii:
typedef long clock_t;
typedef long time_t;
clock_t clock(void); /*returneaz\ num\rul de tacturi CPU utilizate de program
p=n\ aici*/
time_t time(time_t *tp); /*returneaz\ nr. de secunde trecute de la 1 Inuarie
1970 */
char *asctime(const struct tm *tp); /*converte[te timpul inregistrat [i
pointat de tp `ntr-un string ce reprezint\ data*/
char *ctime (const time_t *t_ptr); ?8 converte[te timpul pointat de t_ptr la
string - data*/
struct tm *localtime(const time_t *t_ptr);
De exemplu:
time_t acum;
acum = time(NULL);
printf("%s\n%s ", ctime(&acum),
asctime(localtime(acum)));
..
Codul ASCII
95
Gheorghe GRIGORA
Interchange
0 1 2 3 4 5 6 7 8 9
0 nul soh stx etx eot enq ack bel bs ht
1 nl vt np cr so si dle dc1 dc2 dc3
2 dc4 nak syn etb can em sub esc fs gs
3 rs us sp ! # $ % &
4 ( ) * + , - . / 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ \ ] ^ _ a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z { | } ~ del
Observa]ii:
Caracterul G este `n linia 7 [i coloana 1 deci are codul ASCII 71;
Caracterele cu codurile 0-31 [i 127 nu sunt tip\ribile;
Caracterul cu codul 32 este spa]iu (gol) [i se tip\re[te ca [i un spa]iu gol;
Codurile caracterelor 0-9, A - Z [i a - z sunt contigue;
Diferen]a `ntre codurile literelor mari [i cele mici corespunz\toare este 32;
~n tabela urm\toare se da semantica unora din caracterele de pe liniile 0-2.
~n]elesul unor abrevieri
be audible ht tab orizontal
l bell
bs backspase nl linie nou\
cr retur car nul null
es escape vt tab vertical
c
96
369709427.doc
97