You are on page 1of 94

48627669.

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.........................................................................................................10 2.1. Tipuri simple.............................................................................................................................11 2.2. Literali ......................................................................................................................................11 2.3. Declararea unei variabile şi a unei constante........................................................................12 2.4. Operatori...................................................................................................................................14 2.4.1. Operatori aritmetici.............................................................................................................14 2.4.2. Operatorii relaţionali (de comparaţie).................................................................................15 2.4.3. Operatori logici...................................................................................................................15 2.4.4. Operatori la nivel de bit......................................................................................................15 2.4.5. Operatorul de asignare........................................................................................................16 2.4.6. Operatorul condiţional........................................................................................................17 2.4.7. Operatorul virgulă...............................................................................................................17 2.4.8. Precedenţa operatorilor.......................................................................................................17 Cap 3 FUNCTII...................................................................................................................................19 3.1. Definirea unei funcţii...............................................................................................................19 3.2. Returnarea unui apel...............................................................................................................20 3.3. Funcţii cu un număr variabil de parametri..........................................................................20 3.4. Sfârşitul execuţiei unui program............................................................................................20 3.5. Apelul şi transmiterea parametrilor......................................................................................21 3.6. Funcţia principală main..........................................................................................................22 Cap 4 FUNCŢII DE INTRARE IEŞIRE............................................................................................24 4.1.Fluxuri şi fişiere.........................................................................................................................24 Semnificaţia......................................................................................................................................26 4.2. Funcţii de intrare/ieşire pentru caractere..............................................................................27 4.3. Scrierea cu format....................................................................................................................27 4.5. Citirea cu format......................................................................................................................31 Cap 5 INSTRUCŢIUNI DE CONTROL.............................................................................................34 5.1. Instrucţiunea if.........................................................................................................................35 5.3. Instrucţiunea while...................................................................................................................37 5.4. Instruc]iunea do ... while.........................................................................................................38 5.5. Instrucţiunea for.......................................................................................................................39
i

Gheorghe GRIGORAŞ

5.6. Instrucţiunea break..................................................................................................................40 5.7. Instrucţiunea continue.............................................................................................................41 5.8. Instrucţiunea go to...................................................................................................................41 5.9. Exerciţii.....................................................................................................................................42 Calculul factorialului. ...................................................................................................................42 2. Conversie...................................................................................................................................42 3. Numărarea biţilor 1 într-un număr............................................................................................42 4. Prezentare de date......................................................................................................................42 5.10. Soluţii la exerciţii...................................................................................................................42 1. Calculul factorialului.................................................................................................................43 2. Conversie...................................................................................................................................43 3. Numărarea biţilor 1 într-un număr............................................................................................44 4. Prezentare de date......................................................................................................................45 Cap 6 TABLOURI ŞI POINTERI.......................................................................................................46 6.1. Pointeri......................................................................................................................................46 6.2. Tablouri cu o dimensiune........................................................................................................47 6.2.1. Referenţierea unui element al tabloului..............................................................................47 6.2.2. Iniţializarea unui tablou......................................................................................................48 6.3. Relaţia între pointeri şi tablouri.............................................................................................49 6.4. Operaţii aritmetice cu pointeri...............................................................................................50 6.5. Şiruri de caractere....................................................................................................................50 6.6. Tablouri cu mai multe dimensiuni.........................................................................................51 6.7. Tablouri de pointeri.................................................................................................................52 6.8. Pointeri şi alocarea memoriei..................................................................................................53 6.9. Operatorul “sizeof”..................................................................................................................54 6.10. Pointeri către funcţii..............................................................................................................55 6.11. Exerciţii...................................................................................................................................56 6.12. Soluţii.......................................................................................................................................57 Cap 7 CONSTRUIREA DE NOI TIPURI..........................................................................................59 7.1. Redenumirea unui tip..............................................................................................................59 7.2. Tipul structură........................................................................................................................60 7.3. Accesul şi iniţializarea câmpurilor unei structuri.................................................................61 7.4. Structuri autoreferenţiate.......................................................................................................62 7.5. Tipul enumerare.......................................................................................................................63 7.6. Uniuni.......................................................................................................................................64 7.7. Exerciţii.....................................................................................................................................65 7.8. Soluţii.........................................................................................................................................66 Cap 8 GESTIUNEA MEMORIEI.......................................................................................................70 8.1. Precizarea unui mecanism de memorare...............................................................................71 8.2. Gestiunea automată a memoriei.............................................................................................71
ii

48627669.doc

8.3. Gestionarea “register” a memoriei.........................................................................................72 8.4. Gestionarea statică a memoriei...............................................................................................72 8.5. Variabile globale.......................................................................................................................72 8.6. Declararea variabilelor externe..............................................................................................73 8.7. Gestiunea dinamică a memoriei..............................................................................................73 8.8. Exerciţii.....................................................................................................................................74 8.9. Soluţii.........................................................................................................................................74 Cap 9 CONVERSIA DE TIP...............................................................................................................77 9.1. Mecanisme de conversie..........................................................................................................77 9.1.1 Conversia la asignare...........................................................................................................78 9.1.2 Evaluarea expresiilor aritmetice...........................................................................................79 .....................................................................................................................................................79 9.1.3. Evaluarea expresiilor logice................................................................................................79 9.1.4 Conversii explicite................................................................................................................80 9.1.5 Conversie de pointeri. Pointerul universal...........................................................................80 Cap 10 PREPROCESORUL................................................................................................................82 10.1 Directive preprocesor..............................................................................................................82 10.1.1 Constante simbolice. Directiva #define.............................................................................83 10.1.2 Includerea fişierelor...........................................................................................................83 10.1.3 Compilare condiţionată......................................................................................................84 10.1.4 Directiva #error..................................................................................................................85 10.2 Macroinstruţiuni.....................................................................................................................85 10.2.1 Macroinstrucţiuni predefinite.............................................................................................85 10.2.2 Macroinstrucţiuni tip funcţie..............................................................................................86 Cap 11 EXERCIŢII..............................................................................................................................87 BIBLIOGRAFIE..................................................................................................................................89 ANEXA.................................................................................................................................................90 Biblioteca standard C......................................................................................................................90 Codul ASCII....................................................................................................................................93

iii

sau “systems programming languages”. un limbaj bazat pe BCPL care a fost proiectat de asemenea de către Ken Thompson în 1970. Limbajele BCPL şi B sunt limbaje de nivel scăzut faţă de limbajul Pascal şi nici unul din ele nu este tipizat: toate datele sunt considerate cuvinte maşină încât. BCPL. operanzii flotanţi din expresii trebuiau precedaţi de punct. Limbajul a fost proiectat şi implementat de către Dennis Ritchie la Bell Laboratories în 1972. Problemele create în jurul limbajelor BCPL şi B au dus la dezvoltarea unui nou limbaj. considerat la început a proveni de la Cambridge. care la început s-a numit NB dar numele său a fost stabilit C. În una din implementările BCPL-ului. Asemănarea cu BCPL a fost mai degrabă semantică. Numele “C”. B şi Algol 68. restul operanzilor erau consideraţi întregi. este oficial din “Combined” dar neoficial se consideră a fi iniţiala pronumelui lui Cristopher Strachey. CPL a fost dezvoltat la Universităţile Cambridge şi London în anii 1960-1963. Proiectarea limbajului B a fost influienţată de limitele maşinii pe care a fost implementat: un PDP-7 cu capacitatea 4K ( cuvinte de 18 biţi). la Bell Laboratories în USA. BCPL a fost proiectat de Martin Richards în 1967 şi face parte din categoria “low-level languages”.1 1. sintaxa este total diferită.Cap 1 INTRODUCERE ÎN LIMBAJUL C 1. bazat pe B. În mare parte ( construcţiile for şi .2 1.3 Scurt istoric Forma unui program C Compilarea unui program C 1. cel care a condus echipa ce a proiectat CPL-ul. Ken Thomson a început proiectarea sistemului de operare Unix. Primul limbaj de nivel înalt implementat sub acest sistem de operare a fost limbajul B.1 Scurt istoric Strămoşii limbajului C sunt limbajele de programare CPL. În anii ’60. exemple simple de programe duc la complicaţii nebănuite.

•FORTRAN I (1957) •FORTRAN II (1958) •ALGOL 60 (1960) •ALGOL 68 (1968) •CPL (1963) •BCPL (1967) •B (1970) •C (1972) •C++ (1984) Figura 1. mare parte din implementările 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ă. Ada) cu gradul de control şi flexibilitatea oferite de către limbajul de asamblare. Unul din motivele pentru care limbajul C este în acelaşi timp agreat de mare parte din programatori şi dezagreat de altă mare parte din programatori. Odată cu creştere popularităţii calculatoarelor personale. Algol. Pentru eliminarea acestora în 1983 a fost creată o comisie care să stabilească un standard al acestui limbaj.1. Are de asemenea o mulţime bogată de operatori care-i dau un înalt grad de expresivitate. Ritchie a lucrat pe un calculator DEC PDP-11 sub sistemul de operare Unix. au apărut numeroase alte implementări ale limbajului C şi astfel a crescut şi popularitatea acestuia. unele din acestea au adăugate o serie de facilităţi sau extensii proprii care nu împiedică compilarea unui program standard. În ciuda acestui fapt . a octeţilor şi a adreselor de memorie. De altfel. Fortran. C permite manevrarea biţilor. Limbajul C are structuri de control adecvate precum şi facilităţi de structurare a datelor care îl fac să fie folosit într-o diversitate de domenii. Se înţelege că au existat şi neconcordanţe în multitudinea de “dialecte” ale limbajului. tratarea pointerilor etc. este lipsa totală a verificării tipului (type checking).1. Din acest motiv varianta clasică a limbajului C a fost asociată sistemului de operare Unix . toate compilatoarele C sunt compatibile cu standardul ANSI C.versiunea 5 şi multă vreme a constituit un standard (neoficial de altfel) al limbajului şKeR 78ţ. o variabilă de un tip scalar oarecare poate apare în aceeaşi expresie 5 . Firma Borland a folosit acest standard în faza de proiect şi a realizat implementările Turbo C care se bucură de un succes remarcabil.) limbajul a fost influienţat şi de Algol 68.doc switch.48627669. Limbajul C este privit ca un limbaj de nivel mediu întrucât combină cele mai reuşite elemente ale limbajelor de nivel înalt ( Pas-cal. în prezent . adică a elementelor de bază în funcţionarea unui calculator. Standardul ANSI ( American National Standard Institute) a fost redactat abia în decembrie 1989 şi a fost pus la dispoziţia celor interesaţi la începutul lui 1990. Modula. Genealogia limbajului C este prezentată în Figura 1. De exemplu. programele scrise în C au un grad mare de portabilitate: uşurinţa de a adapta programele scrise pentru o anumită categorie de calculatoare sau sisteme de operare la alte calculatoare sau sisteme de operare. Un fapt cu totul inedit a fost acela că.

proiect ce trebuia să realizeze distribuirea nucleului UNIX într-o reţea de computere conectate LAN. • C este un limbaj disponibil: un limbaj pentru care se poate găsi cu uşurinţă un compilator. şi a fost folosit pentru prima dată în Decembrie 1983. Algol 68 care a dat supraîncărcarea operatorilor. had a nice interpretation. cei care nu-l agrează îl consideră un limbaj lipsit de siguranţă. depending on context. care a adăugat 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). Bjarne Stroustrup a realizat în Octombrie 1979 un preprocesor. •Fortran(1956) •Algol 60(1960) •CPL(1963) 6 . Ada.>> În figura 1. Mesa.Iată ce spune Stroustrup despre această alegere: <<I picked C++ because it wos short. Originea acestui limbaj şSTR 94ţ trebuie căutată în proiectul care a început în Aprilie 1979 la “Computing Research Center of Bell Laboratories” în Murray Hill. Motivele pentru care a fost ales limbajul C (în faţa altor limbaje ale vremii: Modula-2. indiferent de ce calculator dispunem. “succesor” or “increment” . Datele care apar în paranteză se referă la prima implementare disponibilă pentru limbajul respectiv(după [STR 94]). be read as “next”. Pentru realizarea acestui proiect. prezintă etapele importante din proiectarea limbajului. limbajul a căpătat o mare popularitate în lumea academică şi nu numai. acesta oglindeşte conceptele fundamentale ale unui computer tradiţional. tough it is always pronounced “plus plus”. era vorba totuşi de un nou limbaj. este că datorită faptului că face parte din sistemul de operare Unix.2. În martie 1980 preprocesorul îmbunătăţit era implementat pe 16 sisteme iar limbajul acceptat de acesta a fost numit “C cu Clase”. Cei care agrează limbajul C îi apreciază flexibilitatea sa. Ceea ce este sigur. • C este un limbaj portabil: chiar dacă un program C nu este automat portabil de la o maşină la alta. ++ can. New Jersey. acest lucru este posibil în general fără un efort deosebit. 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 oricăror tehnici de programare. referinţele şi abilitatea de a declara variabile oriunde în cadrul unui bloc şi BCPL de unde a fost luată forma de prezentare a comentariilor cu //. Aşa cum vom vedea pe parcursul prezentării limbajului.Gheorghe GRIGORAŞ cu o variabilă de un alt tip scalar. chiar dacă era clădit pe C.3. este prezentată genealogia limbajului C++ iar figura 1. a apărut în 1984. and wasn’t of the form “adjective C”. Smalltalk. Numele C++ a fost sugerat de Rick Mascitti. Cele mai mari influienţe asupra noului limbaj le-au avut: Simula care a dat clasele. Asta pentru scurt timp însă deoarece comitetul ANSI pentru standardizarea C-ului a atras atenţia că se poate crea o confuzie cu această denumire. Compilatoarele oferite împreună cu sistemul Unix sunt relativ ieftine (uneori chiar gratuite) şi pot fi folosite pe o diversitate de maşini. un membru al echipei lui Stroustrup. USA. C++arm reprezintă “The Annotated C++ Reference Manual” iar C++std este standardul ANSI C++. • C este un limbaj eficient: semantica sa este “low level” ceea ce înseamnă că pot fi folosite cu eficienţă resursele hardware pentru programele C. In C++. După numele “ C cu clase” limbajul a fost “botezat” C84. numită C++. numit Cpre. O nouă versiune a limbajului C.

doc •BCPL(1967) •Simula 67(1969) •C •Algol 68(1977) •C cu Clase (1980) •Ada (1983) •ANSI C (1986) •C++ (1984) •ML(1976) •Clu(1978) •C++arm(1990) •C++std (1995) Figura 1.48627669. 1979 1980 1982 1983 1984 1985 1986 1987 1988 1990 1991 1992 1994 Mai Octombrie Aprilie Ianuarie August Decembrie Ianuarie Februarie Octombrie Septembrie Noiembrie Decembrie Ianuarie Iunie Martie Mai Mai Iunie Februarie Martie Mai August Începutul proiectului “C cu clase” Prima implementare a lui C cu clase Primul raport intern la Bell Labs asupra lui C cu clase Primul articol extern asupra lui C cu clase Prima implementare a limbajului C++ Limbajul a fost “botezat” C++ Primul manual C++ Prima lansare externă C++ Manualul The C++ Programming Language Prima conferinţă OOPSLA (centrată pe Smalltalk) Prima conferinţă USENIX C++ Prima lansare GNU C++ Prima implementare Oregon Software C++ Prima implementare Zortech C++ Prima reuniune tehnică ANSI X3J16 pentru C++ Prima implementare Borland C++ C++arm: The Annotated C++ Reference Manual Prima reuniune ISO WG21 Prima lansare DEC C++ Prima lansare Microsoft C++ Prima lansare IBM C++ A fost înregistrat Raportul Comitetului ANSI/ISO 7 .2.

do { rest = x%y. Trebuie reţinut faptul că orice program C conţine definiţia unei funcţii cu numele main care ţine locul programului 8 . 1. return 0. Metoda care se aplica pentru a determina cmmdc este urmatoarea: . . b este valoarea cautata. Urmează o linie ce începe cu #. primul limbaj de programare studiat (cel puţin până acum) a fost altul decât limbajul C. &raspuns). Aceste comentarii sunt incluse între "parantezele" “/*” şi “*/”. } Să trecem în revistă structura programului prezentat. Programul pe care l-am prezentat este constituit din două funcţii: main şi cmmdc. return x. In caz contrar. Vom începe prezentarea printr-un exemplu.daca acest rest este nul.h. } printf (" Cmmdc al celor doua numere este: %d\n".b)).se calculeaza restul impartirii intregi a lui a prin b.a = b. Primele linii din program constituie comentarii.3. &a. Pe această linie este o directivă care este gestionată de precompilator (preprocesor) şi permite includerea definiţiilor funcţiilor intrare/ieşire furnizate de sistem şi care se găsesc în fişierul stdio. la disciplina de informatică. se începe cu un limbaj diferit de C iar în învăţământul superior.2 Forma unui program C În general. scanf ("%c".Gheorghe GRIGORAŞ Figura 1. y = rest.cmmdc (a. Aceasta pentru că în programa de liceu. b capata valoarea restului si procedeul se repeta.h> int cmmdc (int x. x = y. char raspuns. la facultăţile care au în planul de învăţământ informatică şi chiar la cele de profil. mai ştie cel puţin un limbaj de programare (Pascal în cele mai multe cazuri). } while (raspuns!=’n’).b = c. printf (" Continuati ? d)a n)u -->"). &b). Programul 1 /* Calculul celui mai mare divizor comun (cmmdc) a doua numere intregi pozitive a si b. } int main (){ int a. } while (rest!=0). */ # include <stdio.b. a capata valoarea lui b. if (b>a) { int c = a. do { printf (" Introduceti 2 valori intregi pozitive -->"). scanf ("%d%d". int y){ int rest. cel care se apucă de învăţat limbajul C.

singura funcţie care trebuie să fie prezentă în orice program se numeşte main( ). Aceste funcţii vor fi prezentate mai târziu într-un capitol special. altele folosesc programul de legare al sistemului de operare.3 Compilarea unui program C Se ştie că există două metode generale de transformare a unui program sursă într-un program executabil: compilarea şi interpretarea. În limbajul C nu există instrucţiuni de intrare/ieşire. Standardul ANSI C precizează setul minimal de funcţii care va fi inclus în biblioteca standard. în esenţă. 2. )" care apare şi în funcţia main şi în funcţia cmmdc este una din structurile iterative de care dispune limbajul C: grupul de instrucţiuni cuprins între acoladele de după do se execută atâta timp cât condiţia scrisă după while este îndeplinită (de precizat că acel grup de instrucţiuni se execută măcar odată). care îndeplinesc funcţii distincte (figura 1. Prin urmare. Construcţia "do {. Majoritatea compilatoarelor C asigură medii de programare care includ facilităţi pentru realizarea tuturor etapelor precizate mai sus.). funcţia main( ) conţine. Aceasta este prima funcţie apelată la începutul executării programului. Dacă se foloseşte un compilator care nu are integrat un editor (cum sunt cele din sistemul de operare UNIX). Toate programele în C constau dintr-una sau mai multe funcţii. compilatoarele ce există pe piaţă conţin cu siguranţă şi alte funcţii. C a fost gândit de la bun început ca fiind destinat compilării. În corpul funcţiei main în Programul 1 avem apeluri la alte funcţii: printf. În exemplul de aici avem: printf cu un parametru aflat între ghilimele: acest text va fi tipărit pe ecran scanf cu trei parametri: "%d%d". Deşi au fost concepute şi interpretoare de C şi acestea sunt disponibile pentru diferite medii. Stiva este folosită în timpul execuţiei programului în scopurile: • memorează adresele de revenire ale apelurilor la funcţii. operaţiile de intrare/ieşire se realizează prin apel la funcţiile unei biblioteci standard furnizate de sistem.b)) este un apel la o operaţie de scriere (pe ecranul monitorului) a textului: cuprins între " şi " în afară de %dăn care reprezintă formatul cu care se va tipări valoarea returnată de apelul la funcţia cmmdc (a. cmmdc. Legarea programului cu funcţiile necesare existente în bibliotecă.4. Structurile de control ale limbajului C se vor prezenta într-un capitol special.doc principal: punctul de intrare în execuţia unui program C este funcţia main. Prima regiune este aceea care stochează codul programului. Celelalte două zone reprezintă aşa zisa stivă a programului şi zona de manevră. Limbajul C a fost optimizat special în vederea compilării. Un program C compilat creează şi foloseşte patru zone de memorie disjuncte.h. Procesul de legare (linking) este acela în care programul de legare(linker) combină codul scris de programator cu codul obiect al funcţiilor utilizate şi care se găseşte în bibliteca standard. scanf. printf ("Cmmdc al celor doua numere este: %dăn" cmmdc (a. Într-un program C corect conceput. 9 .} while ( . Atenţie însă: compilatoarele acceptă ca fişiere de intrare (programe sursă) numai fişiere text standard. schemă compusă din apeluri ale altor funcţii aflate în biblioteca standard a limbajului C sau definite de programator.. 1. iar &b adresa variabilei b. &b corespund adreselor (faptul că & apare în faţă) unde vor fi memorate cele două valori întregi: &a adresa variabilei a.Urmează o zonă de memorie în care sunt stocate variabilele globale. 3. Unele compilatoare au programul propriu de legare.48627669. Corpul unei funcţii este delimitat de acolade: ‘{’ ţine locul lui begin (dinalte limbaje) iar ‘}’ al lui end. Definiţiile acestor funcţii se află în fişierul sistemului stdio. Acesta este un apel la o operaţie de citire a unor date pe care le introducem de la tastatură. o schemă a ceea ce face programul.b): va fi scris un număr întreg (%d) după care se trece la linie nouă (caracterul ăn). Parametrul "%d%d" specifică formatul de citire a două numere întregi (d de la digit) iar parametrii &a. Crearea programului. &a şi %b. atunci trebuie folosit un editor pentru crearea fişierului sursă C.. dacă se crează un fişier sursă cu editorul Word su Windows. Crearea unui format executabil al unui program C parcurge următoarele trei etape: 1. acesta trebuie salvat ca fişier text pentru a putea fi utilizat de un compilator. Compilarea programului.

care a fost concepută pentru programarea orientată pe obiecte. 2. că în general. memorează starea curentă a unităşii centrale de prelucrare. programarea în limbajul C va dăinui multă vreme de acum încolo. un programator care nu ştie C nu va putea programa în C++.4. aşa cum dăinuie de când a fost creat limbajul şi. expresii 2. Zona de manevră (heap) este o regiune de memorie liberă pe care programul . memorează variabilele locale.2. le foloseşte pentru stocarea unor articole de genul listelor înlănţuite şi arborilor. operatori. în încheierea acestei scurte introduceri . Cap 2 Tipuri. 2. STIVA ZONA DE MANEVRĂ VARIABILE GLOBALE CODUL PROGRAMULUI Figura 1. compilatoarele existente pe piaţă. 10 Tipuri simple Literali Declararea unei variabile Operatori . prin intermediul funcţiilor de alocare dinamică ale limbajului C. 2. C++ este o versiune extinsă a limbajului C. Să mai precizăm .Gheorghe GRIGORAŞ • • • memorează argumentele funcţiilor.4.3.1. De aceea C++ acceptă limbajul C: orice program C va putea fi compilat de un compilator C++.După unii autori. Aşa cum vom vedea în partea a doua a acestei cărţi. sunt compilatoare C++.

Tipurile de bază ale limbajului C pot fi grupate în trei mulţimi: • Tipuri întregi: char. Limbajul C oferă de asemenea un mecanism de conversie a tipului care va fi prezentat mai târziu în lucrare. 4294967295 2.. nume de constante (literali). short. 255 0 . Pentru tipurile întregi se pot folosi specificările signed şi unsigned.32768.127 short .iar double pentru numere reale în dublă precizie – aproximativ 15 cifre semnificative. au un anume tip iar în funcţie de aceste tipuri se vor aplica algoritmi specifici pentru determinarea valorii expresiei. Este un tip folosit pentru reprezentări de dimensiune nulă. Aceste tipuri sunt utilizate pentru reprezentarea numerelor întregi. double Aceste tipuri sunt folosite pentru a reprezenta numere reale.32768. Tabela 1.48627669. • Tipul vid: void. Diferenîa dintre acestea constă în dimensiunea zonei de memorie ocupată de o variabilă de acest tip şi implicit de mărimea domeniului de valori.. Operanzii într-o expresie sunt nume de variabile..... int şi long.32767 int .1. Acest lucru este sintetizat în Tabela 1. Tipuri simple 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 conţinutul acestei zone. 65535 0 . Tabela 2..2. 65535 0 .32767 long -2147483648. Literali 11 . Ele se disting prin precizia de reprezentare: float – numere reale în simplă precizie –aproximativ 6 cifre semnificative . Aceşti operanzi.doc O expresie în limbajul C – ca în orice limbaj de programare – este o secvenţă de operatori şi operanzi care descrie algoritmul de calcul al unei valori. Tipurile întregi Tipul Dimensiunea memoriei ocupate 8 biţi 16 biţi 16 biţi 32 biţi Domeniul char .128. 2. (long int) 2147483647 • Tipuri reale: float. Specificarea signed tip este echi-valentă cu tip iar unsigned tip are semnificaţia din Tabela 2. apeluri la funcţii.. fiecare dintre ei.. Tipuri întregi unsigned Tipul unsigned char unsigned short unsigned (int) unsigned long (int) Dimensiunea 8 biţi 16 biţi 16 biţi 32 biţi Domeniul 0 .

14159. ‘A’.primul caracter este literă sau ‘_’ (underscore). Declararea unei variabile şi a unei constante Toate variabilele unui program trebuiesc declarate înainte de a fi utilizate. O3724 ox7F. Acestea sunt: ‘\n’ .3.caracterul NULL. ‘\b’ .retur de car. A24E 39u. OX3.tabulare. . ‘^’ şir “şir de caractere” Explicaţii Notaţia zecimală Notaţia octală (prefix O) Notaţie hexazecimală (prefix ox sau OX) Constante fără semn Reprezentare pe 32 biţi Constante fără semn pe 32 biţi Reprezentare fără exponent Reprezentare cu exponent Există şi caractere speciale (de control) care sunt compuse din caracterul “\” şi din alt caracter. în limbajul C se folosesc diferite reguli sintactice pentru reprezentarea constantelor. ‘\f’ .caracter de cod hexazecimal hh. ‘\xhh’ . 10e-12 caracter ‘a’. -457. o245u.tabulare verticală.caracterul ‘’’ ‘\”’ . Un identificator în limbajul C este un şir de caractere care trebuie să îndeplinească condiţiile: . Tabela 3 sintetizează unele din aceste reguli. o42l long 423uL. ‘\u’ . Cuvintele cheie ale limbajelor C şi C^^ asm auto break case catch char class const continue default 12 delete do double else enum extern float for friend goto handle if inline int long new operator overload private protected public register return short signed sizeof static struct switch template this throw try typedef union unsigned virtual void volatile while . 0 O12. ‘\\’ . 2. ‘\o’ .caracterul \ (backslash). .Gheorghe GRIGORAŞ Literalii (sau constantele literale) sunt valori constante.interlinie (linie nouă).caracter de cod octal ddd.03. ‘\ddd’ . -12.2E^3. Constante literale Constante Exemple întregi 123. ‘\r’ .Nu trebuie să coincidă cu vreun cuvânt cheie (vezi Tabela 4) Tabela 4. ‘\t’ .retur de linie. Variabilele sunt obiectele de bază ale limbajului şi au un nume care este un identificator. ele reprezintă valori care nu pot fi modificate pe parcursul execuţiei unui program. . Tabela 3. ^423. 42153l.backspace.caracterul ”. ‘\’’ . 25AfuL flotant 3.următoarele caractere sunt caractere alfanumerice (litere sau cifre) sau ‘_’. 57F3u întregi 12L.425 -15.

O constantă se declară prin: const tip nume= valoare. Tabelul 5. Variabilele din clasele auto şi register nu îşi păstrează valoarea de la un apel la altul al funcţiei în care sunt definite. Dacă se definesc în interiorul unei funcţii trebuie să aibă neapărat în faţă cuvântul rezervat static (se mai spune că sunt în clasa static internal). tip nume = valoare.14159. const float pi = 3.14159.doc O variabilă se declară prin una din următoarele instrucţiuni: tip nume.48627669. Register Static internal External Static external External (în funcţie) . explicit se poate specifica prin cuvântul cheie aut: aut int x. Exemple: int i. dacă e posibil. j. const double e = 2. Clase de alocare CLASA CARACTERISTICI Adre Păstrează Vizibilitate să valoarea fixă în interiorul funcţiei NU NU în interiorul funcţiei în toate modulele în modulul în care-i definită în toate modulele aplicaţiei DA DA DA DA DA DA DA Durata de viaţă Pe durata funcţiei Pe durata aplicaţiei Pe durata aplicaţiei Pe durata aplicaţiei 13 Auto. Variabilele se declară la începutul funcţiilor (variabile locale) sau în exteriorul tuturor funcţiilor (variabile globale). Variabilele din clasa static diferă de cele din clasa auto sau register prin aceea că sunt memorate în locaţii fixe de memorie (au o adresă fixă. Variabilele din clasa automatic sunt definite în interiorul funcţiilor fiind locale funcţiei în care au fost definite. într-o declaraţie se specifică clasa de alocare (implicit sau explicit). k.71828182845905. Variabilele definite în exteriorul tuturor funcţiilor fără vreun specificator de clasă sunt în clasa extern şi au alocate adrese fixe. char n1='\n'. Această clasă este implicită. având durata de viaţă pe parcursul execuţiei funcţiei. pi = 3. float eps = 1. Tabelul 5 sintetizează clasele de alocare. despărţite prin virgule. alocarea se face în registrele unităţii centrale şi nu în memoria RAM. Mai multe variabile de acelaşi tip pot fi declarate în aceeaşi instrucţiune. Tot în interiorul unei funcţii variabilele mai pot fi definite şi în clasa register care este asemănătoare cu cea automatic cu deosebirea că. const char mesaj[ ] = "Eroare".e-4. permanentă). în afară de tipul variabilei şi eventual o valoare iniţială pentru aceasta. Clasele principale de alocare sunt automatic şi static.

se aplică conversii implicite de tip: unul din operanzi se converteşte la tipul celuilalt iar tipul rezultatului va fi tipul comun. 2.45. Fiecare dintre aceştia au un tip declarat. Aceştia pot fi unari sau binari iar în privinţa asociativităţii. Negaţia are semnificaţia obişnuită: schimbă semnul valorii expresiei în faţa căreia se află.4. Operatorii ++ şi -. ++ autoincrementarea. operatori unari cu notaţie prefixată sau postfixată: -x. x++. operatorul ternar condiţional operand 1 ? operand 2 : operand 3. asociativitatea este de la dreapta la stânga. De pildă expresiile x * y +z şi x * (y + z) vor fi evaluate diferit pentru aceleaşi valori ale variabilelor. Am văzut că operanzii pot fi variabile. atunci: j = i ++ /* j = 10 apoi i = 10 */ k = ++i/* i = 12 apoi k = 12 */ l = i-. • Operatorii unari: +. • postfixaţi: variabila este incrementată (decrementată) după evaluarea expresiei în care se află iar asociativitatea este de la stânga la dreapta.plus şi minus unari.Gheorghe GRIGORAŞ Static în toate modulele DA External aplicaţiei (în funcţie) În capitolul al optulea sunt tratate mai în amănunt problemele legate de gestiunea memoriei. aceasta este de la stânga la dreapta. k. (x + y) * z../* l = 12 apoi i = 11 */ 14 . Exemplu: x+y x % y. j.45 Dacă operanzii au tipuri diferite .incrementează (decrementează) cu 1 valoarea unei variabile şi pot fi : • prefixaţi: variabila este incrementată (decrementată) înainte de evaluarea expresiei în care se află iar asociativitatea este de la dreapta la stânga.4. float beta = 25. ++x. Evaluarea expresiilor se face înlocuind operanzii prin valorile sale şi efectuînd operaţiile conform cu specificaţiile acestora. Dacă tipul operanzilor este acelaşi într-o expresie.45 + 5.0 20. atunci evaluarea expresiei: alpha + sqrt (beta).se face în ordinea indicată mai jos: alpha + sqrt (25) alpha + 5. • • • • 2. constante sau apeluri la funcţii (despre care se va vorbi mai târziu). Operatori Operatorii se folosesc la constituirea de expresii pornind de la constante şi variabile.1. Exemple: Fie declaraţia int i = 10. l. ca şi perechea: x+y*z . m. aceştia delimitează subexpresii şi pot schimba asociativitatea operatorilor. Operatori aritmetici Operatorii aritmetici sunt aceea care se aplică operanzilor numerici. -autodecrementarea. Operatorii ce pot apare într-un program C sunt de patru feluri: operatori primari de parantetizare. operatori binari cu notaţie infixată adică: operand operator operand. Spre exemplu. acolo unde nu este specificat altfel.0 25. y--. evaluarea se face în mod natural. dacă se declară: float alpha = 20.

deplasare la dreapta.funcţia de ridicare la putere pow.prezentate în Anexa – care sunt operatori cu scriere prefixată: . .4. 2.disjuncţie logică la nivel de bit. short. y a = (x! = y). ^) este cea naturală (aminitm că 1 reprezintă valoarea logică “adevărat” iar 0 valoarea “fals”). logaritmică etc.48627669.funcţiile exponenţială. Exemplele următoare sunt edificatoare.disjuncţia logică (sau) && . 2. Aceştia se pot aplica doar operanzilor de tip întreg (char. iar dacă unul din ei are valoarea fals (0) atunci expresia are valoarea zero. în secvenţa anterioară. cos.3.conjuncţia logică (şi) Expresia: • op1&&op2 are valoarea adevărat (1) dacă cei doi operanzi sunt evaluaţi la adevărat. Aceştia sunt operatori binari iar sintaxa lor în C este: < (mai mic) <= (mai mic sau egal) > (mai mare) >= (mai mare sau egal) == (egal) != (diferit) Cum rezultatul unei comparări este un număr întreg este posibilă asignarea acestuia unei variabile întregi: int a. >> . |.4. asin. • !op1 are valoarea fals dacă op1 este adevărat şi are valoarea adevărat dacă op1 este fals.conjuncţie logică la nivel de bit.2. long) şi servesc la poziţionarea sau interpretarea valorilor întregi ca o secvenţă de valori binare. x.4. Operatori logici Operatorii logici sunt operatori binari care se aplică unor operanzi ce au valori adevărat (1) sau fals (0) şi ei corespund operaţiilor logice uzuale: ! .4. ~ . ^ .doc m = --i /* i = 10 apoi m = 10 */ • Operatorii binari sunt următorii + adunare * înmulţire scădere / împărţire % modulo La aceşti operatori se adaugă funcţiile din biblioteca matematică . Aceşti operatori sunt: & . acos.negare la nivel de bit (operator unar). Operatorii relaţionali (de comparaţie) Operatorii relaţionali sunt operatori binari şi permit compararea valorilor a doi operanzi (expresii) iar rezultatul evaluării este zero (dacă rezultatul este fals) sau 1 (dacă rezultatul este adevărat).sau exclusiv la nivel de bit.funcţiile trigonometrice uzuale: sin. • op1 op2 are valoarea zero (fals) dacă i numai dacă op1 şi op2 au ambii valoareea zero (fals). << . .negaţia logică cu asociativitate de la dreapta la stânga  .deplasare la stânga. tan.  . dacă x va fi egal cu y atunci a va căpăta valoarea 0 iar în caz contrar a va căpăta valoarea 1. Semnificaţia primilor trei operatori binari (&. Operatori la nivel de bit Limbajul C dispune de şase operatori pentru tratarea informaţiei la nivel de bit. int. atan. 15 . 2.

4) z = 0000 0000 0000 0011(= 13/4) 2. k. >>= Faptul că atribuirea este privită ca un operator binar. y = x << 2. *=. /=. Această asignare este echivalentă cu : e1 = (e1) op (e2). variabila = expresie. Exemple: x = 13. %= • Operatori logici la nivel de bit: &=. exprimat prin =.. ~ op1 = 10011011 Operatorii binari de decalare ( << şi >>) servesc la decalarea cu un anumit număr de biţi (dat de cel de-al doilea operand) la stânga sau la dreapta în cadrul primului operand. = varn = expresie..4. unde e1 şi e2 sunt expresii. Acest lucru permite “atribuirea în lanţ”precizând că asociativitatea operatorului de asignare este de la dreapta la stânga: var1 = var2 = . Astfel variabilă = expresie. are ca efect evaluarea expresiei din dreapta semnului = şi atribuirea acestei valori variabilei ce se află în stânga acestui semn. ^= • Operatori de decalare: <<=. Spre exemplu i = j = k = l = 1. prin care cele n variabile capătă valoarea expresiei din partea dreaptă. x = 0000 0000 0000 1101 (= 13) y = 0000 0000 0011 0100 (= 13. j. Se obţin asignări compuse cu: • Operatori aritmetici: +=. este o expresie ce are ca valoare. prin aceasta cele patru variabile i. permite ca aceştia să formeze expresii care au atribuite valori. Pe lângă acest tip de asignare. limbajul C permite compunerea asignării (#) cu un operator binar (op) obţinându-se operatori de asignare compusă: e1 op = e2. -=. în particular se poate obţine (rapid!) înmulţirea cu 2op2 (op1 << op2) sau cu 2-op2 (op1 >> op2). l capătă valoarea 1. 16 . valoarea expresiei din dreapta semnului # . este o construcţie validă în C.5. z = x >> 2. Operatorul de asignare Operatorul de asignare.Gheorghe GRIGORAŞ op1 =01100100 op2 =10111010 op1 & op2 = 00100000 op1 | op2 = 11111110 op1 ^ op2 = 11011110 De asemenea negaţia (~) acţionează la nivelul fiecărui bit schimbând 1 =n 0 şi 0 =n 1. |=.

8. minus unari Acces la o variabilă Descrierea 17 .4.4. Precedenţa operatorilor limbajului C este dată în tabelul nr. i < j..op2.op3 sunt operanzi.6. Operatorul condiţional se notează cu ?: şi are asociativitatea de la dreapta la stânga. else max = b. Exemplu: max = (a > b) ? a : b.7. decrementare Negare pe biţi Negare logică Plus.. 2.48627669. * Funcţia (semnificaţia) Acces explicit la o variabilă globală (unar) Acces explicit la o clasă (binar) Selectarea unui membru Indexarea unui tablou Apel la o funcţie Lungimea în biţi Incrementare. Precedenţa operatorilor Asociativitatea şi precedenţa operatorilor indică ordinea în care se evaluează subexpresiile într-o expresie.expresie2. Operatorul condiţional Acesta este singurul operator ternar al limbajului C. . Forma generală a sa este: op1 ? op2 : op3. expresia este egală cu op3. Dacă op1 are valoarea adevărat. este o expresie echivalentă cu construcţia: if (a > b) max = a. . . Operatorul virgulă Forma generală a unei expresii ce utilizează acest operator este: expresie1.4. Pentru limbajul C. ~ ! +.j = 0. 6. j--) 2. i < 100.j = n-1. operatorilor unari. unde op1. i++. j++) for(i = 0. Tabelul nr. i++. se înţelege) expresiei ultime ce apare în acest şir. Expresiile sunt evaluate de la stânga la dreapta iar valoarea întregii expresii este valoarea (şi tipul. Am văzut că operatorii primari de parantetizare pot schimba asociativitatea operatorilor. [] () sizeof -> . expresia este egală cu op2 iar dacă op1 are valoarea fals.6. O asemenea construcţie apare frecvent în instrucţiuni for pentru realizarea mai multor acţiuni: for(i = 0.doc 2. Operator :: :: →. operatorul condiţional şi cel de atribuire li se aplică asociativitatea la dreapta pe când tuturor celorlalţi li se aplică asociativitatea la stânga.

|= . >>= &=.Gheorghe GRIGORAŞ & () new.>> . %= +=. ^=. % +.<=. >= ==.*=.delete ->* . != & ^ | && || ?: =. <<=. . >. << <.* *. /. Adresa unei variabile Conversie de tip (cast) Operatori de gestiune a memoriei Selectarea unui membru Operatori multiplicativi Operatori aritmetici Operatori de decalare Operatori relaţionali Egalitate. -=./=. inegalitate Conjuncţie pe bit Sau exclusiv pe bit Sau (disjunctiv) pe bit Conjuncţie logică Disjuncţie logică Afectare condiţională Operatori de asignare compusă Operatorul virgulă 18 .

funcţii ce se găsesc în bibliotecile sistemului. 3.descompunerea unei secvenţe lungi de procesare a informaţiei într-o mulţime de secvenţe “mici” de transformări de bază ale informaţiei.furnizarea către alţi programatori a unor elemente de bază de nivel înalt. În general.modificări ulterioare ale acestuia. o funcţie trebuie declarată înainte de a fi apelată.3. Mulţimea funcţiilor unui program poate fi partiţionată în mai multe fişiere care pot fi compilate separat.Cap 3 FUNCTII 3.2. } În această definiţie. tip este unul din cuvintele rezervate care defineşte tipul funcţiei. Signatura unei .1. 3.). Limbajul C permite de asemenea utilizarea unor funcţii predefinite (printf. Aceste elemente de nivel înalt oferă o claritate în plus programului global şi permite . Definirea unei funcţii Definiţia unei funcţii are următoarea sintaxă: tip nume (lista parametri) { declaratii (de variabile). Aşa cum o variabilă trebuie declarată înainte de a fi utilizată într-o expresie.1.4. . detaliile acestor elemente rămân “ascunse” pentru utilizator.5. tipul implicit al funcţiei este int. Funcţiile care returnează în programul apelant valoarea vidă se declară de tip void. Să precizăm că nu se poate defini o funcţie în interiorul altei funcţii. 3. 3. respectiv tipul valorii returnate de un apel la această funcţie. Declararea unei funcţii constă în a da signatura funcţiei. 3. Dacă această specificare lipseşte. Este posibilă definirea de funcţii care să retuneze valoarea vidă: în acest caz tipul valorii returnate este void. Apelurile la aceste funcţii sunt gestionate în faza de editare a legăturilor. 3. Definirea unei funcţii Returnarea unui apel Funcţii cu un număr variabil de parametri Sfârşitul execuţiei unui program Apelul şi transmiterea parametrilor Funcţia principală main În limbajul C . În C există doar funcţii care returnează o valoare. Numele unei funcţii este un identificator şi acesta trebuie să respecte aceleaşi reguli ca cele referitoare la numele unei variabile. instructiuni. getc. utilizarea unei funcţii permite: .6. etc.relativ uşor .nu există noţiunile distincte de procedură şi de funcţie.spre deosebire de Pascal sau alte limbaje .

int strlen (const char* s).4. .implicit: în definiţia funcţiei. Definirea unor astfel de funcţii se face printr-o sintaxă de forma: int printf (char *. Funcţia "exit" este o funcţie sistem care termină execuţia unui program.3.x).Gheorghe GRIGORAŞ funcţii defineşte atât tipul său (tipul valorii returnabile) cât şi numărul şi tipul argumentelor sale. scanf. 3. Returnarea unui apel Sintaxa instrucţiunii de returnare a valorii unei funcţii este: return expresie. Sfârşitul execuţiei unui program exit (valoare). O funcţie f returnează o valoare în corpul funcţiei din care s-a făcut apel la f. int funct ( ). Un exemplu la îndemână îl oferă funcţiile sistemului: printf. Acesta este singurul exemplu de apel la o funcţie care nu returnează nimic: sistemul opreşte execuţia programului şi raportează valoarea transmisă la apel. printf("x\%f\n". linia de început conţine tipul său şi argumentele sale (număr şi tip). care în C++ se numeşte "elipsă".b\%d\n". Iată câteva instrucţiuni de declarare a unei funcţii: long int cod (const char *... Funcţii cu un număr variabil de parametri Există funcţii care pot avea un număr nedeterminat de parametri. /*3 argumente */. void schimbare (int . prin instrucţiunea return (plasată în corpul lui f). int). 3. ).b). 3. În ultima linie avem un exemplu de funcţie fără parametri (numărul parametrilor este zero).a. Această valoare poate fi utilă atunci când programul este executat în interiorul 20 . etc.2. int).explicit: printr-o instrucţiune ce descrie signatura sa în cazul în care se face apel la o funcţie descrisă într-un fişier separat sau în cazul în care apelul la funcţia respectivă precede declaraţia funcţiei în acelaşi fişier. char* decod (long int).: printf ("Un apel cu un singur argument \n"). Există două moduri de a declara o funcţie: . O funcţie care returnează valoarea vidă (funcţie de tip void) poate conţine instrucţiunea "return" fără argument sau poate omite această instrucţiune. Valoarea expresiei "expresie" va fi returnată şi poate fi utilizată în programul apelant./*Un apel cu 2 argumente */ printf ("a\%d. Tipul acestei expresii trebuie să fie acelaşi cu tipul funcţiei. .

int y){ int temp = x.b). printf ("%d %d \n". 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. tipăreşte (cu unele compilatoare) 10 10 şi nu 10 11. *y = temp. secvenţa: int n = 10. Singura diferenţă este că valoarea transmisă prin parametrii actuali &a. Pentru înlăturarea acestui efect este posibilă simularea unui mod de transmitere prin referinţă. b = 2. Apelul şi transmiterea parametrilor Apelul unei funcţii se face prin: nume (listă _ parametri_actuali). schimba1(a. Să facem precizarea că şi în cazul funcţiei schimba2 transmiterea parametrilor se face prin valoare: am simulat aici transferul prin referinţă ce ar fi trebuit să se facă în cazul funcţiei schimba1. } iar apelul în funcţia main se face prin: schimba2 (&a . Prin convenţie. *x = *y.&b este adresa lui a respectiv b şi prin funcţia schimba2 se modifică valorile referenţiate. punând drept parametri actuali valorile adreselor variabilelor ce trebuiesc modificate. int* y){ int temp = *x. n). Să precizăm că în C nu există decât un singur mod de transmitere a parametrilor şi anume transmiterea prin valoare. } Apelul funcţiei schimba1 în funcţia main nu are efectul scontat: prin apelul la printf se tipăresc valorile 1 şi 2 pentru a respectiv b. În C adresa unei variabile poate fi specificată într-o variabilă de tip "pointer" (de care vom vorbi mai târziu). dacă funcţia este declarată fără tip şi prin folosirea numelui funcţiei urmat de lista de parametri actuali într-o expresie (în care este permis tipul ei) atunci când funcţia este declarată cu tip . 3. Aşadar. y â temp. a. n++. pentru schimbarea conţinutului unor variabile 21 . încât trebuiesc luate măsurile corespunzătoare. &b). Asta înseamnă că parametrul actual (de la apel) şi parametrul formal corespunzător (declarat în antetul funcţiei) sunt două variabile distincte. b =%d". x = y. } main ( ){ int a = 1.5. Ordinea evaluării parametrilor este în general de la stânga la dreapta dar acest lucru nu este garantat de orice compilator. printf ("a = %d.48627669. În absenţa unei instrucţiuni exit. Funcţia schimba2 care simulează transmiterea parametrilor prin referinţă este: void schimba2(int* x .doc unei linii de comandă a interpretorului de comenzi. valoarea implicită a codului returnat la sfârşitul execuţiei unui program este 0. Asta înseamnă că o funcţie nu poate modifica parametrii actuali. Un exemplu clasic al consecinţei acestui mod de transfer al parametrilor este ilustrat mai jos: void schimba1(int x. Modificările efectuate asupra parametrilor formali nu au decât un efect local care nu este vizibil în afara funcţiei. De pildă. b)..

linia de comandă conţine numele programului urmat de o listă de parametri: nume-program p1.argv: un tablou de pointeri către fiecare din argumentele liniei de comandă. În cazul în care programatorul nu doreşte să utilizeze argumentele (parametrii) transmise la execuţie. } Funcţia main este singura funcţie absolut necesară într-un program C. este permisă utilizarea funcţiei main fără parametri: int main( ) este o declaraţie validă pentru funcţia main. . p2. . Aceasta defineşte punctul de intrare în execuţia programului.char* argv [ ]) { instructiuni.argc: numărul argumentelor din linia de comandă (inclusiv numele programului). char* argv[ ] ){ if (argc<2) printf ("Nu exista argumente in aceasta executie ! \n"). Valoarea întreagă returnată de funcţia main este valoarea transmisă mediului la sfârşitul execuţiei programului (vezi funcţia exit). Parametrii funcţiei main permit recuperarea argumentelor transmise din momentul execuţiei programului. arg[0] conţine numele programului executabil.7) precum şi pentru limitarea numărului de valori ce trebuiesc puse în stiva de apel a execuţiei unui program. 1. la lansarea unui program. “nume . else { printf ("Argumentele executiei sunt: \n").6. Argumentele de tip pointer vor fi utilizate de asemenea pentru transmiterea ca parametru a unei variabile de tip structură (vezi Cap. i++) printf ("%s". În capitolul 6 vom discuta mai pe larg modul de transmitere al parametrilor de tip tablou ca argumente ale unei funcţii.. în particular. În general.succes.program” “p1” “pn” 0 n Iată un exemplu de utilizare a acestor argumente : Programul 2 main (int argc. i < argc. 3. parametrul corespunzător trebuie să fie de tip pointer.eroare).. for (i â 1. Utilizarea instrucţiunii return precizează condiţia de terminare ( 0 .. } } Dacă acest program are numele prg2 atunci linia de comandă: prg2 22 . argv [i] ). pn Atunci argc va avea valoarea n^1 iar argv va fi un tablou ce conţine pointeri astfel: 0 1 : . Parametrii disponibili la apelul funcţiei main sunt: . Funcţia principală main int main(int argc.Gheorghe GRIGORAŞ printr-o funcţie.

doc produce scrierea mesajului: Nu exista argumente in aceasta executie ! iar linia de comandă: prg2 Iata niste argumente ! produce scrierea mesajului: Iata niste argumente 23 .48627669.

1 4.. poziţie curentă etc). imprimanta. Aşadar dispozitivul fizic pe care se scriu datele se numeşte fişier iar abstractizarea acestuia se numeşte flux (sau stream). încât aceeaşi funcţie care scrie date pe un fişier de pe disc poate fi folosită pentru a scrie date pe o altă categorie de dispozitive: consola. stare.! Cap 4 FUNCŢII DE INTRARE IEŞIRE 4. Un flux se poate asocia unui fişier executând o operaţie de deschidere: odată deschis.h> Orice program C începe execuţia prin deschiderea unităţilor de intrare/ieşire standard: stdin : unitatea standard de intrare stdout : unitatea standard de ie[ire stderr : unitatea de eroare stdprn : unitatea standard de ie[ire (imprimant\) prn . inclusiv cu terminale. unităţi de disc sau de bandă etc.Fluxuri şi fişiere Sistemul de fişiere al limbajului C este conceput pentru a lucra cu o mare varietate de dispozitive. o imprimantă sau “o zonă” (fişier) pe disc. Un pointer de fişier este un pointer către informaţia care defineşte diverse caracteristici ale unui fişier(nume. Există două tipuri de fluxuri: • Fluxul text este o scvenţă de caractere.2 4. Datorită posibilelor conversii s-ar putea ca numărul de caractere scrise/citite să difere de numărul de caractere existente pe dispozitivul extern. # include <stdio. Tipul FILE Funcţii de intrare /ieşire pentru caractere Scrierea cu format Citirea cu format 4. sistemul de fişiere le transformă pe fiecare într-un dispozitiv logic numit flux. Deşi fiecare dintre acestea este foarte diferit de celelalte. Acesta din urmă este opţional pe ultima linie şi este determinat de modul de implementare. • Fluxul binar este o secvenţă de octeţi cu corespondenţă biunivocă faţă de octeţii existenţi pe dispozitivul extern: numărul de octeţi scrişi/citiţi este acelaşi cu numărul acestora de pe dispozitivul extern. Pentru a putea utiliza într-un program funcţiile standard de intrare/ieşire trebuie scrisă la începutul acestui program o directivă "include" care are ca argument numele fişierului antet ce conţine definiţiile acestor funcţii: stdio.4 4.5 Fluxuri şi fişiere Accesul la fişiere. Pointerul de fişier identifică un anumit fişier şi este folosit de către fluxul asociat pentru a conduce operaţia de intrare/ieşire. Fluxurile sunt independente de dispozitivele iniţiale . Unificarea sistemului de intrare/ieşire în C se face prin “pointerii” de fişier. Un fişier în limbajul C poate fi un terminal. Standardul ANSI C permite organizarea unui flux text în linii care se încheie cu un caracter linie nouă(“ăn”).3 4. pot avea loc transferuri de informaţii între fişier şi programul curent în execuţie.1.h .

stdout) pot fi orientate şi către alte dispozitive sau fişiere. Tipul FILE Conceptul de bază pentru intrări/ieşiri standard este cel de pointer la fişier. Bibliotecile standard C oferă o serie de funcţii pentru operaţii de intrare/ieşire orientate pe fişiere. Deschiderea unui fişier se face prin funcţia fopen care returnează ca rezultat un pointer la un descriptor de fişier.48627669. Aceste fişiere (stdin. în lipsa altor indicaţii.h şi are forma: FILE* pointer_la_fi[ier unde pointer_la_fişier este un identificator (numele pointerului). tastaturii calculatorului (intrare) şi ecranului (ieşire şi eroare).doc Aceste unităţi standard sunt asociate. Declararea unei variabile de tip "pointer la fişier" se face folosind tipul FILE definit în fişierul antet stdio. FILE* fopen(const char* fi[ier. Acest dispozitiv este gestionat de sistem pentru a asigura intrările şi ieşirile efectuate în program.const char* mod) 25 . Accesul la fişiere. Dispozitivele standard de intrare (tastatura) şi de ieşire (ecranul) sunt văzute tot ca fişiere cu pointerii stdin şi stdout. Sistemul de fişiere ANSI C este compus din mai multe funcţii legate una de alta.1. Tabelul 5 NUME fopen( ) fclose( ) putc( ) fputc( ) puts( ) fputs( ) getc( ) fgetc( ) gets( ) fgets( ) fseek( ) printf( ) fprintf( ) scanf( ) fscanf( ) feof( ) ferror( ) rewind( ) remove( ) fflush( ) OPERA}IE Deschide un fişier Închide un fişier Scrie un caracter într-un fişier Analog lui putc() Scrie un şir pe ecran Scrie un şir pe fişier Citeşte un caracter dintr-un fişier Analog lui getc( ) Citeşte un şir de la tastatură Citeşte un şir din fişier Caută un anumit octet într-un fişier Scrie la ieşirea standard Analogul pentru fişiere al funcţiei printf( ) Citeşte din intrarea standard Analogul pentru fişiere al funcţiei scanf( ) Returnează “adevărat” dacă se atinge sfărşitul fişierului Returnează “adevărat” dacă survine o eroare Iniţializează indicatorul de poziţie al fişierului la început Şterge un fişier Goleşte conţinutul unui fişier 4. Cele mai frecvent folosite dintre acestea sunt date în Tabelul 5 şi vor fi prezentate în continuare.

if(freopen("iesire. fişier este un şir de caractere (identificator) ce desemnează numele extern al fişierului iar mod este un şir de caractere ce descrie modul de deschidere al fişierului. if (freopen ("CON". aceasta indică faptul că deschiderea s-a efectuat corect.Gheorghe GRIGORAŞ Aici. valoare ce va fi utilizată în apelul la funcţiile de intrare/ieşire. FILE* pointer_la_fi[ier cod = fclose (pointer_la_fi[ier) Fişierele pot fi reasignate prin program folosind funcţia freopen: FILE* freopen (const char* nume_fisier. Apelul la fclose se poate face prin: int cod.dat \n"). Acest lucru poate fi folosit pentru tratarea erorilor la deschiderea fişierului. Programul 3 # include <stdio. se actualizează fişierul pe disc şi încetează conexiunea logică între pointer şi fişier. } printf ("Mesaj scris in fisierul iesire. "Eroare la reasignare \n"). Tabelul 6. exit (1). fclose (stdout)."w+". "wt". Închiderea unui fişier se face prin apelul la funcţia fclose: int fclose (FILE* pointer_la_fi[ier) Funcţia returnează EOF în caz de eroare şi 0 în caz normal. atribuind pointerul "pf" la acest fişier. Prin închidere se eliberează descriptorul de fişier. Aceasta permite redirecţiona-rea dispozitivelor periferice prin program. Valoarea returnată este un pointer la un descriptor de fişier valid. mod "r" "w" "a" "r+" "w+" "a+" Semnificaţia Citire Creare (schimbare) pentru scriere Adăugare la sfârşitul fişierului (existent) Actualizare (citire/scriere) Schimbare pentru actualizare Actualizare cu scriere la sfârşitul fişierului (existent) Facem precizarea că. Modurile posibile de deschidere (deci şirurile de caractere ce constituie parametrul lui fopen) sunt date în Tabelul 6. stdout) == NULL) { 26 . const char* mod.dat". Dacă deschiderea nu s-a efectuat corect valoarea returnată este NULL(pointer la informaţia nulă) . deschiderea unui fişier existent în modurile "w" sau "w+" produce pierderea conţinutului său de până atunci. Apelul la această funcţie închide fişierul cu pointerul "pf". FILE* pf).h> main ( ){ printf ("Mesaj scris pe monitor \n"). Programul următor ilustrează acest fapt. deschide fişierul cu numele “nume_fişier” în modul de acces "mod".stdout)==NULL) { fprintf (stderr. Dacă funcţia fopen returnează o valoare nenulă.

iar putchar (c).. "eroare la reasignarea lui exit (1).48627669. redenumirii unui fişier: int rename (const char* nume_nou. 4. Scrierea cu format 27 .2. 4. este echivalentă cu: fput (c. Limbajul C dispune şi de posibilitatea: ştergerii de fişiere prin funcţia remove: int remove(const char* nume_fi[ier). stdout la CON\n"). FILE* pointer_la_fişier. simplificată. const char* nume_vechi ). În caz de eroare este returnată valoarea EOF. pointer_la_fişier). char c. Spre exemplu: c = getchar ( ).doc } • • } printf ("Mesaj scris din nou pe monitor \n"). • creării unui fişier temporar: FILE*tmpfile (void). stdout). FILE* pointer_la_fişier. char c. este echivalentă cu: c = fgetc (stdin). int fputc(char c. FILE* flux). int cod. Funcţia fgetc returnează valoarea întreagă a caracterului următor din fişierul pointat cu pointer_la_fişier sau constanta EOF în caz de eroare sau sfârşit de fişier. Funcţia fputc scrie un caracter la sfârşitul fişierului pointat prin pointer_la_fişier. a scrierii apelului la fgetc şi fputc în cazul în care intrarea respectiv ieşirea este cea standard : stdin respectiv stdout. cod = fgetc(c. c = fgetc(pointer_la_fişier). Există de asemenea două funcţii getchar şi putchar care permit exprimarea în C.3. fprintf (stderr. Funcţii de intrare/ieşire pentru caractere int fgetc(FILE* flux).

G) rezultatul se va afişa cu un punct zecimal. Această secvenţă conţine.: rezultatul conversiei se va cadra la dreapta. Dacă formatul este octal se va adăuga un o înaintea numărului.…). iar pentru X literele A. Se pot utiliza şi dimensiuni variabile: se utilizează '*' în loc de numărul ce indică dimensiunea iar variabila respectivă se pune în lista de argumente. e. real în notaţie zecimală sub forma: [-]m. Formatul "şir-format" este un şir de caractere ce conţine fie caractere ordinare fie directive de conversie pentru transformarea valorii unei variabile într-un şir de caractere Caracterele ordinare sunt transmise la ieşire aşa cum apar ele pe când directivele de conversie indică formatul de ieşire pentru argumentele transmise în apelul funcţiei.Gheorghe GRIGORAŞ Funcţiile de scriere cu format permit afişarea sub forma unui şir de caractere a diverselor valori. pentru x sau p se folosesc literele a. în plus .dddddde ± xx sau [-]m. f. iar sprintf pentru scrierea într-un şir de caractere. int printf(const char* şir_format. în ordine: • eventual unul sau mai mulţi indicatori ce modifică semnificaţia conversiei. Pentru formatele flotante ( e. …). # : desemnează un format alternativ. c. F.const char* şir_format. Numărul de d este dat de argumente de precizie (implicit este 6). + : la formatul de ieşire va fi ataşat semnul + sau . fprintf pentru scrierea într-un fişier. 28 . Funcţia printf se utilizează pentru afişarea la ieşirea standard.dddddd sau numărul de d este dat de argumente de precizie (implicit acesta este 6). • • Tabelul 7. la g sau G se vor afişa şi zerourile nesemnificative de după punctul zecimal. f. int fprintf(FILE* flux. d. • eventual un număr pentru a indica dimensiunea minimală a câmpului în care se va afişa. într-un fişier sau într-un şir de caractere. întreg în notaţie hexa fără semn. p sau X u f e sau E TIP ARGUMEN T int int int int float sau double float sau double CONVERSIA întreg în notaţie zecimală cu semn. Acestea pot fi transmise la ieşirea standard. O directivă se specifică prin caracterul % urmat de o secvenţă de caractere ce identifică formatul. Indicatorii disponibili în C sunt: . Formatele ce se folosesc în C sunt date în Tabelul 7. g. int sprintf(char* s. caracterul ce indică formatul conversiei. b. întreg în notaţie octală fără semn. C. eventual caracterul l care precizează că numărul ce urmează a fi afişat este un "întreg lung" (long integer). D.cu excepţia cazului când primul caracter nu este semn.ddddddE ± xx. Formatele de conversie utilizate de printf. B. CARACTE R d sau i o x. E. dacă acesta este hexazecimal se va adăuga ox sau OX înaintea numărului. caracterele se vor cadra la stânga (implicit) sau la dreapta (pentru -). Dacă dimensiunea rezultată prin conversie este mai mică.…).const char* şir_format. E. întreg în notaţie zecimală fără semn real în notaţie zecimală sub forma [-]mmm.

printf(" ul = %d\n". In urma execuţiei se va afişa: Forma zecimala: i = 123 l = 123456789 ui = 45678 ul = 987654321 Forma octala: ui = 131156 ul = 7267464261 printf("Scrierea hexazecimala:\n").45. l). unsigned long int ul = 987654321UL. afişează argumentul în notaţia pointer. Permite afişarea caracterului ‘ % ‘ Exemple Următoarele programe ilustrează folosirea formatelor de afişare la apelul funcţiei printf rezultatele sunt ilustrate la sfârşitul fiecărui program. long int l = 123456789L. afişarea unui singur caracter după conversie în unsigned char.i). ui). printf(" i = %lo\n\n". printf(" ul = %lu\n\n". printf(" ui = %o\n".ul). printf(" l = %ld\n". printf(" Forma zecimala:\n"). double d = 123. în stil f în caz contrar. ul). printf(" Forma octala:\n"). Programul 4 # include <stdio.48627669. unsigned int ui = 45678U.h> int main ( ) { int i = 123. 29 . ui).doc g sau G c s p n % float sau double int char* void* int* afişare în acelaşi stil cu e dacă exponentul este -4 sau superior preciziei. printf(" ui = %u\n". afişarea unui şir de caractere până la întâlnirea caracterului '@0' (sfârşit de şir) sau până când numărul de caractere este egal cu numărul de precizie. i). nu există nici conversie nici afişare în acest caz: este vorba de referinţe la un pointer la un întreg în care se va stoca numărul de caractere afişate până în prezent. printf(" i = %d\n".

ul). 123. 123. 123).-123.4o|\n".4d|\n". printf("|%. 123). printf("|%+6.Gheorghe GRIGORAŞ printf(" ui = %X\n". 123). printf("|%X| |%#X|\n". În urma execuţiei se va afişa: Scrierea hexazecimala: ui = B26E ul = 3ADE68B1 Afisarea semnului: |-123| |-123| |-123| | 123| |+123| |123| Afisare in octal si hexazecimal: |76| |0x7b| |7B| |0X7B| |173| |0173| /*Specificarea lungimii campului si a **numarului de cifre*/ printf("|%. printf("|% d| |%+d| |%d|\n". 123). 123. ui). printf("|%o| |%#o|\n". printf("|%#5d| |%#-5d|\n". 123).-123). 123). printf("|%+6. printf("\n"). printf("Afisarea semnului:\n").4X|\n". 123). 123). printf("|%5d| |%-5d|\n". printf("\n").4d|\n". 123. printf("|%+5d| |%+-5d|\n".-123. Iată ce se va afişa: |0123| |+0123| |0X007B| | 123| |123 | 30 . 123). printf("Afisare in octal si hexazecimal:\n"). printf("|%x| |%#x|\n".4X|\n". 123. printf("|%+6. printf("\n"). 123). printf("|%+. printf("\n").123. printf("|% d| |%+d| |%d|\n". 123). printf(" ul = %lX\n\n". 123).4d|\n". 123.123. 123).

11G|\n". printf("|%#. printf("|%.14157).142| |3| |3.00001). Rezultatul interpretării este încărcat la adresele ce se dau ca argumente la apelul funcţiilor de citire.1e11).48627669.0f|\n" 3. printf("|%.E+123| |3.0E|\n" 3.3E|\n" 3.1e5.141570| |3.14157e123). printf("|%E|\t|%G|\n".14157e123).141570E+123| |1. const char* şir_format.0001. 3. printf("|%#.14157e123). -0. printf("|%. 3.14157). printf("|%G|\t|%G|\n". printf("|%f|\t|%G|\n".14157e123).14157e123).1e6.14157).100000E+10| |3. de la un fişier respectiv dintr-un şir de caractere sunt: int scanf (const char* şir_format.1E+10| |-1. printf("|%E|\n" 3. } Iată ce se va afişa de această dată: |3. int sscanf (char* s. 3.142E+123| |3E+123| |3.110).doc | +123| |+123 | | 0X7B| |0X7B | | +0123| | 0173| |0X007B| /* Afisarea numerelor in virgula flotanta*/ printf("|%f|\n" 3.| |3.…).11G|\t|%. 3. Citirea cu format Funcţiile de citire cu format permit interpretarea unui şir de caractere ca o secvenţă de valori în concordanţă cu un format dat. printf("|%.100000| |3.1E+07| |3100000| |3.5.0E|\n" 3.0f|\n" 3. 3.1). printf("|%.1e7).14157). 3.1. int fscanf (FILE* flux.3f|\n" 3.1| |3. 3. 0. 31 . return0. Aceste funcţii. corespunzătoare citirii de la intrarea standard. …). const char* şir_format. printf("|%E|\n" 3.0001| |1E-05| |310000| |3.1e10.…). printf("|%f|\t|%G|\n".1 E+11| 4. 3.

În general. întreg în notaţie hexa. valoarea unei adrese. Dacă este indicat un număr q (%qC) atunci sunt citite cel mult q caractere. permite indicarea caracterului literal '%'. Implicit se citeşte un singur caracter. Tabelul 8. . Se poate face o omisiune de afectare. şir de caractere: se citeşte până la întâlnirea unui spaţiu sau până la atingerea numărului de caractere indicat. g p n [. Directivele pentru specificarea unui format sunt utilizate pentru precizarea conversiei următorului câmp citit. Nu se face nici o operaţie de citire. f. Câmpul ce urmează a fi convertit (ce este citit) se întinde până la primul spaţiu sau numărul de caractere din acest câmp este specificat în format. . scrie în argument numărul de caractere citite până acum. întreg fără semn în notaţie zecimală. întreg în notaţie octală..caractere ordinare (în afară de %) care trebuie să corespundă următorului caracter citit.caractere de spaţiere sau tabulare care vor fi ignorate. caracter.] FORMAT DE INTRARE întreg în notaţie zecimală. real în notaţie virgulă flotantă. Caracterele pentru specificarea unui format de citire sunt date în Tabelul 8. întreg în notaţie octală(primul caracter 'o') sau hexa (primul caracter 'Ox' sau 'OX'). %*s): în acest caz câmpul este citit dar nu-i memorat. citeşte caracterele din intrare atât cât acestea nu sunt în mulţimea indicată în [ ] după care adaugă '@0'.Gheorghe GRIGORAŞ Formatul (şir_format) este un şir de caractere care poate conţine: .directive de specificare a formatului. punând caracterul '*' în directivă (de ex. Programul 5 32 ... citeşte caracterele din intrare atât timp cât acestea aparţin mulţi-mii indicate în [ ]. Adaugă la argument caracterul '@0' (sfârşit de şir). citindu-se şi spaţiile care. rezultatul citirii este memorat în variabila corespunzătoare din lista argumentelor funcţiei.] % char* Programul următor ilustrează utilizarea formatelor de intrare. Formatele de conversie pentru scanf CARACTER d i o u x c s e. care încep cu '%'. Pentru citirea următorului caracter diferit de spaţiu se foloseşte %ls.. de obicei sunt ignorate. TIPUL ARGUMENTULUI int* int* int* unsigned int* int* char* char* float* double* void* int* char* [∧.

&i1. s2.i1.s6)return 0. &i3). &i2. s1. scanf("%4c%4c%4c". s4.i1. i3.c2. s1. charc1. } Rezultatul unei execuţii a acestui program este: Introduceti trei numere intregi: 5454 -9988 0 A-ti introdus numerele: 5454 -9988 0 Introduceti trei numere intregi: 5454998 390 A-ti introdus numerele: 5454 998 390 Introduceti un text: Iata un exemplu! s1=|Iata| s2=|un| s3=|exemplu!| Introduceti un text: Iata un exemplu! s1=|Iata| s2=|un| s3=|exem| c1=|p| c2=|l| c3=|u| Introduceti un text: Iata un exemplu!: s4=|! Ia| s5=|ta u| s6=|n ex| 33 .doc #include <stdio.s2[10].&c2. printf("Introduceti un text: ").s5. &i2.s6).48627669. printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n".s4. scanf("%c%c%c". printf("Introduceti trei numere intregi: "). s4[4] =s5[4] =s6[4] ="\0". &i3). scanf("%4s %4s %4s". s6[5].i3). printf("c1= |%c|\tc2=|%c|\tc3=|%c|\n"c1.s1.&c3). printf("Introduceti un text: ").i2.c3). scanf("%s%s%s. chars1[10]. s3").h> int main(){ int i1.s3).i3). s5[5].s1. &c1. i2.s3).s5.i2.s2. &i1. printf("Ati introdus:%d\t%d\t%d\n".s3[10]. c3. char s4[5]. printf("s4=|%4s|\ts5=|%4s|\ts6=|%4s|\n". printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n".s2. printf("Introduceti trei numere intregi: "). printf("Ati introdus:%d\t%d\t%d\n". s3). printf("Introduceti un text: "). c2. scanf("%d%d%d". s2. scanf("%4d%3d%4d".

3. 5. end din alte limbaje).10.. ~n capitolul 2 am v\zut cum se construiesc expresiile `n C. alpha). 5. • instruc]iuni de control.9.'. • defini]ii de func]ii. 5. O expresie urmat\ de caracterul '.. 5. ~n general o instruc]iune se termin\ prin '..while Instruc]iunea for Instruc]iunea break Instruc]iunea continue Instruc]iunea go to Exerci]ii Solu]ii la exerci]ii Limbajul C ofer\ urm\toarele tipuri de instruc]iuni: • declara]ii.' este o instruc]iune `n C. • blocuri de instruc]iuni. . 5. cod = printf ("%d\n". Urm\toarele construc]ii sunt instruc]iuni C de tip expresii: i = 1. Un bloc este un [ir de instruc]iuni `ncadrat `n acolade: { [i } (care joac\ rolul de begin .8. ++ k.7. 5.5.1.6.. • expresii. j ++. 5.Cap 5 INSTRUCŢIUNI DE CONTROL 5. Instruc]iunile if Instruc]iunea switch Instruc]iunea while Instruc]iunea do. 5. Iat\ un bloc `n C: { i = 1. 5.2. Un bloc este echivalent cu o instruc]iune.4.

5. int sau long).doc } j = 2.3) : tip identificator. short. Vom trece `n revist\ `n continuare instruc]iunile de control ale limbajului C. y).48627669. 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\). if ( a < b ) { a += 2. Instruc]iunile de declarare a variabilelor (declara]iile) sunt de forma(vezi [i paragraful 2. if (x>y) printf("%d este cel mai mare\n". j --. else printf("al doilea numar este mai mare\n"). 35 .1. else printf("%d este cel mai mare\n". else y = y-x. s [i] = t [j]. }. s [i] = t [j]." este facultativ\. x). Tipul expresiei de dup\ cuv=ntul rezervat if poate fi `ntreg (char. else if (x==y) printf("numerele sunt egale\n"). Instrucţiunea 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. b += 1. i ++. Exemple: if (x>y) x = x-y. if (x>y) printf("primul numar este cel mai mare\n"). real (float sau double) sau tip pointer. if ((c = getchar ( ) ) ! = EOF) putchar (c). tip identificator = valoare. Expresia se pune obligatoriu `ntre paranteze iar partea "else instruc]iune2.

cons2. break. case 'b': printf ("s-a citit litera b\n").. C\rui if `i este ata[at else? Limbajul C rezolv\ problema aceasta prin ata[area lui else celui mai apropiat if.. break. Cazul default este facultativ. 5. else printf (“ b nu este egal cu doi\n”).Gheorghe GRIGORAŞ else a -=b. .’ 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”).2. caracter sau enumerare. deci exemplul este interpretat astfel: if ( a == 1 ) if ( b == 2 ) printf (“ b este egal cu doi\n”). Aceasta permite execu]ia unei anumite ramuri `n func]ie de valoarea expresiei "expresie" din parantez\. dac\ expresia nu are nici una din valorile indicate prin cons1. Instruc]iunea switch switch(expresie){ case const1: instruc]iune1 case const2: instruc]iune2 … case constn: instruc]iunen default: instruc]iune } Instruc]iunea switch este o structur\ de control cu alegeri multiple ce `nlocuie[te o succesiune de alternative de tip if. else printf (“ b nu este egal cu doi\n”). dac\ valoarea sa este const2 atunci se execut\ instruc]iune2 [i urm\toarele p=n\ la "break" etc. Dac\ expresia are valoarea const1 atunci se execut\ instruc]iune1 [i toate cele ce urmeaz\ dup\ aceasta p=n\ la `nt=lnirea unei instruc]iuni "break". dac\ aceasta exist\. care poate fi de tip `ntreg. se execut\ instruc]iunile desemnate de ramura "default".. 36 . 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 ‘. Exemplu: switch (getchar ( ) ) { case 'a': printf ("s-a citit litera a\n").

while (x!=y) { if (x>y) x = x-y. Se `n]elege c\. } Programul urm\tor ilustreaz\ utilizarea instruc]iunii while [i a instruc]iunii switch. se execut\ "instruc]iune" (care poate fi. break poate lipsi (vezi exemplul de la insrtuc]iunea for). break. default: printf ("s-a citit altceva decat a. Dup\ execu]ia acestei instruc]iuni se face din nou evaluarea expresiei indicate `n while [i se repet\ execu]ia p=n\ c=nd evaluarea expresiei returneaz\ o valoare nul\.doc case 'c': printf ("s-a citit litera c\n"). Acest program analizeaz\ un text [i num\r\ vocalele. Instrucţiunea while while(expresie) instruc]iune Expresia "expresie". Exemplu: int c. while ((c = getchar( )) != EOF){ putchar (c). n = 0. nspatii. n++ } int x. pe fiecare ramur\ s-a folosit instruc]iunea break. else y = y-x. b sau c\n"). 5.h> int main (void){ int nvocale. break. un bloc). while ((c = getchar( )) != '\n') { switch (c) { case 'a': case 'A': 37 . Programul 6 # include <stdio.3. `n cazul `n care exist\ pe una din ramuri alte instruc]iuni de control. nvocale = naltele = nspatii = 0. char c. este evaluat\ [i dac\ aceasta nu este nul\. y. binen]eles. printf ("Introduceti un text\n -->"). spa]iile goale [i restul caracterelor din acesta. } ~n acest exemplu. naltele. ce trebuie pus\ `ntre paranteze.48627669.

5.while. n-1). int n = 1. n++ }. Instruc]iunea do . break. c = getchar ( ) while (c!= '\n') { c = getchar ( ). Spre deosebire de instruc]iunea while. 38 . dac\ "expresie" este evaluat\ prima dat\ la zero.Gheorghe GRIGORAŞ case case case case } } } printf("In text sunt %d vocale. "corpul" instruc]iunii do.. do { c = getchar ( ).while (adic\ "instruc]iune") se execut\ la intrarea `n aceast\ bucl\ dup\ care se testeaz\ condi]ia "expresie": dac\ aceasta are valoare nenul\ se execut\ din nou "instruc]iune" etc.. while do instruc]iune while(expresie). Exemplu: int n = 0.. Execu]ia se termin\ atunci c=nd "expresie" are valoarea nul\. printf ("Linia contine %d caractere\n". c. "instruc]iune" se execut\ m\car o dat\ pe c=nd `n cazul while.nspatii. default: naltele++. 'e': case 'E': 'i': case 'I': 'o': case 'O': 'u': case 'U': nvocale++.naltele). A[adar `n cazul do. case ' ': case '\t': nspatii++. break.. return 0. printf ("Linia contine %d caractere \n". Rezultatul unei execu]ii: Introduceti un text: --> Iata un text pentru test ! In text sunt 8 vocale.4. c. n++. } while (c!= '\n'). "instruc]iune" nu se execut\.nvocale. %d spatii si %d alte caractere..5 spatii si 13 alte caractere. n-1)..\n".

while (expr2){ instruc]iune expr3. i++) putchar (c). expr2 sau expr3 sau prin suprimarea corpului ("instruc]iune"): • Suprimarea ini]ializ\rii. i++) if (c == '\n') break. Singura modalitate de a ie[i din aceasta este utilizarea instruc]iunii break. S\ observ\m c\ ini]ializarea lui i s-a f\cut `n afara instruc]iunii for ! • Suprimarea expresiei de control: for( expr . expr2 .(c = getchar( )) != '\0'. i).) Exemplu: i = 0. • se execut\ (o singur\ dat\) expr1 [i se intr\ `n bucl\ (execu]ia de n ≥ 0 a instruc]iunii "instruc]iune"). . expr3) instruc]iune Semantica acestei instruc]iuni poate fi descris\ `n dou\ moduri: 1. 39 . . • expresia expr2 se evalueaz\ [i se testeaz\ la fiecare `nceput de bucl\: dac\ este adev\rat\ atunci se execut\ "instruc]iune" altfel bucla se termin\. expr3) instruc]iune Aceasta este echivalent\ cu secven]a dat\ mai sus (2. 2.) din care lipse[te prima instruc]iune (expr1. c = getchar ( ). 5.doc Se constat\ u[or c\ cele dou\ secven]e de program sunt echivalente. Instrucţiunea for for (expr1. } Instruc]iunea poate fi folosit\ [i prin suprimarea uneia dintre expr1. for(.48627669. for( . Instruc]iunea este echivalent\ cu secven]a: expr1.5. expr2. • instruc]iunea expr3 se execut\ la fiecare sf=r[it de bucl\. expr3) instruc]iune Aceasta este o bucl\ infinit\. printf("numarul de caractere:%d\n". Exemplu: for (i = 0.

(c = getchar( )) != '\0'.Gheorghe GRIGORAŞ • Suprimarea expresiei finale: for( expr1 . while ( ( c = getchar( )) != EOF) { sum++. (c = getchar( )) != '\0'.){ putchar (c) i++ } printf ("numarul de caractere: %d\n". i). Instrucţiunea break Instruc]iunea break permite ie[irea dintr-o bucl\ (for. { putchar (c) i++ } printf ("numarul de caractere: %d\n". do) sau dintr-o instruc]iune cu alegeri multiple (switch). break. 5. i). expr2 . while.3): 1.6. i++). ) instruc]iune Exemplu: i=0 for (. ) instruc]iune Exemplu: for (i = 0. Iat\ c=teva exemple de utilizare a acestei instruc]iuni (vezi [i programul de la sf=r[itul paragrafului 5. Exemplu: for (i = 0. expr3 ) . getchar( )!= '\n'. if (sum>=50) { printf ("50\n"). 40 . expr2 . • Suprimarea ini]ializ\rii [i a expresiei finale: for( . • Suprimarea corpului buclei: for( expr1 . expr2 .

doc } } printf ("Iesire din bucla while\n"). numar++) { if (numar % 5 == 0) continue. suma). go to eticheta . ~n acest prim exemplu. Etichetele sunt nume ce se pun `n fa]a instruc]iunilor ]int\ urmate de ":". numar <= 100. p=n\ la sf=r[itul buclei `n care se afl\. . sum <= 25. ~n exemplul urm\tor se ilustreaz\ folosirea instruc]iunii go to [i modul cum ea poate fi evitat\: for (i = 0. `n cuprinsul acelea[i func]ii.48627669. 2. j < m. de 5. sum). 5. if ( j >= 75. } ~n acest caz instruc]iunea break permite ie[irea din bucla for. for (j = sum.5. instruc]iunea break permite ie[irea din bucla while dup\ citirea a 50 de caractere [i nu la `nt=lnirea caracterului EOF. } print ("Suma este:%d\n". j++) { j* = 1. printf("Tablourile nu au elemente comune\ n"). . Instrucţiunea continue Instruc]iunea continue ignor\ toate instruc]iunile ce urmeaz\ dup\ ea. i < n. Este recomandat s\ se evite folosirea instruc]iunii go to (a[a cer principiile program\rii structurate) dar uneori este util\. j++) if (a [i] == b [j] ) go to gasit.7. Se observ\ c\ prin continue se evit\ ad\ugarea la suma a numerelor multiple 5. suma++ = numar.5) break. for (numar = 1. Instrucţiunea go to Instruc]iunea go to provoac\ saltul necondi]ionat la o etichet\. Iat\ un exemplu: int numar. suma = 0. while ( ( c = getchar( ))!= EOF) { sum++.8. ea provoac\ trecerea la urm\toarea itera]ie. i++) for (j=0. } printf ("Total: %d". 41 .

if (gasit) printf (" a[%d]= b[%d]= %d\n". .j. pe m\sur\ ce se citesc cifrele hexazecimale se face conversia `n zecimal. Soluţii la exerciţii 42 . ad\ug=nd la sf=r[itul liniei suma lor. j++) gasit = (a [i] == b [j]). 5. verific\ validitatea sa [i efectueaz\ conversia `n zecimal.i. 3. i++) for (j = 0.9. Numărarea biţilor 1 într-un număr Scrie]i un program care cite[te 10 numere `ntregi [i pentru fiecare din acestea calculeaz\ num\rul bi]ilor ce au valoarea 1. i < n && ! gasit. itera]ia se opre[te dac\ se cite[te un caracter ce nu este cifr\ hexazecimal\ [i. . else printf ("Tablourile nu au elemente comune \n"). Exerciţii jgjj Calculul factorialului.j. Scrie]i un program care s\ realizeze urm\toarele: . 2. int gasit = 0.10. 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).afi[area rezultaului.Gheorghe GRIGORAŞ . 5. se va face apel la o func]ie ce num\r\ bi]ii 1. aliniat\ la sf=r[it de linie.citirea unui num\r natural (dat de utilizator). Prezentare de date Scrie]i un program care cite[te n valori `ntregi [i le afi[eaz\ c=te l pe fiecare linie. j < m &&! gasit. Ultima linie va con]ine suma sumelor.a[i]). Conversie Scrie]i un program care cite[te un num\r hexazecimal (ca o succesiune de caractere). Numerele n [i l se definesc ca valori constante. for (i = 0. 4. gasit: printf (" a[%d]=b[%d]=%d\n".calculul factorialului acestui num\r (iterativ). ~n bucla de citire. Se va utiliza o itera]ie pentru citirea caracter cu caracter a num\rului.a [i]).i.

se converte[te `n valoare `ntreag\.'a' + 10).h> int main (void) { int n. c = getchar ( ) . printf ("Introduceti un numar natural ->"). } 43 . else numar = numar*16 + (c . a) /*Citirea unui numar hexa si conversia sa in zecimal*/ # include <stdio.'A' + 10).48627669. i. /* Calculul lui n! */ # include <stdio. i < = n. char c. for (i = 2.doc 1. else if ((c>= 'a') && (c<='f')) numar = numar*16 + (c . n. numar). Calculul factorialului Iat\ o solu]ia incomplet\ a problemei. c = getchar ( ). 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. } printf("Conversia zecimala :%d\n".'0'). return 0. &n). return 0. scanf ("%d". fact. p\str=nd valoarea cumulat\ a num\rului zecimal ob]inut. while (( c>= '0') && (c<='9')| | (c>= 'a') && (c<='f')| | (c>= 'A') && (c<='F') { if ((c>= '0') && (c<='9')) numar = numar*16 + (c . fact = 1. } 2. Dac\ este o astfel de cifr\. fact). 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.h> int main (void){ int numar = 0. printf (" %d ! = %d\". Prima solu]ie face conversie `n func]ia main ( ) iar a doua solu]ie folose[te o func]ie de conversie. printf (" Introduceti un numar hexa ->"). i++) fact * = i.

while (( c>= '0') && (c<='9')| | (c>= 'a') && (c<='f ')| | (c>= 'A') && (c<='F') { numar = numar*16 + conversie (c). x >>=1. } int numarbit(int x){ int n = 0. printf ("Numarul bitilor 1 este: %d\n". i++) { printf ("Introduceti o valoare intreaga: ").h> int conversie (char x){ return (x>= '0') && ( x<= '9') ? x . } return 0. int val. while (x!=0) { if (x & 01) n++. c = getchar ( ) . c = getchar ( ) . printf (" Introduceti un numar hexa ->"). &val). char c. Numărarea biţilor 1 într-un număr Determinarea bi]ilor 1 se face prin decalaj succesiv [i testarea bitului.h> int numarbit(int).'0': ((x>='a')&&(x<='f')?x-'a':x-'A')+10. i < 10. int main (void) { int i.Gheorghe GRIGORAŞ b) /*Citirea unui numar hexa si conversia sa in zecimal*/ # include <stdio. } int main (void){ int numar = 0. } return n. /* Numararea bitilor 1 din reprezentarea binara a unui numar # include <stdio. } 3. return 0. } printf ("Conversia zecimala: %d\n". } 44 intreg */ . scanf ("%d". numarbit(val)). numar). for (i = 0.

doc ~n func]ia numarbit. nl = 0. for (i = nl. se poate a[adar utiliza x ca variabil\ de lucru. &val). sumap). val). transmiterea parametrului se face prin valoare. i < l. suma p+= val.Ultima linie contine suma sumelor */ # include <stdio. } 45 . /*ultima valoare intreaga citita */ sumap=0. } /* alinierea sumei totale pe ultima linie */ int i. 4. int main (void){ int val. for (nt = 0. la st=nga se adaug\ un zero./*numarul intregilor pe linie */ suma=0. printf ("%6d\n". /* suma sumelor par]iale */ nt. ++nl. suma += sumap. const l = 3. printf ("%6d". return 0 . nt < n.48627669. suma += sumap. sumap = 0. printf ("%d\n". i++) printf (" "). /*numarul total de intregi */ printf ("Introduceti%d numere intregi". if (nl == l ) { printf (" %6d\n". nt++) { scanf ("%d". suma). /*suma din linia curenta*/ nl=0. Prin instruc]iunea x >>=1 se decaleaz\ bi]ii lui x cu o pozi]ie la dreapta. } } if (nl! = 0) { /*ultima linie este incompleta: se **completeaza cu spatii*/ int i. i++) printf (" "). Prezentare de date /* Se citesc n intregi si se afiseaza cate l pe **linie impreuna cu suma acestora la sfarsit de **linie. sumap).h> const n = 10. n). for (i = 0. i < l.

11. Operatorul unar "&" numit operator de referen]iere sau adresare. 6.Cap 6 TABLOURI ŞI POINTERI 6. 6. .7.10. De exemplu. 6. aplicat unei variabile.6. 6. 6. 6. 6. Pointerii au tip : aceasta `nseamn\ c\ un pointer nu poate fi folosit dec=t pentru a con]ine adrese de variabile de un singur tip.4. char *pc.9. Pointeri Tablouri cu o dimensiune Rela]ia `ntre pointeri [i tablouri Opera]ii aritmetice cu pointeri {iruri de caractere Tablouri cu mai multe dimensiuni Tablouri de pointeri Pointeri [i alocarea memoriei Operatorul sizeof Pointeri c\tre func]ii Exerci]ii Solu]ii 6. se specific\ faptul c\ pi este un pointer la o variabil\ de tip `ntreg iar pc un pointer la o variabil\ de tip "char".3. permite ob]inerea adresei acesteia: int i.1. 6. Pointeri tip *identificator.12. Un pointer este o variabil\ ce con]ine adresa unei alte variabile.5. prin declara]iile: int *pi. 6.1. 6.2. 6.8. pi = &i.

Referenţierea unui element al tabloului Elementele unui tablou pot fi accesate prin numele tabloului urmat de o expresie `ntre paranteze p\trate .2. permite derefen]ierea unui pointer. int vector[10]. o declara]ie de tablou cu o dimensiune con]ine tipul tabloului (tip). dimensiune.precum [i dimensiunea sa. a = b.) nu are nici un efect asupra variabilelor x. schimbare_corecta (&x. &y). int b) { int temp = a. chiar periculoas\ am spune: acesta permite citirea sau scrierea `n orice zon\ de memorie. numele tabloului (nume) . dereferen]iere. Dac\ se dore[te modificarea unui parametru formal. int *q){ int temp. indirectare. Dimensiunea este o constant\ `ntreag\ [i specific\ num\rul elementelor tabloului. y). ~n declara]ia de mai sus.care este un identificator . Forma "clasic\" a func]iei. 6.2. b = temp. 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.doc Operatorul unar "*". cele 10 elemente ale tabloului vector sunt: vector[0]. A[adar. *q = temp. incorect\ (semantic) `n limbaj C. x = *pi ⇔ x = i.care trebuie s\ aib\ valoarea `ntre 0 [i dimensiune .numit\ expresie indice .1. furniz=nd valoarea variabilei pointate de acesta: int x. 6. este: void schimbare (int a. define[te un tablou cu numele "vector" care are 10 elemente de acela[i tip. `ntreg. Utilizarea operatorului "*" este destul de delicat\. `n limbajul C transferul implicit al parametrilor este prin valoare. trebuie transmis\ func]iei adresa variabilei iar `n corpul func]iei s\ se foloseasc\ operatorul de dereferen]iere.1. temp = *p. } Un apel al acestei func]ii (prin schimbare (x. *p = *q. y = 2. Varianta corect\ este: void schimbare_corecta (int *p. A[a cum s-a precizat la capitolul "Func]ii". Tablouri cu o dimensiune tip nume[dimensiune]. vector[9] 47 . Declara]ia int vector[10]. Un tablou este o colec]ie de elemente(date) de acela[i tip. O aplica]ie important\ privind utilizarea pointerilor este transferul prin referin]\ al parametrilor unei func]ii. vector[1]. fiecare din acestea put=nd fi accesibil\.y (actuale) pentru c\ func]ia lucreaz\ cu variabilele ei locale a [i b. } Apelul corespunz\tor este: int x = 1. Exemplul clasic pentru acest procedeu este acela al func]iei de interschimbare a dou\ variabile.48627669. Primul element al tabloului este cel de indice 0 iar ultimul este cel de indice dimensiune -1.….

0. 4. 2. valoare_2. 2 0 5. tab[3] = tab[4] = 'd'.2. 6. separate prin virgule. care se `nchid `ntre acolade. 1}. 3.2. 3. '\o'}. tip nume[dim] = { valoare_1. char tab[marime]. are ca efect crearea tabloului: 5 2 3 1 0 0 0 0 0 0 ~n cazul unui tablou care se ini]ializeaz\. . int a[4] = {1.2 3 4 0 48 . 'c'. 4}. tab[0] = 'a'. tab[1] = tab[2] = 'b'. }.. Exemple: 1. char s[4] = {'a'. 0}.Gheorghe GRIGORAŞ La declararea unui tablou se aloc\ o zon\ de memorie contigu\ care s\ stocheze toate elementele tabloului. Iniţializarea unui tablou Ini]ializarea unui tablou se face prin semnul "#" dup\ declara]ia acestuia urmat de o list\ de valori ini]iale. 'a' 'b' 'b' 'd' 'd' Tabloul va avea structura: tab[marime . aceasta se determin\ de c\tre compilator: float x[ ] = {2.. poate fi omis\ dimensiunea. Adresa primului element (cel de indice 0) este [i adresa tabloului iar celelalte elemente se raporteaz\ la acesta. 5. 2. 2. 3. tab[marime/2] = 'c'. 'b'. 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.1] = 'e'. # define marime 5.2. Spre exemplu int a[10] = {5. atunci celelalte valori se ini]ializeaz\ cu zero.

A[adar.48627669. 'f'}. '\0'}. c[3]. i < 10. este echivalent\ cu: char s[ ] = {'a'. i < 10. este echivalent\ cu: char s[6] = {'a'. &x[i]). for ( i = 0. } Este de remarcat faptul c\ nu se face nici o verificare a limitelor unui tablou atunci c=nd se acceseaz\ un element al s\u. iar declara]ia: char s[ ] = "abcdef" . De notat c\ `n cazul sirurilor de caractere ce se memoreaz\ `ntr-un tablou. i < 20. float x [20]. declara]ia: char s[6] = "abcdef" . for ( i = 0. int *pa. Nota]ia "*pa" este echivalent\ cu nota]ia tab[0] iar nota]ia "*(pa+1)" este echivalent\ cu nota]ia tab[1]. este perfect valid\ asignarea 49 . `n sensul c\ ele reprezint\ adresa aceleia[i zone de memorie. sunt echivalente. for (i=0. `n general "*(pa+i)" este totuna cu tab[i]. 'e'. ~n limbajul C.doc ~n cazul tablourilor de caractere. 'b'. Relaţia între pointeri şi tablouri S\ consider\m urm\toarea secven]\: int tab[10]. numele unui tablou poate fi utilizat ca pointer (constant) la adresa de `nceput a tabloului. i++) tab[i] = 100. cu declara]iile de mai sus. [i alocarea se face astfel: a[0 a[1] a[2] b[0] b[1] b[2] c[0] c[1] c[2 ] ] atunci expresiile a[4]. pa = &tab[0]. i++) *(pa++) = 100. Spre exemplu dac\ se declar\ int a[3]. 'b'.5). c[-2]. acest caracter noteaz\ sf=r[itul [irului( vezi paragraful 6. 'd'. 'e'. Ultima instruc]iune asigneaz\ variabilei pointer pa adresa primului element al tabloului tab.3. 'c'. Ini]ializarea unui tablou se poate face [i prin citirea succesiv\ a tuturor elementelor sale: int i. b[1]. 'd'. i++) *(pa+i) = 100. 6. De aceea. 'c'. pa = &tab[0]. i++) { scanf (" %f". b[3]. i < 10. ultimul element al tabloului este caracterul ‘\0’. 'f'. ini]ializarea se poate face [i cu [iruri de caractere incluse `ntre ghilimele. Urm\toarele secven]e for sunt echivalente: for ( i = 0. pa = &tab[0].

pf pointeaz\ la cel de-al doilea element al tabloului ftablou. S\ urm\rim urm\torul exemplu: float ftablou[10]. '\o'}. Nota]ia pointer ptr = tablou ptr1 = ptr + 5 ptr + i ptr + 4 ptr . Trebuie precizat `ns\ c\ unitatea care intr\ `n discu]ie nu este octetul ci adresa obiectului pointat.5. ~n acest exemplu. incrementarea/decrementarea (^^.ptr ptr ++ Nota]ia tablou i=0 i=i+5 tablou [i] tablou [4] tablou [-3] j-i i ++ 6. sau tab ++.3 ptr1 . char mesaj[7] = "salut!". Citirea respectiv tip\rirea acestui [ir se face prin instruc]iunile: 50 . Pentru a reprezenta un [ir de caractere. Nu sunt valide (e lesne de dedus) expresiile: tab = pa. Prin conven]ie.4. ~n rezumat.'l'. A[adar se poate scrie [i: for ( i = 0.'a'. pf++.'t'. i < 10. ultimul caracter dintr-un astfel de lan] este caracterul NULL (' @0'). dup\ incrementare. care este echivalent\ cu "pa=&tab[0]. pa = tab. --) [i sc\derea a doi pointeri de acela[i tip.'u'. Iat\ [i alte exemple: `n partea st=ng\ se descrie o expresie `n care apar pointeri iar `n dreapta expresia echivalent\ `n termenii tabloului.". i++. char mesaj[ ] = "salut!". pa++) *pa = 100. Tabloul de caractere (pe care-l numim mesaj): 's' 'a' 'l' 'u' 't' '!' ' @o' poate fi declarat prin una din urm\toarele trei instruc]iuni: char mesaj[7] = {'s'. nu exist\ un tip de baz\ pentru [iruri (lan]uri) de caractere. echivalen]a `ntre elementele unui tablou [i numele s\u se exprim\ prin: tablou[i] *(tablou + i) &tablou[i] tablou + i 6.Gheorghe GRIGORAŞ pa = tab. float *pf = ftablou.'!'. se utilizeaz\ tablourile de caractere. Şiruri de caractere ~n limbajul C. Operaţii aritmetice cu pointeri Opera]iile aritmetice permise asupra pointerilor sunt adunarea/ sc\derea unei constante.

. Un tablou declarat `n acest mod se compune din dim_1*dim_2*. mesaj). ~n sf=r[it a treia viziune a tabloului este aceea a unei succesiuni de elemente dispuse `ntr-o zon\ contigu\: t [0][0] t [0][1] t [0][2] t [0][3] 51 .48627669.. scanf("%s".. 6. mesaj[0]). Pentru a accesa un element dintr-un tablou exist\ mai multe moduri de notare.. Iat\ de exemplu o declara]ie a unui tablou cu dou\ dimensiuni de valori 3 respectiv 4 (a[adar o matrice cu 3 linii [i 4 coloane). printf("%s". `n concordan]\ cu modul de stocare a elementelor tabloului `n memorie.. &mesaj[0]). datorit\ numerot\rii indicilor de la 0). .*dim_n elemente de acela[i tip (declarat) stocate `ntr-o zon\ contigu\ de memorie. dim_n trebuie s\ fie constante..6. dim_2.[dim_n]. mesaj). Tablouri cu mai multe dimensiuni Declararea unui tablou cu N dimensiuni se face prin: tip nume[dim_1][dim_2]. dim_1.doc scanf("%s". O alt\ viziune (acceptat\ de C) a acestui tablou este aceea a unui tablou cu o singur\ dimensiune `n care fiecare element este la r=ndul s\u un tablou cu o dimensiune: t t[0] t[1] t[2] t [0][0] t [1][0] t [2][0] t [0][1] t [0][2] t [0][3] t [1][1] t [1][2] t [1][3] t [2][1] t [2][2] t [2][3] Elementul t[1] reprezint\ un tablou cu o dimensiune iar elementul ha[urat este referen]iat prin *(t[1]+3). ~n aceast\ declara]ie. Exist\ o bibliotec\ de func]ii standard pentru manipularea [irurilor de caractere care se prezint\ `n anex\. int t[3][4]. printf("%s".. O prim\ viziune a reprezent\rii acestuia `n memorie este cea natural\ a unei matrice: t [0][0] t [0][1] t [0][2] t [0][3] t [1][0] t [1][1] t [1][2] t [1][3] t [2][0] t [2][1] t [2][2] t [2][3] Elementeul ha[urat din acest tablou se referen]iaz\ prin t[1][2] (este elementul de pe linia 2 [i coloana 3 din matrice.

"sambata". Astfel t [0][0] va fi ini]ializat cu 1. 3. pot intra `n componen]a unui tablou.7. "vineri". "miercuri". 8. 6. 2. "joi". 10. • ini]ializarea fiec\rei dimensiuni de tablou. }. 12} }. 9.{5. 12}. "duminica"). 10. 8}. 7. 6}}. 2. A[a cum referen]ierea unui element al tabloului poate fi f\cut\ `n mai multe moduri. Un tablou unidimensional de pointeri corespunde la un tablou (cu dou\ dimensiuni) de elemente de tipul pointat. char *zi[7] = {"luni". zi[0] 'l' ' u ' ' n ' 52 zi[1] 'm ' 'a' 'r' zi[2] ' m ' 'i' 'e' zi[3] 'j' ' o ' 'i' zi[4] 'v ' 'i' ' n ' zi[5] 's' 'a ' ' m ' zi[6] 'd ' 'u ' ' m ' . 6. 4. • ini]ializarea numai a unor elemente din tablou: int t[3][4] = {{1}. [i ini]ializarea unui tablou se poate face `n moduri diferite (sintactic vorbind). 5. Iat\ cum se declar\ un tablou de pointeri cu 7 componente ce se ini]ializeaz\ cu adresele [irurilor constante ce reprezint\ numele zilelor dintr-o s\pt\m=n\. 3.Gheorghe GRIGORAŞ t [1][0] t [1][1] t [1][2] t [1][3] t [2][0] t [2][1] t [2][2] t [2][3] Elementul ha[urat (acela[i ca [i `n cazurile anterioare) se referen]iaz\ prin: *( *t + 6) sau prin nota]ia echivalent\: *( &( t[0][0] + 6)) S\ not\m c\ `n acest caz t este de tip pointer de pointer de `ntregi (dubl\ adresare indirect\). 7. restul elementelor sunt ini]ializate cu zero. O problem\ important\ relativ la tablourile cu mai multe dimensiuni este cea a ini]ializ\rii acestora.{5. Tablouri de pointeri Pointerii fiind variabile. 11. 11. separat: int t[3][4] ={{1. t[3][4]: • ini]ializarea prin enumerarea tuturor elementelor tabloului ( `n ordinea liniilor dac\-i vorba de matrice): int t[3][4] = {1. 4}. {9. t [1][0] cu 5 iar t [1][1] cu 6. "marti". S\ exemplific\m aceste moduri cu referiri la acela[i tablou pe care l-am reprezentat mai sus. 6.

h> 53 . sortat = 0. 7). i++) if (tabp [i] != NULL) printf ( "%s\n".8. int n){ int i.48627669. pozitiv dac\ s1 > s2 [i zero dac\ s1 # s2. O func]ie care s\ afi[eze toate [irurile de caractere (pointate de tabp) la un singur apel ar putea ar\ta astfel: void scrie(char *tabp [ ]. for (i = 0.doc 'i' 't' 'i' 'r' 'c' 'u' 'r' 'i' ' e ' 'r ' 'i' 'b ' 'a ' 't' 'a ' 'i' 'n ' 'i' 'c ' 'a ' S\ consider\m un tablou de pointeri de tip char. # include <stdlib. tabp [i] = tabp [i+1]. 6. for (i = 0. tabp[i] ). rezultatul este negativ dac\ s1 < s2. } } } Apelul pentru sortarea alfabetic\ a zilelor s\pt\m=nii este sortare(zi. } Apelul acestei func]ii pentru scrierea zilelor s\pt\m=nii este: scrie (zi. char *temp. sortat = 0. 7). int n) { int i. S\ mai d\m un exemplu de func]ie care sorteaz\ lexicografic (alfabetic) [irurile pointate de tabp: void sortare (char* tabp[ ]. cu numele tabp. ~n corpul func]iei sortare s-a folosit un apel la func]ia strcmp care compar\ 2 [iruri de caractere s1 [i s2. while (! sortat) { sortat = 1. i < n-1. i < n. i++) if (strcmp (tabp [i]. tabp [i+1]) > 0) { temp =tabp [i]. Pointeri şi alocarea memoriei Printre func]iile de alocare a memoriei (vezi Anexa ). "maloc" [i "free" joac\ un rol important pentru c\ ele permit alocarea / dealocarea `n mod dinamic a spa]iului din memorie. tabp [i+1] = temp. Acest spa]iu este posibil de accesat cu ajutorul variabilelor de tip pointer.

Func]ia malloc are ca argument num\rul de octe]i dori]i a fi aloca]i [i `ntoarce ca rezultat un pointer c\tre zona de memorie liber\ alocat\ de sistem. element *ptr. atunci c=nd este parametrul unei func]ii. /*presupunem ca tipul element este definit undeva */ -------tampon = malloc(512).9. . Operatorul “sizeof” sizeof expresie. void free(void *ptr). ~n cursul execu]iei programul poate aloca memorie `n limitele impuse de sistem. Iat\ un exemplu: char *tampon. 6. Pentru a ob]ine num\rul elementelor tabloului t se utilizeaz\ expresia “sizeof t” sau “sizeof t[0]”.. sizeof(tip). Dac\ nu mai este memorie disponibil\ (nu se poate face alocarea) func]ia malloc returneaz\ valoarea NULL. De pild\.Gheorghe GRIGORAŞ void *malloc (size_t dim). se poate utiliza operatorul "sizeof" (vezi sec]iunea urm\toare). Pentru specificarea m\rimii unui tip particular. Func]ia "free" permite dealocarea spa]iului de memorie alocat `n prealabil de malloc.. dup\ utilizarea memoriei tampon [i ptr (`n exemplul de mai sus) se scrie (`n program) free (tampon). Dac\ se aplic\ unui tablou. Alocarea dinamic\ a memoriei este deosebit de util\ at=ta timp c=t programatorul folose[te structuri de date pentru care nu [tie dimensiunea la scrierea programului. un tablou este considerat ca [i un pointer. /* s-a alocat o memorie tampon de 512 caractere*/ ptr = malloc(32*sizeof(element)). . Acest lucru se ilustreaz\ `n exemplul urm\tor: double tab [100]. free (((char*)ptr).. prin urmare operatorul sizeof nu ofer\ dimensiunea memoriei ocupat\ de tablou ci dimensiunea tipului pointer. /*s-a alocat o zona de 32 de "elemente"*/ if ((tampon == NULL | | ptr == NULL)) { printf ("Alocare imposibila ! \n"). void f(double[ ]). operatorul sizeof ofer\ dimensiunea `n octe]i a memoriei ocupat\ de `ntreg tabloul. S\ not\m `n acela[i timp c\. Operatorul “sizeof” ofer\ dimensiunea `n octe]i a tipului expresiei considerate(tipului respectiv). Pointerul returnat este de tip "void" ce corespunde unui pointer la o variabil\ de tip oarecare.. /*declaratia este echivalenta cu void f(double*)*/ int main( ){ 54 .

h> # include <string. 6. int tab_int[n_max]. tip: este tipul returnat de func]ia pointat\. .. int(*cmp)(const void* val1. 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*”. De exemplu declara]ia: char *(*p)(char*. /* i este initializat cu sizeof(double)*/ } Pentru a ob]ine dimensiunea memoriei ocupat\ de un tip anume se folose[te: sizeof(tip). /* i este initializat cu 100 * sizeof(double)*/ f(tab). Apelul sizeof(long). nume: este identificatorul pointerului la func]ie.doc int i = sizeof tab. size_t n. ofer\ num\rul de octe]i utiliza]i pentru a memora un `ntreg “long” (este incorect a scrie sizeof long). cel\lalt de tipul const char*. Pointeri către funcţii O func]ie are un nume care este identificator dar acesta nu constituie o variabil\ `n C. lista_arg : este lista argumentelor func]iei pointate. "Ion Gheorghe". /* tab_int este tabloul ce contine lungimile liniilor **ce trebuie sortat */ char* tab_nume[n_max] = { "Ionescu Ion". 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. Este posibil. unul de tip char*. } void f(double t[ ]){ int i = sizeof t. de a defini o variabil\ de tip pointer c\tre o func]ie.h> enum {n_max = 10}. are doi parametri. De aceast\ dat\ parantezele sunt obligatorii. Iat\ un program ce utilizeaz\ func]ia qsort : # include <stdio.10. precizeaz\ c\ p este un pointer la o func]ie de tip char* (pointer la tipul char). pe de alt\ parte.const char*). 55 . size_n t. 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. "Constantin Vasile". Declara]ia unui pointer la o func]ie este de forma: tip(*nume) (lista_arg)..h> # include <stdlib.48627669.

printf("Lungimile numelor sortate:\n"). n_max. Exerciţii 1.Gheorghe GRIGORAŞ "Constantin Mircea".comp_nume). "Constantinescu Ioana". S\ se scrie programe C care s\ implementeze func]iile: a) int strlen(const char*s) : func]ie ce returneaz\ dimensiunea [irului s. i++) tab_int[i] = strlen(tab_nume[i]). se returneaz\ o valoare negativ\.i. /* tab_nume este tabloul ce trebuie ordonat **lexicografic */ /* se definesc functiile de comparatie */ int comp_int (const void* n1. i++) printf("%2d: %s\n".const char* sursa) : func]ie ce copie [irul sursa `n [irul dest [i returneaz\ dest. A[a cum s-a mai precizat.tab_int[i]). [irurile de caractere sunt memorate `n tablouri `n care ultimul element este un delimitator de sf=r[it de [ir: caracterul NULL(‘\0’). "Constantiniu Calin". b) char* strcpy(char* dest. } int main(void) { int i.i. "Vasiliu Catalina". "Vasile Radu".tab_nume[i]).*(char**)p2)). const void* n2) { return(*(int*)n1. for(i = 0. } int comp_nume (const void* p1. printf("Nume ordonate lexicografic: \n").i. i++) printf("%2d: %s\n". d) int strcmp(const char* s1. c) char* strcat(char* dest. Dac\ are loc rela]ia s1 < s2. "Vasilescu Maria". qsort(tab_nume. for(i = 0.tab_nume[i]). i < n_max. for(i = 0. printf("Lista initiala de nume : \n").*(int*)n2). return 0.const char* sursa): func]ie ce concateneaz\ [irul sursa la sf=r[itul [irului dest [i returneaz\ valoarea lui dest. comp_int). `n C. const char* s2) : func]ie ce compar\ [irurile s1 [i s2 conform ordinii lexicografice. dac\ s1 = s2 se returneaz\ 0 [i dac\ s1 > s2 se returneaz\ o valoare pozitiv\. qsort(tab_int. sizeof(int). for (i = 0. 56 . ~n anex\ sunt date func]iile din biblioteca standard care se aplic\ [irurilor de caractere. i < n_max .n_max. i++) printf("%2d: %d\n". const void* p2) { return(strcmp(*(char**)p1.sizeof(char*). i < n_max.11. "Vasilescu Cristi" }. i < n_max. } 6.

h> # include <assert. } Iat\ [i un program care testeaz\ aceste func]ii. *dest = '\0'. while(sursa[i] != '\0') { dest[i] = sursa[i].doc 6. while(*scr != '\0') *dest++ = *src++. while((s1[i] == s2[i] && (s1[i] != '\0')) i++. const char *s2){ int i = 0.s2[i]. i++ } dest[i] = '\0'. char* strcat(char *dest.h> int strlen(const char *s) char* strcopy(char *dest. const char *sursa).48627669. char *sfarsit = "exemplu ! ". int main(){ char *inceput = "Iat\". const char *sursa){ int i = 0. Dac\ evaluarea acestui parametru este valoarea fals (0) atunci assert returneaz\ un mesaj de eroare. return -. const char *sursa){ while(*dest != '\0') dest++. return dest.i .12. Implementarea func]iilor de la a) la d) se poate face folosind nota]ia tablou sau aritmetica pointerilor. Soluţii 1. } char *strcpy(char* dest. const char *s2). while(s[i++] != '\0') . char *mesaj. const char *sursa). } char *strcat(char *dest. return s1[i] . return dest. int strlen(const char *s){ int i = 0. Se folose[te func]ia assert (anexa ) care are ca parametru o expresie logic\ ce descrie o proprietate ce trebuie verificat\. char *mijloc = "un mic". 57 . # include <stdlib. int strcmp(const char *s1. } char *strcmp(const char *s1.

Gheorghe GRIGORAŞ } int lungime. mesaj = malloc(lung + 1). return 0. assert(strcmp(mesaj. 58 .inceput).mijloc). assert(lungime==strlen("Iata un mic exemplu ! ")). strcat(strcat(strcopy(mesaj. "Iat un micut exemplu!") < 0). sfarsit).inceput) > 0). "Iata un mic exemplu !")== 0). assert(strcmp(mesaj. lungime = strlen(inceput)+ strlen(mijloc) +strlen(sfarsit). assert(strcmp(mesaj.

Instruc]iunea permite redenumirea at=t a tipurilor de baz\ (deja existente) c=t [i a tipurilor construite.4 7.8 Redenumirea unui tip Tipul structur\ Accesul [i ini]ializarea c=mpurilor unei Structuri autoreferen]iate Tipul enumerare Uniuni Exerci]ii Solu]ii ~n capitolul al doilea au fost introduse tipurile de baz\ ale limbajului C.5 7.6 7. Iat\ c=teva exemple: typedef long Mare. 7.1 7.2 7. typedef char Mesaj[49]. .Cap 7 CONSTRUIREA DE NOI TIPURI 7. Redenumirea unui tip Instruc]iunea typedef permite redenumirea unui tip. ~n acest capitol vom vedea c\ `n C putem construi “structuri” sau “uniuni” care permit regruparea elementelor de tipuri diferite `n scopul de a defini un nou tip. ~n anumite programe este util s\ regrup\m diferite variabile pentru a exprima o anume rela]ie ce le caracterizeaz\. Sintaxa ei este: typedef tip nume_nou.7 7. De asemenea exist\ posibilitatea de a renumi (redenumi) un anume tip. De pild\ un tablou permite a regrupa o mul]ime de elemente de acela[i tip. Aici “tip” este tipul ce se dore[te a fi redenumit iar nume_nou este numele ce se d\ acestuia.1.3 structuri 7.

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]. } amicul. Mesaj salut="!Bine a-ti venit la cursul<Limbajul C>". struct Data{ short ziua. char prenume[20]. Mare a. struct Persoana colegul. char *grupa.2. typedef struct { char nume[20]. short luna. short luna. } Data. struct Student{ char *nume. typedef struct{ short ziua. ~n instruc]iunea de mai sus “nume” este facultativ. short anul. int an. } struct Student ionescu. int varsta. char prenume[20] Data data_nasterii. short anul. Fiecare linie din partea “declara]ii” define[te un c=mp al structurii. 7. char *prenume.Gheorghe GRIGORAŞ typedef char Luna[10]. 60 . }. el este totu[i util pentru a identifica structura definit\. Tipul structură Instruc]iunea pentru definirea structurilor este: struct nume{ declara]ii }. popescu. Structura este o colec]ie de una sau mai multe variabile (numite membri) grupate sub un singur nume. struct Data data_nasterii.b. Luna ianuarie = "ianuarie".

data_nasterii. c=mpurile din variabila “ionescu” sunt copiate `n c=mpurile corespunz\toare din variabila “necunoscut”. } Persoana. 61 . necunoscut ->varsta = 41. " " .doc } Persoana. O atribuire de structuri este o copiere bit cu bit a elementelor corespunz\toare. Are sens asfel: necunoscut = ionescu . Accesul şi iniţializarea câmpurilor unei structuri Accesul la c=mpurile unei variabile de tip structur\ se face utiliz=nd numele unei variabilei urmat\ de punct (“. popescu.nume este de tip char*. Persoana necunoscut = { " " . S\ observ\m c\ structurile se pot defini f\r\ nume. urmat\ de numele c=mpului. ionescu.3.nume = necunoscut->nume. care este un tip structur\. S\ consider\m acum declara]ia: typedef struct{ char nume[40] . Persoana ionescu. Aici. char prenume[40]. "Vasile" . 42 }. Persoana ionescu.varsta este de tip int. *necunoscut. Iat\. 0}. 7. variabilele “ionescu” [i “dan” sunt definite ca fiind de tip Persoana .”) [i de numele c=mpului selec]ionat. prin typedef li se atribuie un nume. int varsta. Elementul desemnat `n acest mod este echivalent cu o variabil\ de acela[i tip cu c=mpul definit `n structur\. avem: ionescu. iar necunoscut este o variabil\ de tip pointer la structura Persoana .varsta = 41. Accesul la c=mpurile unei astfel de variabile(pointer la o structur\) se face ad\ug=nd dup\ numele varibilei pointer o “s\geat\” (“->”) . Exemplu: necunoscut = &ionescu.48627669. dan.ziua este de tip short. O form\ echivalent\ este urm\toarea: (*necunoscut).varsta = (*necunoscut). dan. urm\rind exemplele din paragraful precedent. `nc=t o astfel de expresie are sens doar dac\ structurile sunt de acela[i tip.nume.de pild\. Prin aceasta. Dou\ structuri de acela[i fel pot s\ apar\ `ntr-o expresie de atribuire. amicul. Ini]ializarea unei variabile de tip structur\ se poate face `n maniera `n care se ini]ializeaz\ un tablou: se descrie cu ajutorul unei liste de valori ini]iale c=mpurile structurii: Persoana ionescu = { "Ionescu". dan.

NULL. printf("\n"). printf("Al doilea arbore este: \n"). NULL)). struct Arbore *stang. /* s-a definit tipul "valoare" pentru **informatia din nodurile arborelui*/ typedef struct Arbore{ valoare val. liste. } Arbore. afisare(a1).Gheorghe GRIGORAŞ 7. a2=adauga(10. struct Arbore* stang. printf("Primul arbore este: \n"). a1. struct Arbore* drept. void afisare (Arbore* a). Arbore* d). adauga(4. NULL. NULL)). NULL). S\ observ\m c\ structura Arbore se autoreferen]iaz\: printre c=mpurile structurii arbore sunt dou\ care sunt de acela]i tip struct Arbore. adauga(20. Arbore* a2. } valoare. Arbore* s.. # include <stdio. struct Arbore *drept. } Arbore.4. Arbore* s. a1=adauga(1. NULL). printf("\n"). unul la subarborele st=ng altul la cel drept. arbori etc.h> # include <stlib. adauga(3. int main( ){ Arbore* a1. return 0. NULL. Iat\ cum poate fi definit\ o astfel de structur\: typedef struct { . Arbore* adauga(valoare v. fiecare nod este compus dintr-o informa]ie (valoarea nodului) [i doi pointeri. } Arbore* adauga(valoare v. adauga(2..h> typedef int valoare. Din acest motiv structura are un nume: Arbore. `ntr-un arbore binar. Programul Arbori binari. Programul urm\tor ilustreaz\ utilizarea unei structuri autoreferen]iate: se construiesc doi arbori binari folosind func]ia “adauga” [i se afi[eaz\ un arbore `n nota]ia infix (func]ia “afisare”). De pild\. afisare(a2). Structuri autoreferenţiate Utilizarea structurilor permite construirea de structuri de date evoluate ca: fi[iere. Arbore* d){ 62 . typedef struct Arbore{ valoare val..

48627669.doc

} 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))

Arbore* c; c=malloc (sizeof (Arbore)); c->val = v; c->stang = s; c->drept = d; return c;

7.5. Tipul enumerare
Definirea unui tip enumerare se face prin instruc]iunea: enum nume { Un tip enumerare permite ca, lista_de_identificatori}; `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; Evident se poate redenumi [i tipul enumerare: Typedef enum {da, nu} Bool Bool raspuns=nu;

63

Gheorghe GRIGORAŞ

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 };

Lista de declara]ii, spre deosebire de cea de la structur\, care definea c=mpurile acesteia, define[te o list\ de alegeri posibile. Uniunea trebuie privit\ ca o structur\ `n care membrii ocup\ aceea[i zon\ de memorie; dimensiunea memoriei alocat\ pentru o variabil\ de tip uniune este dimensiunea celui mai mare membru al uniunii. S\ not\m c\, la un moment dat doar un membru al uniunii poate ocupa memoria. ~n exemplul urm\tor se specific\ faptul c\ un punct `n plan poate fi definit fie prin coordonatele sale carteziene fie prin cele polare. 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) : typedef enum {cart=1,pol=2,nec=0} TipCoord; typedef union { TipCoord tip; struct { TipCoord tip; long abscisa; long ordonata; } cart;
64

48627669.doc

struct { TidCoord tip; float ro; float teta; } pol; } Coordonate; C=mpul “tip” este prezent `n toate alternativele uniunii [i el poate fi consultat prin referin]a p1.tip sau p1.cart.tip sau p1.pol.tip. Se mai poate elimina [i aceast\ redondan]\ prin urm\toarea declara]ie: typedef struct { TipCoord tip; union { struct { long abscisa; long ordonata; } cart; struct { float ro; float teta; } pol; } val; } Coordonate; Dezavantajul este c\ numirea coordonatelor se face printr-o “cascad\” mai mare : p1.val.cart.abscisa p1.val.cart.ordonata , dac\ p1.tip=1 p2.val.pol.ro p2.val.pol.teta , dac\ p2.tip=2

7.7. Exerciţii
1. Scrie]i un program pentru consultarea unei agende telefonice la nivelul personalului unei societ\]i. Pentru aceasta va trebui s\ se realizeze urm\toarele: 1.1 crearea agendei telefonice sub forma unui fi[ier text. Acest fi[ier va con]ine o mul]ime de linii, fiecare av=nd c=te dou\ c=mpuri: un [ir de caractere ce `nseamn\ identitatea abonatului [i un num\r care corespunde num\rului s\u de telefon. Iat\ un exemplu: andrei 1427 anca 2130 ana 2131 barbu2140 bogdan 1430 … … [tefan 2143 victor 2114 zeno 1442 1.2 crearea programului care realizeaz\ urm\toarele:
65

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\). while ((compar>0) && (i<n)) { compar=strcmp(cineva.h> # define dim_agenda 100 # define lung_nume 20 typedef char sir[lung_nume] typedef struct { sir nume.Gheorghe GRIGORAŞ 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\). } persoana. int i. b) completarea tabloului de structuri cu noi adrese.8. 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. /* s-a definit agenda ca un tablou de persoane */ int n=0. agenda[i].nume). # include <stdio. /* numarul persoanelor din agenda */ /* urmeaza functia de cautare secventiala */ int cauta_secv(char cineva[ ]) { int compar=1. int tel. ora[. i++.: 2143  quit 2. 7. De exemplu:  anca tel.: 2130  anuta persoan\ necunoscut\  [tefan tel. /* s-a definit o structura de tip persoana*/ persoana agenda[dim_agenda]. int i=0. } return (compar==0)? i-1:-1. int b=n-1. Soluţii 1. codul po[tal). c) afi[area pe ecran a listei de adrese. } /* urmeaza functia de cautare dihotomica */ int cauta_dih(char cineva[ ]){ int compar=1. while ((compar!=0) && (a<=b)) { 66 .h> # include <string. int a=0. strada.

agenda[i].txt". compar=strcmp(cineva. printf("Consultare agenda telefonica\n"). printf("\t sau "quit" pentru sfarsit \n").&(agenda[n]. select_meniu -afi[area op]iunilor. if (compar<0) b=i-1. /* initializarea agendei telefonice */ fisier=fopen("telefon. } 2./* se cauta in prima parte */ else if (compar>0) a=i+1.nume). scanf("%s". printf("\t Dati prenumele celui cautat \n"). } } return 0. n++.%s:%d\n". &(agenda[n]. "quit")==0).%s:necunoscut!\n". fin=(strcmp(cineva. */ if (i==-1) printf("tel. introducere -ad\ugarea unui nou nume `n urm\toarea structur\ liber\."%s%d". int i.cineva). i=(a+b)/2.agenda[i]. afiseaz\ -afi[area listei de adrese.tel)). Programul con]ine func]iile: init_lista -ini]ializarea listei.48627669. fin=0. sir cineva. while (!fin) { printf(">"). /* sau i=cauta_dih(cineva).cineva. if (!fin) { i=cauta_secv(cineva). & cineva)."r"). else printf("tel. } return (compar==0)? i:-1.tel).nume).doc } int main(void){ FILE* fisier. sterge -[tergerea unei adrese. gaseste_liber -exploreaz\ tabloul de structuri `n c\utarea unui element nefolosit. } while (!feof(fisier))./* se cauta in a doua parte */ /* Program pentru listarea unor adrese folosind un **tablou de structuri*/ 67 . do { fscanf(fisier.

Iesire din program \n"). gaseste_liber(void). printf("3. } while (c<0 || c>4). Introduceti un nume \n"). void sterge(void). printf("1. printf("2.h> # include <stdlib. liber=gaseste_liber(). unsigned long int cod_postal.) { optiune=select_meniu(). char strada[40]. switch(optiune) { case 1: introducere().: ").h> # define MAX 100 struct adresa { char nume[30]. int select_meniu(void). afiseaza(void). case 2: sterge(). void main(void){ char optiune. } void introducere(void){ int liber.Gheorghe GRIGORAŞ # include <stdio.t<MAX. case 3: afiseaza(). char oras[20]. 68 . c=atoi(s). unsigned long int numar.++t)adresa_info[t]. case 4: exit(0). Stergeti un nume \n"). char s[80]. int c. void init_lista(void). for(t=0. return c. } int select_meniu(void){ char s[80]. for(. printf("4. break. break. introducere(void). break. gets(s). do { printf("\n Introduceti optiunea dvs.nume[0]= °\0°. Afisati fisierul \n"). init_lista().. } adresa_info[MAX]. } } } void init_lista(void){ register int t.

gets(adresa_info[liber].10).++t).oras).nume). } } printf("\n\n").nume). if (t==MAX) return -1.doc } gaseste_liber(void){ register int t.nume[0]) { printf("%s\n". } printf("Introduceti numele: "). gets(s). inregistrarii: "). printf("%s\n". ++t) { if (adresa_info[t]. printf("%s\n". } if (liber==-1) { printf("\n Lista este completa.nume[0]&&t<MAX.10).cod_postal= strtoul(s. printf("Introduceti numarul: "). } void sterge(void){ register int liber.numar=strtoul(s.adresa_info[t].adresa_info[t]. printf("Introduceti nr. adresa_info[liber]. for (t=0. adresa_info[t]. gets(adresa_info[liber]. "). gets(adresa_info[liber]. printf("Introduceti numele strazii: "). printf("Introduceti numele orasului: "). °\0°.numar). printf("%lu\n".nume[0]= °\0°.adresa_info[t].adresa_info[t]. printf("%lu\n". °\0°. adresa_info[liber].cod_postal).adresa_info[t].oras). } void afiseaza(void){ register int t. return.strada). gets(s).48627669. t<MAX. printf("Introduceti codul postal: "). liber=atoi(s). if (liber>=0 & liber<MAX) adresa_info[liber]. 69 . for(t=0.strada). char s[80]. gets(s). /* Nu mai este loc in lista*/ return t.

9 Solu]ii Limbajul C ofer\ programatorului posibilitatea de a preciza mecanismul pe care-l dore[te pentru memorarea unei variabile.2 Gestiunea automat\ a memoriei 8. `n segmentul datelor programului. • automat\.5 Variabile globale 8. `n memoria disponibil\.Cap 8 GESTIUNEA MEMORIEI 8.8 Exerci]ii 8. ~n acela[i timp `ns\. ~n general programatorul nu trebuie s\ se g=ndeasc\ explicit la un mecanism anume de memorare. `n stiva de execu]ie. nu este lipsit de interes ca programatorul s\ cunoasc\ particularit\]ile fiec\rui tip de mecanism de memorare [i de asemenea s\ cunoasc\ modul `n care compilatorul va administra variabilele pe care le declar\ `n program.3 Gestionarea “register” a memoriei 8. Memorarea poate fi: • static\.4 Gestionarea static\ a memoriei 8. . Compilatorul asociaz\ `n mod automat unei variabile un tip de memorare care corespunde locului unde s-a f\cut declararea.1 Precizarea unui mecanism de memorare 8. • `ntr-un registru al calculatorului. • dinamic\. Acest mecanism se refer\ la gestionarea memoriei `n cursul execu]iei programului.6 Declararea variabilelor externe 8.7 Gestiunea dinamic\ a memoriei 8.

char mesaj[ ] = "Mesaj initial". `n lipsa acestuia. Durata de via]\ [i vizibilitatea unei variabile “auto” vor fi limitate la interiorul blocului `n care este definit\.vizibilitatea variabilei: identificarea p\r]ii din program capabil\ s\ foloseasc\ acea variabil\. tip unde: mem –este unul din cuvintele cheie: auto. va fi nedefinit\. Tipul variabilei va determina: . register. dac\ nu este dat\ explicit. posed\ un anume tip [i este administrat\ de un anume mecanism de memorare. S\ mai not\m c\ limbajul C standard (ISO) permite ini]ializarea tablourilor [i structurilor `n cazul gestiunii automate a memoriei. Cuv=ntul cheie “auto” nu este obligatoriu.el este implicit */ /* x are o valoare nedefinita pe cand p este un **pointer care are ca valoare adresa lui x */ 71 .2. tip [i trebuie s\ fie totdeauna `n interiorul unui bloc. Gestiunea automată a memoriei Variabilele cu gestiune automat\ corespund variabilelor alocate `n stivele de execu]ie. Ini]ializarea unei variabile “auto” se va efectua la fiecare intrare `n bloc. . tip – este cuv=ntul cheie ce define[te tipul variabilei. o variabil\ este identificat\ printr-un nume (identificator). Exemple: auto float x. A[adar. Precizarea unui mecanism de memorare Programatorul are posibilitatea s\ precizeze un mecanism de memorare prin instruc]iunea: mem identificator.dimensiunea zonei de memorie alocat\ pentru a reprezenta variabila.1. Declararea se face prin: auto identificator . 8. extern. o variabil\ definit\ `ntr-un bloc va fi o variabil\ cu gestiune automat\. identificator – este numele variabilei. static.doc 8.durata de via]\ a variabilei: perioada de timp `n care variabila este accesibil\.interpretarea con]inutului variabilei atunci c=nd ea este supus\ unor instruc]iuni.48627669. `ncep=nd cu locul de declarare. /*cuvantul auto a fost omis.ini]ializarea variabilei: con]inutul implicit (dac\ exist\ unul) al variabilei la crearea sa. Vom trece `n revist\ aceste mecanisme de memorare. Categoria de memorare (mem) c\reia-i apar]ine variabila va determina: . valoarea ini]ial\. . . auto float *p = &x.

Exemple de utilizare a unor astfel de variabile sunt `n solu]ia exerci]iului 2 din capitolul precedent. Variabilele statice sunt alocate `n segmentul de date al programului.5. pointeri. prin urmare nu se poate defini o variabil\ global\ `n corpul unei func]ii. Ea este definit\ `ncep=nd cu declara]ia sa. acesta ]ine cont de ea at=ta timp c=t exist\ regi[tri disponibili `n ma[in\. 8. se folose[te cuv=ntul cheie “extern”. Implicit sunt ini]ializate cu 0 la `nc\rcarea programului. este imposibil a se ob]ine adresa unei astfel de variabile.evitarea transmiterii unor argumente la func]ii apelate. Cum num\rul de regi[tri este limitat [i depinde de tipul de ma[in\ pe care ruleaz\ programul. register tip identificator Cuv=ntul cheie “register” permite programatorului s\ indice faptul c\ variabila ce se define[te se memoreaz\ `n unul din regi[trii calculatorului. Variabile globale O variabil\ global\ este o variabil\ static\ care poate fi referen]iat\ `n orice loc al programului. ~n acela[i timp ele permit: .3. implicit. 8. Gestionarea statică a memoriei static tip identificator . oferindu-le posibilitatea s\ accead\ la aceste argumente. ~n cazul tablourilor sau structurilor. declarate `n alte fi[iere. `ntregi. durata lor de via]\ este timpul de execu]ie al programului `nsu[i. p=n\ la sf=r[itul fi[ierului surs\.`n interiorul unui bloc: va fi vizibil\ doar `n blocul acela (la fel ca variabilele auto). Utilizarea acestei clase de memorare trebuie v\zut\ ca o directiv\ de optimizare dat\ compilatorului. Vizibilitatea unei astfel de variabile statice depinde de locul `n care a fost declarat\: .`n exteriorul unui bloc: va fi vizibil\ `ncep=nd cu definirea sa p=n\ la sf=r[itul fi[ierului. Gestionarea “register” a memoriei . Declara]ia “register” trebuie s\ fie plasat\ `n interiorul unui bloc. cerin]a aceasta este satisf\cut\ `n mod real doar dac\ este posibil\. . Este u[or de `n]eles c\. `nainte de execu]ia func]iei main.4. Ea este efectiv\ doar pentru variabilele care pot fi codificate pe un cuv=nt-ma[in\: caractere. ~n plus. ansamblul c=mpurilor va fi ini]ializat cu zero. nedefinit\. Pentru a defini o variabil\ global\ `n alt fi[ier. `n exteriorul oric\rui bloc.Gheorghe GRIGORAŞ 8. Valoarea ini]ial\ a unei variabile registru este. [i 72 . O astfel de variabil\ se declar\ prin: tip identificator . utilizarea unei variabile globale vine `n contradic]ie cu principiile program\rii modulare.

y. fun1(void){.. extern char c. Durata de via]\ a unei variabile alocat\ dinamic este explicit\: -variabila este creat\ `n urma execu]iei opera]iei de alocare a memoriei (func]ia “malloc” `n C [i operatorul “new” `n C++). . main(void){ . Aceast\ gestiune se efectueaz\ `n memoria disponibil\ care se nume[te “gr\mad\” (heap)... Aceast\ facilitate este legat\ de faptul c\ limbajul C permite compilarea [i legarea separat\ a diferitelor module de program: prin declararea unei variabile extern se comunic\ tuturor fi[ierelor variabilele globale necesare programului. este echivalent\ cu: void functie (char)... Exemple: Fi[ier 1 int x. Fi[ier 2 extern int x.doc - av=nd `n fi[ierul local specificarea extern. 73 .x=. } . ~n cazul func]iilor important este s\ se descrie signatura sa. Declararea variabilelor externe O variabil\ extern\ poate fi declarat\ `n orice punct al programului prin: extern identificator ..48627669. Fi[ier 2 extern int x.}.. cuv=ntul extern este facultativ..y=. 8. funct1(void) { x=. Gestiunea dinamică a memoriei Gestiunea dinamic\ a memoriei permite crearea de noi variabile pe parcursul execu]iei programului. .7.}. ini]ializarea structurilor [i tablourilor fie `n mod explicit indic=nd valori ini]iale. fie implicit cu valori 0.6.. Cuv=ntul rezervat extern indic\ compilatorului faptul c\ tipurile [i numele variabilelor care urmeaz\ au fost declarate `n alt\ parte [i nu mai aloc\ din nou spa]iu de memorie pentru acestea. tip Aceast\ declara]ie permite declararea local\ a unei variabile definit\ `n alt fi[ier(cu acela[i nume)... adic\ tipul rezultatului [i al parametrilor de apel... fun2(void){.. -variabila dispare `n urma execu]iei opera]iei de restituire a memoriei (func]ia “free” `n C [i operatorul “delete” `n C++). Ea este referen]iat\ folosind o variabil\ pointer (vezi cap. 6) care con]ine adresa sa. S\ not\m c\ o variabil\ alocat\ dinamic nu are un nume explicit.. Aten]ie `ns\ c\ o variabil\ global\ poate fi modificat\ indirect pe perioada apelului la o func]ie. Declara]ia: extern void functie(char).y.y. char c. extern char c. 8.. De aceea. } ~n cazul declar\rii func]iilor ce se definesc `n alt modul (fi[ier).

pop. -prog. void push(char c){stiva[index++]=c. Soluţii 1.} 74 . De exemplu: Persoana *ptr. stiva_plin\. int stiva_vida(void).h. 8. citirea se va face p=n\ la `nt=lnirea sf=r[itului de fi[ier sau p=n\ la umplerea stivei. static char stiva[dim].c. care con]ine modulul principal.h” care are con]inutul: # define dimensiune_sir 80 # define dimensiune_stiva 10 typedef char sir[dimensiune_sir]. void pop(void).c. care con]ine implementarea func]iilor.9. care s\ implementeze func]iile uzuale aplicate unei stive de caractere: push. -stiva. char top_stiva(void).c : modul de gestionare a stivei de **caractere */ # define dim 100. Pornind de la acest modul scrie]i un program test care realizeaz\: a) citirea unui [ir de [iruri de caractere care se vor “`mpinge” `n stiv\ (se vor stivui).c */ void push(char).} int stiva_vida(){return(index==0). int stiva_plina(void). S\ se construiasc\ un program. ptr=malloc(sizeof(Persoana)). 2. stiva_vid\. Avem aici de-a face cu o variabil\ alocat\ dinamic care este referen]iat\ cu ajutorul pointerului ptr prin *ptr. Utiliza]i func]iile de manipulare a [irurilor de caractere (Anexa ) pentru definirea func]iilor acestui modul.8.h : header ce contine declaratiile **functiilor din modulul stiva. 8.} void pop(){--index. Modulele vor fi: -stiva. Exerciţii 1.c. Caracteristicile modulului sunt definite `n fi[ierul header “stiva. void push(const sir ch). /* stiva.Gheorghe GRIGORAŞ vizibilitatea unei variabile alocat\ dinamic este legat\ de tipul de gestiune al pointerilor care referen]iaz\ indirect acea variabil\. format din trei module. Defini]i un modul pentru gestionarea unei stive de [iruri de caractere. void pop(sir ch). int stiva_plina(void). int stiva_vida(void). static int index=0. care con]ine declara]iile func]iilor din modulul stiva.} char top_stiva(){return(stiva[index-1]). b) scoate [irurile din stiv\ [i le afi[eaz\ (evident `n ordinea invers\ stivuirii). top. /* stiva.

c : modulul principal */ # include "stiva. index++.c). /* indicile top-ului stivei */ static sir stiva[dimensiune_stiva]. /*stiva. } printf("\n"). } 2.h> # include <string. printf(">"). /*modul. int stiva_vida(void). int stiva_plina(void). printf("Incarcati stiva: \n>").h" /* ** variabile cu clasa de memorare *static*. } return 0. void pop(sir ch). while (!stiva_vida()) { element=top_stiva(). */ # include <stdio. void push(const sir ch).h> int main() { char element.h> # include <assert. printf("Iata continutul stivei: \n").h> # include "stiva. pop().} /* prog. strcpy(stiva[index].&element)!=EOF){ push(element). printf("<%c\n".c" # include <stdlib.c ** Gestionarea unei stive de siruri de caractere.h> # include <stdio. */ assert(!stiva_plina()).h*/ # define dimensiune_sir 80 # define dimensiune_stiva 10 typedef char sir[dimensiune_sir].h" # include "stiva.doc int stiva_plina(){return(index==dim). Inainte de aceasta se apeleaza functia **assert care impune o conditie pentru a continua **executia: stiva sa nu fie plina. void push(const sir c){ /* Se copie c in stiva dupa care se incrementeaza **index. while(!stiva_plina()&&scanf("%c". */ static int index=0. 75 .element). **nevizibile in alte fisiere.48627669.

x)!=EOF) { push(x).h> # include "stiva.Gheorghe GRIGORAŞ } } void pop(sir c){ /* se decrementeaza index apoi se copie top-ul **stivei in c */ assert(!stiva_vida()). } return 0. while(!stiva_plina()&&scanf("%s". printf("Se incarca stiva: \n>"). } int stiva_vida(void){ return(index==0). printf(">"). --index.x).} int stiva_plina(void){ return(index==dimensiune_stiva).c : programul de test ce consta din doua **iteratii: prima pentru citirea din fisierul de **intrare si stivuirea informatiei.h" int main(void){ sir x. */ # include <stdio. printf("<%s\n".stiva[index]). a doua pentru **afisarea rezultatului destivuirii. 76 . while (!stiva_goala()) { pop(x). strcpy(c. printf("Iata continutul stivei: \n"). } printf("\n"). } /* test.

1. Evaluarea expresiilor aritmetice 9.1. 2. f=i.3. int i=2..5. asignarea cu tipuri diferite ale variabilelor termeni ai asignării: float f. Conversii de pointeri. int i=10.. Evaluarea expresiilor logice 9.. if (pi>2) pi=pi/i.1 Mecanisme de conversie 9.14. Trebuie s\ facem distinc]ia `ntre dou\ maniere de conversie: aceea care are drept scop schimbarea interpret\rii con]inutului unei variabile [i conversia care are drept consecin]\ modificarea con]inutului unei variabile.1.2. ~n al doilea caz se poate converti o valoare real\ la o valoare `ntreag\. evaluarea unei expresii aritmetice sau logice în care componentele expresiei au tipuri diferite: float pi=3. Pointerul universal. Conversii explicite 9..1.Cap 9 CONVERSIA DE TIP 9. se poate interpreta con]inutul unei variabile de tip caracter ca fiind o valoare `ntreag\ [i drept urmare posibilitatea utiliz\rii acesteia `ntr-o expresie aritmetic\. . ca o consecin]\ se pierde valoarea frac]ionar\ a variabilei reale. ..1.1. Mecanisme de conversie Se disting patru cazuri `n care `ntr-un program C se aplică un mecanism de conversie: 1. Conversia de tip `n limbajul C ofer\ un mecanism simplu pentru evaluarea expresiilor aritmetice [i pentru transmiterea parametrilor.4. ~n primul caz de pild\.1. Conversia la asignare 9. 9.

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\ destinatarul este un tip far\ semn. 3. apare o eroare (Floating point exception). Dac\ valoarea p\r]ii `ntregi a sursei este prea mare pentru a fi reprezentat\ `ntr-un `ntreg. 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\. 78 . poten]ial. o pierdere de informa]ie.1 Conversia la asignare ~n conversia la asignare. bitul semn `n schimb nu se mai “transfer\”: unsigned long=int/short/char unsigned=short/char unsigned short=char 2. utilizarea operatorilor de conversie: float f1=(float)14/5. /* f1=2.Gheorghe GRIGORAŞ 3. Alte conversii `n care intervin tipuri definite de programator sunt considerate ilicite [i sunt respinse de compilator. lucrurile se petrec dup\ cum urmeaz\: 1. /*caracterul ‘z’ este convertit la un intreg */ ~n cazul `n care se utilizeaz\ operatori de conversie. compilatorul este cel care gireaz\ aceste conversii. asignarea unei valori reale `n dubl\ precizie la o variabil\ real\ `n simpl\ precizie: float=double ~n acest caz exist\ o pierdere a preciziei reprezent\rii valorii reale.8 */ float f2=14/5. Poate ap\rea [i aici eroarea “Floating point exception” dac\ partea exponent este prea mare pentru o variabil\ real\ `n simpl\ precizie. 9. (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). c=nd apar dou\ tipuri diferite. Conversiile `ntre tipurile de baz\ ale limbajului sunt considerate permise iar tratamentul la care sunt supuse datele de c\tre compilator este bine stabilit de regulile limbajului. Vom detalia `n continuare aceste mecanisme. mecanismul este acela[i.’z’). /* f2=2.1.0 */ apelul unei funcţii: printf(“%d\n”.

Faza II: . • asignarea valorilor 0-1: dac\ evaluarea expresiilor este “false” (true).48627669.. etc.. f\r\ semn.tipul float este convertit la double.doc 9. Exemple: x=50.. real.1. Evaluarea expresiilor logice Rezultatul evalu\rii unei expresii logice va fi 0 (reprezent=nd “false”) sau 1 (reprezent=nd “true”).2 Evaluarea expresiilor aritmetice tipurile `ntregi mai mici dec=t int sunt convertite la int.se alege tipul de evaluare: `ntreg.3. } 79 . /* b capata valoarea 0 */ i=10 while (i--) { . ~n rezumat.1. De aceea evaluarea unei expresii logice se face prin: • evaluarea operanzilor: dac\ valoarea aritmetic\ este 0 atunci aceasta se interpreteaz\ prin “false”. valoarea asignat\ acesteia este 0 (1). `n caz contrar prin “true”. b=(x>0) && (x<31).. lucrurile se petrec astfel: - Dac\ un operand este: double unsigned long long unsigned Exemple: i (int) int int + Cel\lalt operand se converte[te la: double unsigned long long unsigned + c (char) int int + b) (float) double double Rezultatul este: double unsigned long long unsigned Faza 1: Faza 2: Rezultatul: i (int) Faza 1 Faza 2 Rezulta t Faza 1 Faza 2 Rezulta t int (a (long) long double int double double double double double 9. .

O a doua solu]ie const\ `n a utiliza tipul pointer universal void*.pentru transmiterea valorilor cu tipurile cerute ca parametri `n func]ii. O variabil\ pointer de tip void* poate primi ca valoare pointer la un tip oarecare.-“.. Aceast\ incompatibilitate se poate evita `n dou\ moduri. O prim\ solu]ie const\ `n a utiliza o conversie explicit\: . . S\ consider\m de pild\ urm\toarea secven]\: char *alocare(int dim)..25.5 Conversie de pointeri. int* ptr1 80 . Ace[ti operatori de conversie permit programatorului s\ specifice o conversie care nu se face implicit de c\tre compilator. double r. . */ .schimbarea tipului valorii returnate de o func]ie.pentru for]area conversiilor `n expresii. */ f=(float)a/b. dup\ care. i are valoarea 10 deci expresia cap\t\ valoarea “true”. Compilatorul for]eaz\ conversia [i afi[eaz\ un mesaj de avertisment (“warning”) `ntotdeauna c=nd `ntrun program apare o astfel de conversie. /* f=5. .. etc. 9.. ~n cea de-a treia linie a secven]ei de mai sus apare o asignare `ntre pointeri incompatibili.25.. */ f=a/(float)b.Gheorghe GRIGORAŞ ~nainte de prima evaluare a expresiei “i.. f=a/b.. Operanzii ce apar `n aceast\ expresie r\m=n neschimba]i.0. Exemple: int a=21. i se decrementeaz\.1. Ace[tia pot fi utiliza]i: .1. a=(int)ceil(r). b=4. Pentru exemplul precedent se procedeaz\ astfel: void* alocare(int dim). /* f5. o valoare de tip void* este implicit convertit\ la o valoare pointer de un tip oarecare. ptr = alocare(100)... int *ptr. float f. ptr=(int*) alocare(100). rezultatul expresiei este convertit la tipul indicat. Reciproc. Pointerul universal Conversia `ntre pointeri la tipuri diferite nu este implicit\. r=sqrt(double(a)). /* f=5.4 Conversii explicite Conversiile explicite se exprim\ prin: (tip) expresie sau tip ( expresie ) At=ta timp c=t conversia este permis\. /*functia ceil returneaza o valoare de tip intreg*/ 9.

ptr2=alocare(20). Asign\rile pentru ptr1. 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. 81 .48627669. 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.doc double* ptr2 ptr1=alocare(10).

La apari]ia acestui identificator `n program.2 Macroinstruc]iuni tip func]ie ~n codul surs\ al unui program C se pot include instruc]iuni destinate compilatorului. preprocesorul substituie secven]a corespunz\toare de instruc]iuni `n locul acestui identificator.1.2 Includerea fi[ierelor 10. Rezultatul activit\]ii preprocesorului este un fi[ier surs\ `n care sunt tratate toate directivele de precompilare [i care este transmis compilatorului. Programatorul asociaz\ o secven]\ de instruc]iuni unui identificator.1.1.2.1. acestea se numesc directive pentru preprocesor.4 Directiva #error 10. Preprocesorul realizeaz\ o faz\ de precompilare care are ca obiect: • includerea unor fi[iere (specificate) `n program. • compil\ri condi]ionate conform unor parametri (valori) transmise `n comanda de compilare.1 Directive preprocesor 10.2 Macroinstruc]iuni 10. • definirea unor constante simbolice.Cap 10 PREPROCESORUL 10.1 Constante simbolice. Precompilarea este o faz\ de prelucrare independent\ de compilarea propriu-zis\.1 Macroinstruc]iuni predefinite 10.2. • definirea macroinstruc]iunilor.3 Compilare condi]ionat\ 10. acestea sunt directive c\tre preprocesor.1 Directive preprocesor Preprocesorul trateaz\ doar liniile ce `ncep prin caracterul “#”. Directiva #define 10. ~n acela[i timp `ns\. 10. O directiv\ este de forma: # instruc]iune argumente Principalele instruc]iuni pentru preprocesor sunt: . ea face parte integrant\ din procesul de compilare: apelul compilatorului pentru un program execut\ mai `nt=i `nc\rcarea preprocesorului.

1. # define UNU . Forma acestei directive este: # include <nume_fisier> /* se caut\ fi[ierul `ncep=nd cu directoarele standard */ 83 ... Acest mecanism permite: • a asigna unui identificator un [ir de caractere. `n textul surs\.48627669. Exemplu: # define EOF (-1) . Directiva #define O constant\ simbolic\ asociaz\ unui identificator un [ir de caractere... Constanta simbolic\ se define[te cu directiva “define”: # define identificator [ir_de_caractere Exemple: # define NULL 0L # define TRUE 1 # define FALSE 0 # define EOF (-1) Utilizarea constantelor simbolice are diverse scopuri. prin [irul de caractere asociat.doc define if elif line ifndef else include error undef endif ifdif pragma De notat c\ un r=nd `n fi[ierul surs\ C nu poate con]ine mai mult de o directiv\. Preprocesorul `nlocuie[te fiecare apari]ie a identificatorului. • a defini existen]a unei constante simbolice: # define ident • a suprima defini]ia [i existen]a unei constante simbolice: # undef ident Vizibilitatea constantelor simbolice `ncepe cu definirea lor (directiva #define) [i ]ine p=n\ la sf=r[itul fi[ierului.1. 10.2 Includerea fişierelor Directiva #include cere compilatorului s\ ia `n considerare [i un alt fi[ier surs\ `n afar\ de cel `n care se afl\ directiva.1 Constante simbolice. 10..... cu excep]ia cazului c=nd `n acesta apare o directiv\ #undefine pentru identificatorul corespunz\tor.. # undefine UNU .

Directiva “else” ofer\ o alternativ\ `n cazul `n care “if” e[ueaz\. # elif expresie1 cod1. 3.3 Compilare condiţionată Directivele de compilare condi]ionat\ permit compilarea selectiv\ a unor por]iuni din programul surs\. . 10.. # elif expresie2 cod2. doar dac\ expresia este evaluat\ la “true” (`n caz contrar aceast\ por]iune de cod este ignorat\ de compilator).1. • a insera fi[iere “header” (care au extensia ‘. constante simbolice [i macroinstruc]iuni standard. declara]ii de func]ii incluse `ntr-o bibliotec\.. Directiva “elif” are sensul de “else if”.. Aceste fi[iere con]in: 1. Exemplu Pentru a folosi func]iile din biblioteca matematic\ se include fi[ierul math..Gheorghe GRIGORAŞ sau # include ″nume_fisier″ /* se caut\ fi[ierul `n directorul curent sau cel indicat prin cale */ Includerea fi[ierelor poate fi utilizat\ pentru: • a insera fi[iere surs\ din biblioteci C care pot con]ine module de aplica]ii sau defini]ii de func]ii.h care con]ine declararea acestor func]ii: # include <math. defini]ii de tipuri. ea poate determina un lan] de if-else-if: # if expresie cod. este asem\n\toare instruc]iunii if-else din limbajul C.. 2. # elif expresien codn.h> . val=pow(M_PI. Aceste directive sunt: # # # # # # if expr_constanta else endif elif expr_constanta ifdef identificator ifndef identificator Directiva “if“ prin “expr_constant\” care urmeaz\ dup\ ea permite includerea por]iunii de cod `ntre “if” [i “endif” `n procesul de compilare. # endif 84 .h se afl\ defini]ia constantei M_PI [i a func]iei pow( ). /* se calculeaza puterea a n-a a lui π */ ~n fi[ierul math.h’).. (double)n).

an sunt compuse din c=te dou\ cifre ce reprezint\ `n ansamblu data conversiei fi[ierului surs\ `n cod obiect. • optimizarea unor coduri utiliz=nd avantajele specifice fiec\rei ma[ini. _TIME_.2 Macroinstruţiuni Prin acest mecanism programatorul asociaz\ o secven]\ de instruc]iuni unui identificator. acesta devine noua valoare a lui _LINE_ `n punctul `n care se `nt=lne[te directiva. `ncorporate `n compilator. # line num\r “nume_fi[ier”. zi. _FILE_.1. Aici “num\r” este orice `ntreg pozitiv.48627669. Ora la care a fost executat\ aceast\ conversie este con]inut\ `n _TIME_ sub forma [irului ora/minute/secunde. _STDC_. ~n concluzie. Macroinstruc]iunea _STDC_ con]ine constanta 1 scris\ `n baza 10.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. 10. Macroinstruc]iunea _DATE_ con]ine un [ir de forma “lun\/zi/an” `n care lun\. 10.2. • traseul de execu]ie al programelor `n faza de test. # line “nume_fi[ier”. Ambele directive pot folosi o alternativ\ de forma #else dar nu [i #elif. implementarea nu este `n variant\ standard. _DATE_.1 Macroinstrucţiuni predefinite Limbajul standard ANSI C define[te cinci nume de macroinstruc]iuni predefinite. iar “nume_fi[ier” este un identificator valid de fi[ier care devine noua valoare a lui _FILE_. 85 . Se utilizeaz\ la depanarea programelor. Acestea sunt: _LINE_. Con]inutul acestor doi identificatori poate fi modificat prin directiva #line: # line num\r. Aceasta semnific\ faptul c\ implementarea este conform standardului ANSI C. 10. Identificatorul _LINE_ con]ine num\rul liniei de cod la compilare iar _FILE_ este un [ir care con]ine numele fi[ierului surs\ compilat.4 Directiva #error Directiva #error cere compilatorului s\ sisteze compilarea. Dac\ _STDC_ nu-i definit\ sau con]ine altceva dec=t 1. Are forma: # error mesaj La `nt=lnirea directivei este `ntrerupt\ compilarea [i se afi[eaz\ “mesaj”-ul ce este scris `n linia directivei. 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.

Gheorghe GRIGORAŞ

10.2.2 Macroinstrucţiuni tip funcţie
Aceste macroinstruc]iuni utilizator se definesc cu directiva #define: # define nume_macro secven]\_caractere Aici, “nume_macro” poate fi un identificator ce reprezint\ numele macroinstruc]iunii. Acesta, utilizat `ntr-un text surs\, va fi `nlocuit cu “secven]\_caractere” care poate `nsemna o secven]\ de instruc]iuni C (vezi [i 10.1.1). Dar “nume_macro” poate fi [i numele unei func]ii urmat\ de parametri: prin aceasta se define[te o macroinstruc]iune de tip func]ie care poate fi ‘apelat\’ `n orice punct al programului `n care a fost definit\.
Exemplu:

# define <stdio.h> # define ABS(a) (a)<0?-(a):(a) void main(void){ printf(″Valoarea absoluta a lui -1 si 1: %d%d″,ABS(-1),ABS(1)); } Folosirea func]iilor definite ca macroinstruc]iuni are, pe de o parte, un avantaj major: m\rirea vitezei de execu]ie a codului fiindc\ nu mai apare nici o `nc\rcare suplimentar\ legat\ de apelarea func]iei. Pe de alt\ parte `ns\, dac\ dimensiunea macroinstruc]iunii tip func]ie este mare, acest supliment de vitez\ este “anihilat” de cre[terea dimensiunii programului, datorit\ codului care apare de mai multe ori.

86

Cap 11 EXERCIŢII
1. S\ se a. b. c. scrie un program numit maxmin.c care s\ execute : citirea unui intreg pozitiv n; citirea a n numere reale; determinarea valorilor maxim [i minim dintre cele n numere citite;

2. S\ se scrie un program numit sumedia.c care s\ citeasc\ niste numere reale [i, pentru fiecare s\ scrie un r=nd `ntr-un tabel ce are forma: Nr.crt. Num\r Min Max Suma Media … … …. …. …. ….
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

3. S\ se scrie un program care s\ numere literele mici, literele mari , cifrele [i celelalte caractere(la un loc) dintr-un text(fi[ier). 4. S\ se scrie func]ii recursive pentru calculul factorialului unui num\r dat n, a puterilor 1,2 …, k a unui num\r n, a sumei numerelor naturale m [i n. S\ se foloseasc\ aceste func[ii `ntr-un program principal. 5. S\ se scrie o func]ie “ int este_prim(int n) ” care s\z returneze 1 dac\ num\rul n este prim [i zero `n caz contrar. S\ se scrie o func]ie “ fibonacci ( int n) “ care s\ returneze al n-ulea termen al [irului lui Fibonacci. S\ se foloseasc\ cele dou\ func]ii pentru a verifica dac\ al n-ulea termen din [irul lui Fibonacci este num\r prim ( n = 1, …, 12). 6. Folosind func]ia “este_prim( … )” de la exerci]iul precedent, scrie]i un program ce s\ verifice conjectura lui Goldbach pentru toate numerele pare dintr-un interval dat [a,b] : Orice num\r par n mai mare ca 2 este suma a dou\ numere prime. De exemplu: 700 = 17 + 683 , 702 = 11 + 691, 704 = 3 + 701, etc. 7. Urm\toarea func]ie calculeaz\, recursiv, cel mai mare divizor comun a dou\ numere `ntregi pozitive p [i q: int cmmdc_r(int p, int q) { int r; if (( r = p % q ) == 0 ) return q; else return cmmdc_r(q, r); } Scrie]i un program pentru testarea acestei func]ii precum [i pentru calculul celui mai mare divizor comun a n numere date. Scrie]i apoi [i testa]i varianta iterativ\ a func]iei, cu numele : int cmmdc_i (int p, int q) 8. Descrie]i [i implementa]i trei algoritmi de sortare.

Gheorghe GRIGORAŞ

9. Construi]i o func]ie “ int numar_cuvinte(const char *s) “ care s\ returneze numarul cuvintelor din [irul s ( cuvintele sunt desp\r]ite prin spa]iu/spa]ii). S\ se testeze aceast\ func]ie pentru un [ir anume(fi[ier). 10. S\ se scrie [i apoi s\ se testeze func]ii pentru adunarea a doi vectori [i pentru adunarea a dou\ matrice. 11. S\ se scrie un program `n care s\ se foloseasc\ func]ia sistemului : void qsort(void *array, size_t n_els,size_t el_size, int compare(const void *, const void *)) pentru a sorta o list\ de numere reale `n ordinea cresc\toare relativ la p\r]ile frac]ionare a acestor numere. De exemplu lista: 2.43, 45.01, 23.90, 123.04, 0.98 este sortat\ astfel: 45.01, 123.04, 2.43, 23.90, 0.98 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. 13.Fie a un tablou bidimensional (m x n). Un punct sa al acestui tablou este un element a[i0,j0]cu proprietatea: a[i0,j0] = min{a[i0,j] : 0<=j<=n-1} = max{a[i,j0] : 0<=i<=m-1} Scrieti un program care determina punctele sa (daca exista) ale unui tablou bidimensional. 14. Se da o matrice patratica. Sa se ordoneze crescator fiecare linie a matricii, apoi sa se rearanjeze liniile astfel incat suma elementelor de pe diagonala sa fie minima. 15. Scrieti un program care, avand la intrare doua siruri de caractere, determina cel mai lung subsir comun si pozitiile la care acesta incepe in fiecare dintre cele doua siruri. 16. Proiectati structuri de date pentru reprezentarea unui punct, a unui triunghi, dreptunghi, cerc. Scrieti proceduri de citire si scriere a unui punct, triunghi etc. Scrieti o procedura care determina, pentru un triunghi dat, numarul punctelor de coordonate intregi aflate in interiorul sau. Scrieti o procedura similara pentru cerc. 17. Proiectati o structura de date pentru reprezentarea datei calendaristice si scrieti subprograme care:

88

48627669. Bucure[ti. manual pentru licee de informatic\. calculeaza data calendaristica care precede o anumita data. Ia[i. 1992. Aplica]ii `n C [i C++. 4.XI. Editura Teora. BIBLIOGRAFIE 1. [i al]ii. 18. Sa se proiecteze o structura de date pentru reprezentarea multimilor finite de numere complexe si sa se scrie proceduri care realizeaza operatii cu multimi de numere complexe reprezentate astfel. Bucuresti.Limbajul C++ Volumul III . Programarea calculatoarelor:Fundamente.. Liviu Negrescu Limbajele C si C++ pentru incepatori. Grigora[.doc • verifica daca valoarea unei variabile din structura este o data valida. Musc\. Herbert Schildt C . A. 6. Editura Didactic\.C. Informatic\ aplicat\. • • calculeaza data calendaristica care urmeaza unei anumite date.Kalisz. Gh. 1998. 5. Cristea.Giumale. Limbajul C standard. Ed.Limbajele C si C++ in Aplicatii 3. Editura “Spiru Haret”. cls. 1999.. E. Editura Teora. Cluj-Napoca Volumul I .Limbajul C Volumul II . Bucure[ti 1998 89 . Teora 1998 2. B. P\tru]. Gh. vol I.P\nsiu.Manual Complet.V.III.

. /* isupper(int c). /* isgraph(int c). <limits. h> <signal.h > <stdio. /* isxdigit(int c). grafic? */ litera mica? */ tiparibil? */ car. /* ispunct(int c). Fi[ierul <errno.h> con]ine macrouri folosite pentru raportarea erorilor.h > <math. /* iscntrl(int c). de control? */ cifra? */ car.h> con]ine macrouri (func]ii) pentru testarea caracterelor: • • • • • • • • • • • int int int int int int int int int int int isalnum(int c).h> <time. /* c c c c c c c c c c c este este este este este este este este este este este alfanumeric? */ alfabetic? */ car. h> <stdarg. /* isspace(int c).ANEXA Biblioteca standard C FI{IERE HEADER <assert. Fi[ierul <ctype.h> con]ine macro-ul assert() • void assert (int expr).h> Fi[ierul <assert.h> <stdlib.h > <setjmp. h> <stddef. /* isprint(int c). /* islower(int c). este tip\rit un mesaj(diagnostic) [i se iese din program.h > 1.h> <string./* isalpha(int c). /* isdigit(int c). Dac\ expr este zero.h > <float.h > <errno. punctuatie? */ spatiu? */ litera mare? */ cifra hexa? */ Mai con]ine: int tolower (int c) [i int toupper ( int c) funcii ce permit transformarea literelor din mari ]n mici sau invers. h> <ctype. 3.h > <locale. 2.

h> con]ine prototipuri pentru func]iile matematice: 4. • FILE *tmpfile (void). tanh ( double x). /* Pozi]ioneaz\ indicatorul pentru urm\toarea opera]ie `n fi[ier la “place” + “offset” */ • long ftell (FILE *fp). const char *mode). double acos ( double x). FILENAME_MAX. int place). sinh ( double x). • • • • • • • • • • • 8. Fi[ierul <stdio. 5. /* Returneaz\ valoarea indicatorului de pozi]ie a fi[ierului pointat de fp*/ • void rewind (FILE *fp). 10. Fi[ierul <stddef. EOF.h> con]ine o redefinire (typedef) de tip [i trei m macrouri ce permit scrierea de func]ii cu un num\r variabil de argument ( ca [i printf ).48627669. fmod ( double x. tan ( double x). DBL_EPSILON etc.h> con]ine defini]ii de tip [i macrouri ce se folosesc `n alte defini]ii: • • • • typedef typedef typedef #define char wchar_t. 6. double asin ( double x). DBL_MIN. defini]iile de tip [i prototipurile func]iilor utilizate de programator pentru a accesa fi[iere. /*tipul ob]inut din sizeof() */ NULL. FOPEN_MAX. TMP_MAX. fabs ( double x). informa]ii monetare etc. Fi[ierul <setjmp> con]ine declara]ii [i prototipuri ce permite programatorului s\ utilizeze salturi nelocale.h> con]ine construc]ii ce permit programatorului s\ m=nuiasc\ condi]ii sau semnale excep]ionale. • int fflush (FILE *fp). double x). double flor ( double x). ceil ( double x). 11. double exp ( double x). FLT_MAX. /*tipul diferen]\ de pointeri */ unsigned size_t. double log10 ( double x). stderr [i pentru structura FILE. Fi[ierul < signal.h> con]ine defini]iile unor constante pentru limitele unor valori flotante: DBL_MAX. Func]ii pentru accesul la fi[iere: • FILE *fopen (const char *filename.h> con]ine construc]ii (structuri. double y). 12. double log ( double x). cosh ( double x).h> con]ine macrourile. Fi[ierul <math. /* Seteaz\ indicatorul la `nceputul fi[ierului */ 91 . • int fclose (FILE *fp).doc Fi[irerul <float. func]ii) ce permit setarea unor propriet\]i “locale”: forma punctului zecimal. stdout. double y). Fi[ierul <limits. double sqrt ( double x). NULL. 7. INT_MAX etc.h> con]ine defini]iile unor constante ce caracterizeaz\ `ntregii: CHAR_BIT. 9. sin ( double x). double atan ( double x). atan2 ( double y. Fi[ierul <locale. Fi[ierul <stdarg. De asemenea sunt defini]i pointerii stdin. CHAR_MAX. • int fseek (FILE *fp. long offset. /* tipul wide character*/ int ptrdiff_t. double double double double double double double double double double double cos ( double x). Sunt definite aici constantele BUFSIZ. pow ( double x.

const char *s2. • void free(void *ptr). Iat\ unele dintre ele: • void *calloc(size_t n. • void *malloc(size_t size). long denumer). const char *s2). • div_t div(int numer. • double strtod(const char *s). conversie de stringuri. /* comparare a cel mult n caractere din [irurile s1 [i s2*/ • char *strncpy(char *s1. generare de numere aleatoare. • int abs(int i). size_t n_els. • char *strcat(char *s1. • long strtol(const char *s. int compare(const void *. • void *realloc(void *ptr. • void *memcpy(void *to. void *from. size_t el_size). const void *a_ptr. • void *memmove(void *to. const char *s2). • void srand(unsigned seed). • int atoi(const char *s). int base). • long labs(long i). De asemnea fi[ierul mai con]ine prototipurile func]iilor de intrare/ie[ire (vezi cap. • void *bsearch(const void *key_ptr. comunicarea cu sistemul. const void *)). /*concatenarea a cel mult n caractere din s1 la s2*/ • int strncmp(const char *s1. const char *s2. int c. const char *s2) /* copie s2 `n s1 */ • size_strlen(const char *s). size_t n) /* copie cel mult n caractere din s2 `n s1 */ 92 . • void abort(void). Fi[ierul <stdlib. • double atof(const char *s). size_t n). int c). const void *)). void *from. size_t n_els. c\utare binar\. 14. const fpos_t *pos).4). size_t el_size. int denom). /*cauta c `n [irul s*/ • int strcmp(const char *s1. const char *s2. • int rand(void). • ldiv_t ldiv(long numer. size_t n). sortare. • void exit(int status). size_t n). /*concatenare*/ • char *strchr(const char *s. • void *memset(void *p. char **end_ptr. 13. /*lungimea [irului s */ • char *strncat(char *s1. size_t n). • void qsort(void *a_ptr. size_t el_size.etc.h> con]ine prototipurile func]iilor de uz general : alocarea dinamic\ a memoriei. • long atol(const char *s). size_t size). size_t n).h> con]ine prototipuri de func]ii pentru manipularea blocurilor de memorie sau a [irurilor: • void memcmp(const void *p. const void *q.Gheorghe GRIGORAŞ • int fsetpos (FILE *fp. int compare(const void *. /* Seteaz\ indicatorul la valoarea pos */ • int rename (const char *from. size_t n). Fi[ierul <string. /* comparare [iruri*/ • char *strcpy(char *s1. const char *to).

const char *s2).23 */ /*ziua lunii 1. }. de secunde trecute de la 1 Inuarie 1970 */ • char *asctime(const struct tm *tp). Codul ASCII American Standard Code for Information Interchange 0 1 2 3 4 5 6 7 8 9 93 .59 */ /*ore 0. are ca efect scrierea datei calenderistice. • clock_t clock(void). int tm_wday. int tm_hour.60*/ /*minutr 0. De exemplu: … time_t acum. /*converte[te timpul inregistrat [i pointat de tp `ntr-un string ce reprezint\ data*/ • char *ctime (const time_t *t_ptr). /* caut\ tokenuri `n s1 folosind caracterele din s2 ca separatori */ 15.doc • char *strstr(const char *s1.data*/ • struct tm *localtime(const time_t *t_ptr). asctime(localtime(acum))). /*returneaz\ num\rul de tacturi CPU utilizate de program p=n\ aici*/ • time_t time(time_t *tp).. orei ]i cele privind ceasul intern al calculatorului. /*secunde 0. • typedef long time_t. int tm_year.11 */ /*anul de la 1900 */ /* zilele de la 0 la 6 */ /*zilele din an 0.365 */ /* Indicator de timp */ Func]ii: • typedef long clock_t.48627669.. int tm_isdst. printf("%s\n%s ".. . int tm_mon. Se folose[te structura tm care este definit\ astfel: struct tm { int tm_sec.... acum = time(NULL). int tm_min. int tm_yday. /*returneaz\ nr.31 */ /*luna anului 0.h> con]ine prototipuri ale func]iilor pentru ob]inerea datei. /* caut\ `n s1 prima apari]ie a lui s2 */ • char *strtok(char *s1. const char *s2). Fi[ierul <time. ctime(&acum). int tm_mday.. ?8 converte[te timpul pointat de t_ptr la string .

comanda man ascii produce afi[area tabelei codurilor ASCII pe ecran. • Codurile caracterelor 0-9. • Caracterele cu codurile 0-31 [i 127 nu sunt tip\ribile. 6 @ J T ^ h r | enq si em # 7 A K U _ i s } ack dle sub $ . ~n tabela urm\toare se da “semantica” unora din caracterele de pe liniile 0-2. 8 B L V ‘ j t ~ bel dc1 esc % / 9 C M W a k u del bs dc2 fs & 0 : D N X b l v ht dc3 gs ’ 1 . E O Y c m w Observa]ii: • Caracterul G este `n linia 7 [i coloana 1 deci are codul ASCII 71. 94 .z sunt contigue.Gheorghe GRIGORAŞ 0 1 2 3 4 5 6 7 8 9 10 11 12 nul nl dc4 rs ( 2 < F P Z d n x soh vt nak us ) 3 = G Q [ e o y stx np syn sp * 4 > H R \ f p z etx cr etb ! + 5 ? I S ] g q { eot so can “ .Z [i a . • Caracterul cu codul 32 este spa]iu (gol) [i se tip\re[te ca [i un spa]iu gol. • Diferen]a `ntre codurile literelor mari [i cele mici corespunz\toare este 32. be l bs cr es c ~n]elesul audible bell backspase retur car escape unor abrevieri ht tab orizontal nl nul vt linie nou\ null tab vertical ~n sistemele UNIX. A .