Program Are Limbajul c[Ro][Gheorghe Grigoras]

Programare_ Limbajul_C

CUPRINS
CUPRINS _______________________________________________________________________ i Cap 1 INTRODUCERE ÎN LIMBAJUL C _____________________________________________4 1.1 Scurt istoric_________________________________________________________________4 1.2 Forma unui program C _______________________________________________________8 1.3 Compilarea unui program C___________________________________________________9 Cap 2 Tipuri, operatori, expresii_____________________________________________________11 2.1. Tipuri simple ______________________________________________________________11 2.2. Literali ___________________________________________________________________12 2.3. Declararea unei variabile şi a unei constante ____________________________________13 2.4. Operatori _________________________________________________________________14 2.4.1. Operatori aritmetici ______________________________________________________15 2.4.2. Operatorii relaţionali (de comparaţie) ________________________________________15 2.4.3. Operatori logici _________________________________________________________16 2.4.4. Operatori la nivel de bit ___________________________________________________16 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 ___________________________________________________18 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__________________________________________________________28 4.5. Citirea cu format ___________________________________________________________32 Cap 5 INSTRUCŢIUNI DE CONTROL ______________________________________________35 5.1. Instrucţiunea if ____________________________________________________________36 5.3. Instrucţiunea while_________________________________________________________38 5.4. Instruc]iunea do ... while ___________________________________________________39
i

Gheorghe GRIGORAŞ

5.5. Instrucţiunea for ___________________________________________________________39 5.6. Instrucţiunea break ________________________________________________________41 5.7. Instrucţiunea continue _____________________________________________________42 5.8. Instrucţiunea go to_________________________________________________________42 5.9. Exerciţii __________________________________________________________________43 1. Calculul factorialului. _____________________________________________________43 2. Conversie _________________________________________________________________43 3. Numărarea biţilor 1 într-un număr ______________________________________________43 4. Prezentare de date __________________________________________________________43 5.10. Soluţii la exerciţii _________________________________________________________43 1. Calculul factorialului ________________________________________________________43 2. Conversie _________________________________________________________________44 3. Numărarea biţilor 1 într-un număr ______________________________________________45 4. Prezentare de date __________________________________________________________45 Cap 6 TABLOURI ŞI POINTERI ___________________________________________________47 6.1. Pointeri ___________________________________________________________________47 6.2. Tablouri cu o dimensiune ____________________________________________________48 6.2.1. Referenţierea unui element al tabloului _______________________________________48 6.2.2. Iniţializarea unui tablou ___________________________________________________48 6.3. Relaţia între pointeri şi tablouri ______________________________________________50 6.4. Operaţii aritmetice cu pointeri _______________________________________________51 6.5. Şiruri de caractere _________________________________________________________51 6.6. Tablouri cu mai multe dimensiuni ____________________________________________51 6.7. Tablouri de pointeri ________________________________________________________53 6.8. Pointeri şi alocarea memoriei_________________________________________________54 6.9. Operatorul “sizeof” ________________________________________________________55 6.10. Pointeri către funcţii _______________________________________________________55 6.11. Exerciţii _________________________________________________________________57 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 ___________________________________________________61 7.5. Tipul enumerare ___________________________________________________________63 7.6. Uniuni ____________________________________________________________________63 7.7. Exerciţii __________________________________________________________________65 7.8. Soluţii ____________________________________________________________________66 Cap 8 GESTIUNEA MEMORIEI ___________________________________________________70
ii

Programare_ Limbajul_C

8.1. Precizarea unui mecanism de memorare _______________________________________71 8.2. Gestiunea automată a memoriei ______________________________________________71 8.3. Gestionarea “register” a memoriei ____________________________________________71 8.4. Gestionarea statică a memoriei _______________________________________________72 8.5. Variabile globale ___________________________________________________________72 8.6. Declararea variabilelor externe _______________________________________________72 8.7. Gestiunea dinamică a memoriei_______________________________________________73 8.8. Exerciţii __________________________________________________________________73 8.9. Soluţii ____________________________________________________________________74 Cap 9 CONVERSIA DE TIP _______________________________________________________76 9.1. Mecanisme de conversie ____________________________________________________76 9.1.1 Conversia la asignare _____________________________________________________77 9.1.2 Evaluarea expresiilor aritmetice _____________________________________________77 9.1.3. Evaluarea expresiilor logice________________________________________________78 9.1.4 Conversii explicite _______________________________________________________78 9.1.5 Conversie de pointeri. Pointerul universal _____________________________________79 Cap 10 PREPROCESORUL ________________________________________________________80 10.1 Directive preprocesor ______________________________________________________80 10.1.1 Constante simbolice. Directiva #define ______________________________________81 10.1.2 Includerea fişierelor _____________________________________________________81 10.1.3 Compilare condiţionată ___________________________________________________82 10.1.4 Directiva #error ______________________________________________________82 10.2 Macroinstruţiuni __________________________________________________________83 10.2.1 Macroinstrucţiuni predefinite ______________________________________________83 10.2.2 Macroinstrucţiuni tip funcţie_______________________________________________83 Cap 11 EXERCIŢII_______________________________________________________________84 BIBLIOGRAFIE_________________________________________________________________86 ANEXA ________________________________________________________________________87 Biblioteca standard C __________________________________________________________87 Codul ASCII __________________________________________________________________90

iii

2 Forma unui program C 1. CPL a fost dezvoltat la Universităţile Cambridge şi London în anii 1960-1963.3 Compilarea unui program C 1.1 Scurt istoric Strămoşii limbajului C sunt limbajele de programare CPL. sintaxa este total diferită. Numele “C”. la Bell Laboratories în USA. bazat pe B. În una din implementările BCPL-ului. B şi Algol 68.1 Scurt istoric 1. Primul limbaj de nivel înalt implementat sub acest sistem de operare a fost limbajul B. exemple simple de programe duc la complicaţii nebănuite. este oficial din “Combined” dar neoficial se consideră a fi iniţiala pronumelui lui . considerat la început a proveni de la Cambridge. sau “systems programming languages”.Cap 1 INTRODUCERE ÎN LIMBAJUL C 1. BCPL a fost proiectat de Martin Richards în 1967 şi face parte din categoria “low-level languages”. care la început s-a numit NB dar numele său a fost stabilit C. restul operanzilor erau consideraţi întregi. În anii ’60. BCPL. Asemănarea cu BCPL a fost mai degrabă semantică. 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). Ken Thomson a început proiectarea sistemului de operare Unix. un limbaj bazat pe BCPL care a fost proiectat de asemenea de către Ken Thompson în 1970. Problemele create în jurul limbajelor BCPL şi B au dus la dezvoltarea unui nou limbaj. 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. operanzii flotanţi din expresii trebuiau precedaţi de punct.

) limbajul a fost influienţat şi de Algol 68. au apărut numeroase alte implementări ale limbajului C şi astfel a crescut şi popularitatea acestuia. Un fapt cu totul inedit a fost acela că. •FORTRAN I (1957) •FORTRAN II (1958) •ALGOL 60 (1960) •CPL (1963) •ALGOL 68 (1968) •BCPL (1967) •B (1970) •C (1972) •C++ (1984) Figura 1. Pentru eliminarea acestora în 1983 a fost creată o comisie care să stabilească un standard al acestui limbaj. adică a elementelor de bază în funcţionarea unui calculator. cel care a condus echipa ce a proiectat CPL-ul. Se înţelege că au existat şi neconcordanţe în multitudinea de “dialecte” ale limbajului. În ciuda acestui fapt .1. 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. programele scrise în C 5 . Ada) cu gradul de control şi flexibilitatea oferite de către limbajul de asamblare. 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ă. Firma Borland a folosit acest standard în faza de proiect şi a realizat implementările Turbo C care se bucură de un succes remarcabil. Algol. 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.1.Programare_ Limbajul_C Cristopher Strachey. Ritchie a lucrat pe un calculator DEC PDP-11 sub sistemul de operare Unix. De altfel. tratarea pointerilor etc. toate compilatoarele C sunt compatibile cu standardul ANSI C. unele din acestea au adăugate o serie de facilităţi sau extensii proprii care nu împiedică compilarea unui program standard. C permite manevrarea biţilor. în prezent . Genealogia limbajului C este prezentată în Figura 1. Limbajul a fost proiectat şi implementat de către Dennis Ritchie la Bell Laboratories în 1972. În mare parte ( construcţiile for şi switch. Modula. a octeţilor şi a adreselor de memorie.versiunea 5 şi multă vreme a constituit un standard (neoficial de altfel) al limbajului [KeR 78]. Din acest motiv varianta clasică a limbajului C a fost asociată sistemului de operare Unix . Odată cu creştere popularităţii calculatoarelor personale. Fortran.

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

Programare_ Limbajul_C •Fortran(1956) •Algol 60(1960) •CPL(1963) •BCPL(1967) •Simula 67(1969) •C •Algol 68(1977) •C cu Clase (1980) •Ada (1983) •C++ (1984) •ANSI C (1986) •ML(1976) •Clu(1978) •C++arm(1990) •C++std (1995) Figura 1. 1979 1980 1982 1983 1984 1985 1986 1987 Mai Octombrie Aprilie Ianuarie August Decembrie Ianuarie Februarie Octombrie Septembrie Noiembrie Î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++ 7 .2.

Vom începe prezentarea printr-un exemplu. printf (" Continuati ? d)a n)u -->").b. primul limbaj de programare studiat (cel puţin până acum) a fost altul decât limbajul C. */ # include <stdio. b capata valoarea restului si procedeul se repeta.a = b. } while (rest!=0). Metoda care se aplica pentru a determina cmmdc este urmatoarea: se calculeaza restul impartirii intregi a lui a prin b. mai ştie cel puţin un limbaj de programare (Pascal în cele mai multe cazuri). &a. a capata valoarea lui b. daca acest rest este nul. la facultăţile care au în planul de învăţământ informatică şi chiar la cele de profil.cmmdc (a. do { printf (" Introduceti 2 valori intregi pozitive -->").3.b)).b = c. &b). 8 . do { rest = x%y. b este valoarea cautata. 1.Gheorghe GRIGORAŞ 1988 1990 1991 1992 1994 Decembrie Ianuarie Iunie Martie Mai Mai Iunie Februarie Martie Mai August 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 Figura 1. x = y.h> int cmmdc (int x. Aceasta pentru că în programa de liceu. cel care se apucă de învăţat limbajul C. In caz contrar. se începe cu un limbaj diferit de C iar în învăţământul superior. if (b>a) { int c = a. } int main (){ int a. la disciplina de informatică.2 Forma unui program C În general. char raspuns. int y){ int rest. y = rest. return x. Programul 1 /* Calculul celui mai mare divizor comun (cmmdc) a doua numere intregi pozitive a si b. } printf (" Cmmdc al celor doua numere este: %d\n". scanf ("%d%d".

Să trecem în revistă structura programului prezentat. În corpul funcţiei main în Programul 1 avem apeluri la alte funcţii: printf. 1. 3. return 0. Parametrul "%d%d" specifică formatul de citire a două numere întregi (d de la digit) iar parametrii &a. Construcţia "do {.h. cmmdc. Crearea programului. Definiţiile acestor funcţii se află în fişierul sistemului stdio.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. Crearea unui format executabil al unui program C parcurge următoarele trei etape: 1. operaţiile de intrare/ieşire se realizează prin apel la funcţiile unei biblioteci standard furnizate de sistem. )" 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ă). Legarea programului cu funcţiile necesare existente în bibliotecă.} while ( . Prin urmare. &b corespund adreselor (faptul că & apare în faţă) unde vor fi memorate cele două valori întregi: &a adresa variabilei a.h. 2. Limbajul C a fost optimizat special în vederea compilării. Structurile de control ale limbajului C se vor prezenta într-un capitol special. 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. În limbajul C nu există instrucţiuni de intrare/ieşire. dacă se crează un fişier sursă cu editorul Word su Windows. Urmează o linie ce începe cu #.. Acesta este un apel la o operaţie de citire a unor date pe care le introducem de la tastatură. Aceste funcţii vor fi prezentate mai târziu într-un capitol special. Primele linii din program constituie comentarii. Deşi au fost concepute şi interpretoare de C şi acestea sunt disponibile pentru diferite medii. Atenţie însă: compilatoarele acceptă ca fişiere de intrare (programe sursă) numai fişiere text standard.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.Programare_ Limbajul_C } scanf ("%c". Trebuie reţinut faptul că orice program C conţine definiţia unei funcţii cu numele main care ţine locul programului principal: punctul de intrare în execuţia unui program C este funcţia main. Î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". Aceste comentarii sunt incluse între "parantezele" “/*” şi “*/”.b): va fi scris un număr întreg (%d) după care se trece la linie nouă (caracterul ăn). &a şi %b. Dacă se foloseşte un compilator care nu are integrat un editor (cum sunt cele din sistemul de operare UNIX). iar &b adresa variabilei b. &raspuns). atunci trebuie folosit un editor pentru crearea fişierului sursă C. scanf. acesta trebuie salvat ca fişier text pentru a putea fi utilizat de un compilator. C a fost gândit de la bun început ca fiind destinat compilării. Programul pe care l-am prezentat este constituit din două funcţii: main şi cmmdc. Majoritatea compilatoarelor C asigură medii de programare care includ facilităţi pentru realizarea tuturor etapelor precizate mai sus. } while (raspuns!=’n’). Compilarea programului.. printf ("Cmmdc al celor doua numere este: %dăn" cmmdc (a. 9 . Corpul unei funcţii este delimitat de acolade: ‘{’ ţine locul lui begin (dinalte limbaje) iar ‘}’ al lui end.

4. care îndeplinesc funcţii distincte (figura 1. 10 . Să mai precizăm . 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. De aceea C++ acceptă limbajul C: orice program C va putea fi compilat de un compilator C++. singura funcţie care trebuie să fie prezentă în orice program se numeşte main( ). în esenţă. Un program C compilat creează şi foloseşte patru zone de memorie disjuncte. • memorează argumentele funcţiilor. prin intermediul funcţiilor de alocare dinamică ale limbajului C. Într-un program C corect conceput. Aşa cum vom vedea în partea a doua a acestei cărţi. Prima regiune este aceea care stochează codul programului. aşa cum dăinuie de când a fost creat limbajul şi. Celelalte două zone reprezintă aşa zisa stivă a programului şi zona de manevră.4. o schemă a ceea ce face programul. STIVA ZONA DE MANEVRĂ VARIABILE GLOBALE CODUL PROGRAMULUI Figura 1.Gheorghe GRIGORAŞ Toate programele în C constau dintr-una sau mai multe funcţii. le foloseşte pentru stocarea unor articole de genul listelor înlănţuite şi arborilor. funcţia main( ) conţine.Urmează o zonă de memorie în care sunt stocate variabilele globale. programarea în limbajul C va dăinui multă vreme de acum încolo. compilatoarele ce există pe piaţă conţin cu siguranţă şi alte funcţii. compilatoarele existente pe piaţă.). în încheierea acestei scurte introduceri . Standardul ANSI C precizează setul minimal de funcţii care va fi inclus în biblioteca standard. C++ este o versiune extinsă a limbajului C. • memorează starea curentă a unităşii centrale de prelucrare. Zona de manevră (heap) este o regiune de memorie liberă pe care programul . sunt compilatoare C++. • memorează variabilele locale. care a fost concepută pentru programarea orientată pe obiecte. altele folosesc programul de legare al sistemului de operare. Unele compilatoare au programul propriu de legare.După unii autori. un programator care nu ştie C nu va putea programa în C++. Aceasta este prima funcţie apelată la începutul executării programului. că în general. Stiva este folosită în timpul execuţiei programului în scopurile: • memorează adresele de revenire ale apelurilor la funcţii. schemă compusă din apeluri ale altor funcţii aflate în biblioteca standard a limbajului C sau definite de programator.

Aceşti operanzi.. Tipurile de bază ale limbajului C pot fi grupate în trei mulţimi: • Tipuri întregi: char.127 .Programare_ Limbajul_C Cap 2 Tipuri. Tabela 1.3. apeluri la funcţii.32767 -2147483648.32768. au un anume tip iar în funcţie de aceste tipuri se vor aplica algoritmi specifici pentru determinarea valorii expresiei. 2147483647 11 .4.2. Operatori 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. Aceste tipuri sunt utilizate pentru reprezentarea numerelor întregi.. 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. Tipuri simple 2. operatori..32767 . Declararea unei variabile 2. Acest lucru este sintetizat în Tabela 1. Literali 2. 2. Operanzii într-o expresie sunt nume de variabile.32768. 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. short. int şi long. Tipurile întregi Tipul char short int long (long int) Dimensiunea memoriei ocupate 8 biţi 16 biţi 16 biţi 32 biţi Domeniul . expresii 2.1.1. Limbajul C oferă de asemenea un mecanism de conversie a tipului care va fi prezentat mai târziu în lucrare. nume de constante (literali)..128. fiecare dintre ei.

Tipul vid: void. ele reprezintă valori care nu pot fi modificate pe parcursul execuţiei unui program.retur de linie.14159. ‘\r’ . o42l long 423uL.2E^3.2. ‘\\’ .interlinie (linie nouă). 0 O12. ^423. . 65535 0 . Literali Literalii (sau constantele literale) sunt valori constante.caracterul ‘’’ ‘\”’ . Tabela 3 sintetizează unele din aceste reguli. 12 . ‘\f’ .03.retur de car. 65535 0 .caracter de cod hexazecimal hh.caracter de cod octal ddd. ‘A’. 10e-12 caracter ‘a’. ‘\ddd’ . ‘\t’ . 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 . Este un tip folosit pentru reprezentări de dimensiune nulă. 255 0 .. A24E 39u.backspace. Pentru tipurile întregi se pot folosi specificările signed şi unsigned.caracterul NULL.425 -15. double Aceste tipuri sunt folosite pentru a reprezenta numere reale. ‘\u’ . ‘\b’ . O3724 ox7F. -12.. 25AfuL flotant 3. ‘\’’ . ‘\xhh’ . 57F3u întregi 12L. -457.iar double pentru numere reale în dublă precizie – aproximativ 15 cifre semnificative..Gheorghe GRIGORAŞ • Tipuri reale: float.tabulare.caracterul \ (backslash). în limbajul C se folosesc diferite reguli sintactice pentru reprezentarea constantelor. Constante literale Constante Exemple întregi 123. o245u. ‘^’ ş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. ‘\o’ . Tabela 3.. • Tabela 2.. 4294967295 2. OX3. Specificarea signed tip este echi-valentă cu tip iar unsigned tip are semnificaţia din Tabela 2. Ele se disting prin precizia de reprezentare: float – numere reale în simplă precizie –aproximativ 6 cifre semnificative .tabulare verticală. Acestea sunt: ‘\n’ .caracterul ”. 42153l.

desp r ite prin virgule. Exemple: int i. char n1='\n'.14159. explicit se poate specifica prin cuvântul cheie aut: aut int x.primul caracter este literă sau ‘_’ (underscore). pi = 3. k. având durata de viaţă pe parcursul execuţiei funcţiei. Variabilele se declară la începutul funcţiilor (variabile locale) sau în exteriorul tuturor funcţiilor (variabile globale). const char mesaj[ ] = "Eroare". Variabilele sunt obiectele de bază ale limbajului şi au un nume care este un identificator. O constantă se declară prin: const tip nume= valoare.următoarele caractere sunt caractere alfanumerice (litere sau cifre) sau ‘_’. dacă e posibil. .71828182845905. Variabilele din clasa automatic sunt definite în interiorul funcţiilor fiind locale funcţiei în care au fost definite. Un identificator în limbajul C este un şir de caractere care trebuie să îndeplinească condiţiile: . . const double e = 2. într-o declaraţie se specifică clasa de alocare (implicit sau explicit). Această clasă este implicită. j.e-4. const float pi = 3. Declararea unei variabile şi a unei constante Toate variabilele unui program trebuiesc declarate înainte de a fi utilizate. float eps = 1. în afară de tipul variabilei şi eventual o valoare iniţială pentru aceasta. alocarea se face în registrele unităţii 13 . tip nume = valoare. 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ă.3.Programare_ Limbajul_C 2.14159. Mai multe variabile de acela i tip pot fi declarate în aceea i instruc iune. Clasele principale de alocare sunt automatic şi static.Nu trebuie să coincidă cu vreun cuvânt cheie (vezi Tabela 4) Tabela 4. Cuvintele cheie ale limbajelor C şi C^^ this handle public asm delete throw do if register auto try double inline return break short typedef else int case signed union catch enum long new sizeof unsigned char extern virtual operator static class float void struct overload for const volatile switch private continue friend template while protected default goto O variabilă se declară prin una din următoarele instrucţiuni: tip nume.

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 DA DA DA DA Durata de viaţă Pe durata funcţiei Pe durata aplicaţiei Pe durata aplicaţiei Pe durata aplicaţiei - Auto. Tabelul 5. Dacă tipul operanzilor este acelaşi într-o expresie. Register Static internal External Static în modulul în care-i DA DA external definită External în toate modulele DA (în funcţie) aplicaţiei 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.4.45. Operatorii ce pot apare într-un program C sunt de patru feluri: • operatori primari de parantetizare. De pildă expresiile x * y +z şi x * (y + z) vor fi evaluate diferit pentru aceleaşi valori ale variabilelor. ca şi perechea: x+y*z . evaluarea se face în mod natural. Spre exemplu.0 20. dacă se declară: float alpha = 20. Evaluarea expresiilor se face înlocuind operanzii prin valorile sale şi efectuînd operaţiile conform cu specificaţiile acestora. Fiecare dintre aceştia au un tip declarat. aceştia delimitează subexpresii şi pot schimba asociativitatea operatorilor.0 25. (x + y) * z. 2. Variabilele din clasele auto şi register nu îşi păstrează valoarea de la un apel la altul al funcţiei în care sunt definite. 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ă. se aplică conversii implicite de tip: unul din operanzi se converteşte la tipul celuilalt iar tipul rezultatului va fi tipul comun. permanentă). Operatori Operatorii se folosesc la constituirea de expresii pornind de la constante şi variabile.45 Dacă operanzii au tipuri diferite . float beta = 25. atunci evaluarea expresiei: alpha + sqrt (beta). 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).Gheorghe GRIGORAŞ centrale şi nu în memoria RAM. Variabilele definite în exteriorul tuturor funcţiilor fără vreun specificator de clasă sunt în clasa extern şi au alocate adrese fixe. 14 .45 + 5. Am văzut că operanzii pot fi variabile.se face în ordinea indicată mai jos: alpha + sqrt (25) alpha + 5. constante sau apeluri la funcţii (despre care se va vorbi mai târziu). Tabelul 5 sintetizează clasele de alocare.

k. Operatori aritmetici Operatorii aritmetici sunt aceea care se aplică operanzilor numerici. x. • 2. Exemplu: x+y x % y. cos. . acos. l. atan.prezentate în Anexa – care sunt operatori cu scriere prefixată: . y a = (x! = y). 2. 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. m. asin. y--./* l = 12 apoi i = 11 */ 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ă .4.2. tan. Operatorii ++ şi -.plus şi minus unari. j. acolo unde nu este specificat altfel.funcţia de ridicare la putere pow. logaritmică etc. 15 . Negaţia are semnificaţia obişnuită: schimbă semnul valorii expresiei în faţa căreia se află. ++ autoincrementarea. Aceştia pot fi unari sau binari iar în privinţa asociativităţii. 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).. . în secvenţa anterioară. • Operatorii unari: +.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.funcţiile exponenţială. -autodecrementarea. aceasta este de la stânga la dreapta. x++. • operatorul ternar condiţional operand 1 ? operand 2 : operand 3. Exemple: Fie declaraţia int i = 10.1.Programare_ Limbajul_C operatori binari cu notaţie infixată adică: operand operator operand. ++x. • operatori unari cu notaţie prefixată sau postfixată: -x. atunci: j = i ++ /* j = 10 apoi i = 10 */ k = ++i/* i = 12 apoi k = 12 */ l = i-. • postfixaţi: variabila este incrementată (decrementată) după evaluarea expresiei în care se află iar asociativitatea este de la stânga la dreapta. asociativitatea este de la dreapta la stânga. 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.funcţiile trigonometrice uzuale: sin.4.

• op1op2 are valoarea zero (fals) dacă i numai dacă op1 şi op2 au ambii valoareea zero (fals).4. ~ .4.disjuncţie logică la nivel de bit. >> .deplasare la dreapta. z = x >> 2. x = 0000 0000 0000 1101 (= 13) y = 0000 0000 0011 0100 (= 13. variabila = expresie.deplasare la stânga. ^ .4) z = 0000 0000 0000 0011 (= 13/4) 2. Aceştia se pot aplica doar operanzilor de tip întreg (char. Exemplele următoare sunt edificatoare. Semnificaţia primilor trei operatori binari (&. ^) este cea naturală (aminitm că 1 reprezintă valoarea logică “adevărat” iar 0 valoarea “fals”).negare la nivel de bit (operator unar). iar dacă unul din ei are valoarea fals (0) atunci expresia are valoarea zero.Gheorghe GRIGORAŞ 2. 2.disjuncţia logică (sau) && .5. Operatorul de asignare Operatorul de asignare. Exemple: x = 13. Aceşti operatori sunt: & .  . |. short.negaţia logică cu asociativitate de la dreapta la stânga  . Operatori la nivel de bit Limbajul C dispune de şase operatori pentru tratarea informaţiei la nivel de bit. ~ 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. long) şi servesc la poziţionarea sau interpretarea valorilor întregi ca o secvenţă de valori binare. 16 . •!op1 are valoarea fals dacă op1 este adevărat şi are valoarea adevărat dacă op1 este fals. y = x << 2. 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.sau exclusiv la nivel de bit. int. 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.conjuncţie logică la nivel de bit. are ca efect evaluarea expresiei din dreapta semnului = şi atribuirea acestei valori variabilei ce se află în stânga acestui semn. exprimat prin =.3.4.conjuncţia logică (şi) Expresia: •op1&&op2 are valoarea adevărat (1) dacă cei doi operanzi sunt evaluaţi la adevărat. << . în particular se poate obţine (rapid!) înmulţirea cu 2op2 (op1 << op2) sau cu 2-op2 (op1 >> op2).

este o construcţie validă în C. Spre exemplu i = j = k = l = 1.. *=. 17 . prin care cele n variabile capătă valoarea expresiei din partea dreaptă. .. /=. k. Forma generală a sa este: op1 ? op2 : op3. permite ca aceştia să formeze expresii care au atribuite valori. expresia este egală cu op3. j.op2. Astfel variabilă = expresie.Programare_ Limbajul_C Pe lângă acest tip de asignare. unde e1 şi e2 sunt expresii. -=.7. expresia este egală cu op2 iar dacă op1 are valoarea fals. unde op1. Exemplu: max = (a > b) ? a : b. 2.. valoarea expresiei din dreapta semnului # .6.4. = varn = expresie. limbajul C permite compunerea asignării (#) cu un operator binar (op) obţinându-se operatori de asignare compusă: e1 op = e2.. este o expresie echivalentă cu construcţia: if (a > b) max = a.expresie2. |=. Operatorul condiţional se notează cu ?: şi are asociativitatea de la dreapta la stânga. este o expresie ce are ca valoare. Operatorul virgulă Forma generală a unei expresii ce utilizează acest operator este: expresie1. l capătă valoarea 1. %= • Operatori logici la nivel de bit: &=. >>= Faptul că atribuirea este privită ca un operator binar.op3 sunt operanzi. ^= • Operatori de decalare: <<=. prin aceasta cele patru variabile i. Acest lucru permite “atribuirea în lanţ”precizând că asociativitatea operatorului de asignare este de la dreapta la stânga: var1 = var2 = . Operatorul condiţional Acesta este singurul operator ternar al limbajului C. else max = b.4. Dacă op1 are valoarea adevărat. 2. Se obţin asignări compuse cu: • Operatori aritmetici: +=. Această asignare este echivalentă cu : e1 = (e1) op (e2).

j++) for(i = 0. 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ă Descrierea . ./=. Precedenţa operatorilor limbajului C este dată în tabelul nr. Pentru limbajul C. Operator :: :: →. 18 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.8. %= +=. /. ~ ! +. >>= &=. decrementare Negare pe biţi Negare logică Plus. se înţelege) expresiei ultime ce apare în acest şir. |= . i < 100.*=.Gheorghe GRIGORAŞ Expresiile sunt evaluate de la stânga la dreapta iar valoarea întregii expresii este valoarea (şi tipul.delete ->* .j = n-1. O asemenea construcţie apare frecvent în instrucţiuni for pentru realizarea mai multor acţiuni: for(i = 0. i < j.. % +.6. . operatorilor unari. Tabelul nr. -=. 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. Precedenţa operatorilor Asociativitatea şi precedenţa operatorilor indică ordinea în care se evaluează subexpresiile într-o expresie. <<=. << <. >= ==.j = 0.* *.4. j--) 2. minus unari Acces la o variabilă 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. i++. >. i++. [] () sizeof -> . * & () new.>> . Am văzut că operatorii primari de parantetizare pot schimba asociativitatea operatorilor.<=. 6. ^=. != & ^ | && || ?: =.

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

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

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

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

Programare_ Limbajul_C printf ("%s". } } Dacă acest program are numele prg2 atunci linia de comandă: prg2 produce scrierea mesajului: Nu exista argumente in aceasta executie ! iar linia de comandă: prg2 Iata niste argumente ! produce scrierea mesajului: Iata niste argumente ! 23 . argv [i] ).

Unificarea sistemului de intrare/ieşire în C se face prin “pointerii” de fişier. 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.h . o imprimantă sau “o zonă” (fişier) pe disc. Un flux se poate asocia unui fişier executând o operaţie de deschidere: odată deschis.5 Citirea cu format 4. stare. Deşi fiecare dintre acestea este foarte diferit de celelalte. Datorită posibilelor conversii s-ar putea ca numărul de caractere scrise/citite să difere de numărul de caractere existente pe dispozitivul extern. Acesta din urmă este opţional pe ultima linie şi este determinat de modul de implementare. Un pointer de fişier este un pointer către informaţia care defineşte diverse caracteristici ale unui fişier(nume. unităţi de disc sau de bandă etc.Gheorghe GRIGORAŞ Cap 4 FUNCŢII DE INTRARE IEŞIRE 4. î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. poziţie curentă etc). # include <stdio. Tipul FILE 4. Există două tipuri de fluxuri: •Fluxul text este o scvenţă de caractere.3 Funcţii de intrare /ieşire pentru caractere 4.1 Fluxuri şi fişiere 4. Aşadar dispozitivul fizic pe care se scriu datele se numeşte fişier iar abstractizarea acestuia se numeşte flux (sau stream).h> Orice program C începe execuţia prin deschiderea unităţilor de intrare/ieşire standard: stdin stdout stderr stdprn : unitatea standard de intrare : unitatea standard de ie[ire : unitatea de eroare : unitatea standard de ie[ire prn (imprimant\) 24 . Fluxurile sunt independente de dispozitivele iniţiale . imprimanta. 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.1. sistemul de fişiere le transformă pe fiecare într-un dispozitiv logic numit flux.Fluxuri şi fişiere Sistemul de fişiere al limbajului C este conceput pentru a lucra cu o mare varietate de dispozitive. Standardul ANSI C permite organizarea unui flux text în linii care se încheie cu un caracter linie nouă(“ăn”).. •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.2 Accesul la fişiere. inclusiv cu terminale. pot avea loc transferuri de informaţii între fişier şi programul curent în execuţie. Un fişier în limbajul C poate fi un terminal.4 Scrierea cu format 4.

Modurile posibile de deschidere (deci şirurile de caractere ce constituie parametrul lui fopen) sunt date în Tabelul 6. Cele mai frecvent folosite dintre acestea sunt date în Tabelul 5 şi vor fi prezentate în continuare. stdout) pot fi orientate şi către alte dispozitive sau fişiere.h şi are forma: FILE* pointer_la_fi[ier unde pointer_la_fişier este un identificator (numele pointerului). Declararea unei variabile de tip "pointer la fişier" se face folosind tipul FILE definit în fişierul antet stdio.1. Accesul la fişiere.const char* mod) Aici. Sistemul de fişiere ANSI C este compus din mai multe funcţii legate una de alta. Tipul FILE Conceptul de bază pentru intrări/ieşiri standard este cel de pointer la fişier.Programare_ Limbajul_C Aceste unităţi standard sunt asociate. 25 . Dispozitivele standard de intrare (tastatura) şi de ieşire (ecranul) sunt văzute tot ca fişiere cu pointerii stdin şi stdout. FILE* fopen(const char* fi[ier. Bibliotecile standard C oferă o serie de funcţii pentru operaţii de intrare/ieşire orientate pe fişiere. Aceste fişiere (stdin. 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. Deschiderea unui fişier se face prin funcţia fopen care returnează ca rezultat un pointer la un descriptor de fişier. tastaturii calculatorului (intrare) şi ecranului (ieşire şi eroare). 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. în lipsa altor indicaţii. Acest dispozitiv este gestionat de sistem pentru a asigura intrările şi ieşirile efectuate în program.

exit (1). Programul următor ilustrează acest fapt. Aceasta permite redirecţiona-rea dispozitivelor periferice prin program. fclose (stdout). Apelul la această funcţie închide fişierul cu pointerul "pf". const char* mod. Acest lucru poate fi folosit pentru tratarea erorilor la deschiderea fişierului. exit (1).stdout)==NULL) { fprintf (stderr. if(freopen("iesire. Dacă funcţia fopen returnează o valoare nenulă. deschide fişierul cu numele “nume_fişier” în modul de acces "mod". Prin închidere se eliberează descriptorul de fişier. 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ă. valoare ce va fi utilizată în apelul la funcţiile de intrare/ieşire. Valoarea returnată este un pointer la un descriptor de fişier valid. 26 . if (freopen ("CON". se actualizează fişierul pe disc şi încetează conexiunea logică între pointer şi fişier."w+". aceasta indică faptul că deschiderea s-a efectuat corect. Programul 3 # include <stdio. } printf ("Mesaj scris in fisierul iesire.dat".Gheorghe GRIGORAŞ Tabelul 6. FILE* pf). Apelul la fclose se poate face prin: int cod. deschiderea unui fişier existent în modurile "w" sau "w+" produce pierderea conţinutului său de până atunci. atribuind pointerul "pf" la acest fişier. stdout) == NULL) { fprintf (stderr.dat \n"). "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. Dacă deschiderea nu s-a efectuat corect valoarea returnată este NULL(pointer la informaţia nulă) . "Eroare la reasignare \n"). "eroare la reasignarea lui stdout la CON\n"). 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.h> main ( ){ printf ("Mesaj scris pe monitor \n").

este echivalentă cu: c = fgetc (stdin). 27 . simplificată. a scrierii apelului la fgetc şi fputc în cazul în care intrarea respectiv ieşirea este cea standard : stdin respectiv stdout. stdout). char c. redenumirii unui fişier: int rename (const char* nume_nou. • creării unui fişier temporar: FILE*tmpfile (void).2. În caz de eroare este returnată valoarea EOF. este echivalentă cu: fput (c. char c. const char* nume_vechi ). 4. pointer_la_fişier). iar putchar (c). Există de asemenea două funcţii getchar şi putchar care permit exprimarea în C. FILE* pointer_la_fişier. 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.Programare_ Limbajul_C } printf ("Mesaj scris din nou pe monitor \n"). cod = fgetc(c. Funcţia fputc scrie un caracter la sfârşitul fişierului pointat prin pointer_la_fişier. } • • Limbajul C dispune şi de posibilitatea: ştergerii de fişiere prin funcţia remove: int remove(const char* nume_fi[ier). Spre exemplu: c = getchar ( ). Funcţii de intrare/ieşire pentru caractere int fgetc(FILE* flux). int fputc(char c. FILE* flux). c = fgetc(pointer_la_fişier). int cod. FILE* pointer_la_fişier..

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

afişează argumentul în notaţia pointer. ul). 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. printf(" Forma octala:\n"). ui). printf(" ul = %lu\n\n".ul). în stil f în caz contrar.45. afişare în acelaşi stil cu e dacă exponentul este -4 sau superior preciziei.h> int main ( ) { int i = 123. i). long int l = 123456789L. l). printf(" l = %ld\n". printf(" ui = %o\n". Numărul de d este dat de argumente de precizie (implicit este 6).dddddde ± xx sau [-]m. printf(" ui = %u\n".Programare_ Limbajul_C e sau E float sau double g sau G c s p n % float sau double int char* void* int* real în notaţie zecimală sub forma: [-]m. i). Programul 4 # include <stdio. printf(" Forma zecimala:\n"). unsigned long int ul = 987654321UL. printf(" ul = %d\n". printf(" i = %lo\n\n". In urma execuţiei se va afişa: Forma zecimala: i = 123 l = 123456789 ui = 45678 ul = 987654321 29 . 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".ddddddE ± xx. 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. afişarea unui singur caracter după conversie în unsigned char. double d = 123. ui). unsigned int ui = 45678U.

123. printf("|%x| |%#x|\n".-123. printf(" ul = %lX\n\n". 123. printf("|% d| |%+d| |%d|\n". 123). printf("|%+6. ui).4d|\n". printf("|%+6. printf("\n"). 123). 30 . 123. printf("\n").4X|\n".123.4X|\n". printf("\n"). printf("|%X| |%#X|\n". 123). 123). 123). printf("Afisare in octal si hexazecimal:\n"). printf("|%+5d| |%+-5d|\n". 123.4o|\n". 123). 123). 123). printf("Afisarea semnului:\n"). 123). 123). printf("|% d| |%+d| |%d|\n". 123).-123.123. printf("|%.Gheorghe GRIGORAŞ Forma octala: ui = 131156 ul = 7267464261 printf("Scrierea hexazecimala:\n"). printf("|%+. printf("|%o| |%#o|\n". printf("|%5d| |%-5d|\n".-123). 123). 123). printf("\n"). printf("|%+6. printf(" ui = %X\n". printf("|%#5d| |%#-5d|\n".4d|\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("|%. 123.4d|\n". 123. ul).

printf("|%. 3.0f|\n" 3. printf("|%#.14157). printf("|%E|\n" 3.0001| |1E-05| |310000| |3. printf("|%G|\t|%G|\n".1e6.0001.110).142| |3| |3.0E|\n" 3. printf("|%f|\t|%G|\n". 3. 3.14157).14157e123). 3.1e7).14157e123). printf("|%E|\t|%G|\n". 0.3E|\n" 3.1e5.| |3. printf("|%.1e10.1E+07| |3100000| |3.142E+123| |3E+123| |3.11G|\n". 3.14157e123).3f|\n" 3.141570E+123| |1. 3.1E+10| |-1.0f|\n" 3.1 E+11| 31 . printf("|%E|\n" 3.100000| |3.E+123| |3.00001).Programare_ Limbajul_C Iată ce se va afişa: |0123| |+0123| |0X007B| | 123| |123 | | +123| |+123 | | 0X7B| |0X7B | | +0123| | 0173| |0X007B| /* Afisarea numerelor in virgula flotanta*/ printf("|%f|\n" 3.14157).14157e123). printf("|%. } Iată ce se va afişa de această dată: |3. printf("|%. printf("|%.1e11). 3. return0.14157). 3. printf("|%#. printf("|%f|\t|%G|\n".141570| |3.1. -0.14157e123).0E|\n" 3.11G|\t|%.100000E+10| |3.1).1| |3.

întreg în notaţie octală(primul caracter 'o') sau hexa (primul caracter 'Ox' sau 'OX'). Dacă este indicat un număr q (%qC) atunci sunt citite cel mult q caractere. de la un fişier respectiv dintr-un şir de caractere sunt: int scanf (const char* şir_format. Nu se face nici o operaţie de citire. Implicit se citeşte un singur caracter. punând caracterul '*' în directivă (de ex. scrie în argument numărul de caractere citite până acum. %*s): în acest caz câmpul este citit dar nu-i memorat.5. întreg în notaţie octală. 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.caractere ordinare (în afară de %) care trebuie să corespundă următorului caracter citit. g p n FORMAT DE INTRARE întreg în notaţie zecimală. const char* şir_format. întreg în notaţie hexa. Aceste funcţii. const char* şir_format. Formatele de conversie pentru scanf CARACTER d i o u x c s e.caractere de spaţiere sau tabulare care vor fi ignorate. caracter. 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.…). valoarea unei adrese. de obicei sunt ignorate. TIPUL ARGUMENTULUI int* int* int* unsigned int* int* char* char* float* double* void* int* 32 . întreg fără semn în notaţie zecimală. Directivele pentru specificarea unui format sunt utilizate pentru precizarea conversiei următorului câmp citit.Gheorghe GRIGORAŞ 4. Pentru citirea următorului caracter diferit de spaţiu se foloseşte %ls. În general. Caracterele pentru specificarea unui format de citire sunt date în Tabelul 8. …).directive de specificare a formatului. care încep cu '%'. 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. Tabelul 8.…). rezultatul citirii este memorat în variabila corespunzătoare din lista argumentelor funcţiei. corespunzătoare citirii de la intrarea standard. Formatul (şir_format) este un şir de caractere care poate conţine: . int fscanf (FILE* flux. . . citindu-se şi spaţiile care. Rezultatul interpretării este încărcat la adresele ce se dau ca argumente la apelul funcţiilor de citire. f. int sscanf (char* s. real în notaţie virgulă flotantă.

printf("Introduceti un text: "). citeşte caracterele din intrare atât cât acestea nu sunt în mulţimea indicată în [ ] după care adaugă '@0'. printf("Ati introdus:%d\t%d\t%d\n". char s4[5]..s3[10]. s4[4] =s5[4] =s6[4] ="\0". printf("Introduceti trei numere intregi: ").s2.&c2.s1.&c3).i2.c2.s2. permite indicarea caracterului literal '%'. printf("Ati introdus:%d\t%d\t%d\n". scanf("%4c%4c%4c".] [∧. scanf("%4d%3d%4d". s2. &i1. char* char* Programul următor ilustrează utilizarea formatelor de intrare.i2.s1.i3).i3). s5[5]. } 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!| 33 . s2.] % citeşte caracterele din intrare atât timp cât acestea aparţin mulţi-mii indicate în [ ]. printf("Introduceti un text: "). printf("Introduceti un text: "). &i2.s3). &i3). scanf("%d%d%d".i1.. scanf("%4s %4s %4s". printf("c1= |%c|\tc2=|%c|\tc3=|%c|\n"c1. s1. s3"). &c1.s2[10]. s1.. &i1.s6).h> int main(){ int i1.i1. s4. &i2. c3. i2. char c1. c2. printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n"..s5. i3. char s1[10]. s3). scanf("%c%c%c". scanf("%s%s%s.s6)return 0. Programul 5 #include <stdio.s5. s6[5].Programare_ Limbajul_C [. printf("Introduceti trei numere intregi: ").c3). &i3).s3). Adaugă la argument caracterul '@0' (sfârşit de şir).s4. printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n". printf("s4=|%4s|\ts5=|%4s|\ts6=|%4s|\n".

Gheorghe GRIGORAŞ 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| 34 .

j ++.Cap 5 INSTRUCŢIUNI DE CONTROL 5. cod = printf ("%d\n".2. ~n capitolul 2 am v\zut cum se construiesc expresiile `n C. Vom trece `n revist\ `n continuare instruc]iunile de control ale limbajului C. Urm\toarele construc]ii sunt instruc]iuni C de tip expresii: i = 1. 5.9. ++ k. end din alte limbaje)..7.8.1. s [i] = t [j]. Instruc]iunile if Instruc]iunea switch Instruc]iunea while Instruc]iunea do.6. defini]ii de func]ii. alpha).'..10. 5. s [i] = t [j]. 5. } Instruc]iunile de declarare a variabilelor (declara]iile) sunt de forma(vezi [i paragraful 2. Un bloc este un [ir de instruc]iuni `ncadrat `n acolade: { [i } (care joac\ rolul de begin . 5. j --. expresii.4.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.. Iat\ un bloc `n C: { i = 1. 5. i ++.5. instruc]iuni de control. 5.3. 5. O expresie urmat\ de caracterul '. blocuri de instruc]iuni.3) : • • • • • tip identificator. Un bloc este echivalent cu o instruc]iune. . 5. ~n general o instruc]iune se termin\ prin '.' este o instruc]iune `n C. tip identificator = valoare. 5.. j = 2.

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. deci exemplul este interpretat astfel: if ( a == 1 ) if ( b == 2 ) printf (“ b este egal cu doi\n”)." este facultativ\. int sau long). real (float sau double) sau tip pointer. }. Tipul expresiei de dup\ cuv=ntul rezervat if poate fi `ntreg (char. Exemple: if (x>y) x = x-y. if (x>y) printf("%d este cel mai mare\n". else if (x==y) printf("numerele sunt egale\n"). if ((c = getchar ( ) ) ! = EOF) putchar (c). else printf("%d este cel mai mare\n". 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 ‘. y). else y = y-x.Gheorghe GRIGORAŞ 5. x). else a -=b. Expresia se pune obligatoriu `ntre paranteze iar partea "else instruc]iune2. 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\). else printf("al doilea numar este mai mare\n").1. 36 . b += 1. short.’ 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”). if (x>y) printf("primul numar este cel mai mare\n"). C\rui if `i este ata[at else? Limbajul C rezolv\ problema aceasta prin ata[area lui else celui mai apropiat if. if ( a < b ) { a += 2. else printf (“ b nu este egal cu doi\n”).

break. break. Se `n]elege c\. Cazul default este facultativ.2. } ~n acest exemplu. cons2. Exemplu: switch (getchar ( ) ) { case 'a': printf ("s-a citit litera a\n"). Aceasta permite execu]ia unei anumite ramuri `n func]ie de valoarea expresiei "expresie" din parantez\. default: printf ("s-a citit altceva decat a. case 'b': printf ("s-a citit litera b\n").Programare_ Limbajul_C else printf (“ b nu este egal cu doi\n”). 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". caracter sau enumerare.. break. 37 . b sau c\n"). case 'c': printf ("s-a citit litera c\n"). dac\ valoarea sa este const2 atunci se execut\ instruc]iune2 [i urm\toarele p=n\ la "break" etc. break poate lipsi (vezi exemplul de la insrtuc]iunea for). break. 5. . pe fiecare ramur\ s-a folosit instruc]iunea break.. care poate fi de tip `ntreg. se execut\ instruc]iunile desemnate de ramura "default". `n cazul `n care exist\ pe una din ramuri alte instruc]iuni de control. 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. dac\ expresia nu are nici una din valorile indicate prin cons1.. dac\ aceasta exist\.

%d spatii si %d alte caractere. break. case ' ': case '\t': nspatii++.h> int main (void){ int nvocale. 38 .3. 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\. n++ } int x. printf ("Introduceti un text\n -->").Gheorghe GRIGORAŞ 5.nvocale. binen]eles. while ((c = getchar( )) != '\n') { switch (c) { case 'a': case 'A': case 'e': case 'E': case 'i': case 'I': case 'o': case 'O': case 'u': case 'U': nvocale++. Acest program analizeaz\ un text [i num\r\ vocalele. while ((c = getchar( )) != EOF){ putchar (c). spa]iile goale [i restul caracterelor din acesta. y. char c. default: naltele++. break. Instrucţiunea while while(expresie) instruc]iune Expresia "expresie". while (x!=y) { if (x>y) x = x-y. Exemplu: int c. ce trebuie pus\ `ntre paranteze. nvocale = naltele = nspatii = 0. se execut\ "instruc]iune" (care poate fi. un bloc). } Programul urm\tor ilustreaz\ utilizarea instruc]iunii while [i a instruc]iunii switch.nspatii. este evaluat\ [i dac\ aceasta nu este nul\. nspatii. Programul 6 # include <stdio.naltele). else y = y-x. naltele.\n". n = 0. } } printf("In text sunt %d vocale.

Programare_ Limbajul_C return 0.. Instructiunea do . Spre deosebire de instruc]iunea while..5 spatii si 13 alte caractere.. 5. A[adar `n cazul do. • 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\.. "corpul" instruc]iunii do.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. • instruc]iunea expr3 se execut\ la fiecare sf=r[it de bucl\. n++.while. expr3) instruc]iune Semantica acestei instruc]iuni poate fi descris\ `n dou\ moduri: 1. c = getchar ( ) while (c!= '\n') { c = getchar ( ). "instruc]iune" nu se execut\. printf ("Linia contine %d caractere \n". Instrucţiunea for for (expr1.5.4.. "instruc]iune" se execut\ m\car o dat\ pe c=nd `n cazul while. Exemplu: int n = 0. } Rezultatul unei execu]ii: Introduceti un text: --> Iata un text pentru test ! In text sunt 8 vocale. } while (c!= '\n'). while do instruc]iune while(expresie). dac\ "expresie" este evaluat\ prima dat\ la zero. expr2. 5. Execu]ia se termin\ atunci c=nd "expresie" are valoarea nul\. 39 . Se constat\ u[or c\ cele dou\ secven]e de program sunt echivalente. c. int n = 1. n++ }. n-1). do { c = getchar ( ). printf ("Linia contine %d caractere\n". • se execut\ (o singur\ dat\) expr1 [i se intr\ `n bucl\ (execu]ia de n ≥0 a instruc]iunii "instruc]iune").. n-1). c.

expr2 . . S\ observ\m c\ ini]ializarea lui i s-a f\cut `n afara instruc]iunii for ! • Suprimarea expresiei de control: for( expr . while (expr2){ instruc]iune expr3. i). expr3) instruc]iune Aceasta este echivalent\ cu secven]a dat\ mai sus (2. Instruc]iunea este echivalent\ cu secven]a: expr1. Singura modalitate de a ie[i din aceasta este utilizarea instruc]iunii break.) Exemplu: i = 0. for(.) din care lipse[te prima instruc]iune (expr1. c = getchar ( ). expr2 . Exemplu: for (i = 0.(c = getchar( )) != '\0'. • Suprimarea expresiei finale: for( expr1 . expr3) instruc]iune Aceasta este o bucl\ infinit\. i++) if (c == '\n') break. } Instruc]iunea poate fi folosit\ [i prin suprimarea uneia dintre expr1. expr2 sau expr3 sau prin suprimarea corpului ("instruc]iune"): • Suprimarea ini]ializ\rii. for( . . printf("numarul de caractere:%d\n".){ putchar (c) i++ } printf ("numarul de caractere: %d\n". i++) putchar (c). ) instruc]iune Exemplu: for (i = 0. 40 . (c = getchar( )) != '\0'. i).Gheorghe GRIGORAŞ 2.

6. break. 2. j++) { j* = 1. do) sau dintr-o instruc]iune cu alegeri multiple (switch). instruc]iunea break permite ie[irea din bucla while dup\ citirea a 50 de caractere [i nu la `nt=lnirea caracterului EOF. (c = getchar( )) != '\0'. ) instruc]iune Exemplu: i=0 for (. } printf ("Total: %d". getchar( )!= '\n'. Exemplu: for (i = 0. i). Iat\ c=teva exemple de utilizare a acestei instruc]iuni (vezi [i programul de la sf=r[itul paragrafului 5. for (j = sum. Instrucţiunea break Instruc]iunea break permite ie[irea dintr-o bucl\ (for. while. sum <= 25. sum). 5. ~n acest prim exemplu. • Suprimarea corpului buclei: for( expr1 . } 41 .5. if ( j >= 75. expr2 . { putchar (c) i++ } printf ("numarul de caractere: %d\n".5) break. if (sum>=50) { printf ("50\n").Programare_ Limbajul_C • Suprimarea ini]ializ\rii [i a expresiei finale: for( . } } printf ("Iesire din bucla while\n"). i++). expr2 . while ( ( c = getchar( ))!= EOF) { sum++. while ( ( c = getchar( )) != EOF) { sum++. expr3 ) .3): 1.

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

se va face apel la o func]ie ce num\r\ bi]ii 1. fact. .10.calculul factorialului acestui num\r (iterativ). Se va utiliza o itera]ie pentru citirea caracter cu caracter a num\rului. 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. fact = 1.citirea unui num\r natural (dat de utilizator). Exerciţii jgjj 1.Programare_ Limbajul_C 5. Scrie]i un program care s\ realizeze urm\toarele: . 43 . Conversie Scrie]i un program care cite[te un num\r hexazecimal (ca o succesiune de caractere). Prezentare de date Scrie]i un program care cite[te n valori `ntregi [i le afi[eaz\ c=te l pe fiecare linie. Numerele n [i l se definesc ca valori constante. Ultima linie va con]ine suma sumelor. 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). pe m\sur\ ce se citesc cifrele hexazecimale se face conversia `n zecimal. 2. 3. verific\ validitatea sa [i efectueaz\ conversia `n zecimal. 4. i++) fact * = i. Calculul factorialului Iat\ o solu]ia incomplet\ a problemei. . 5. ad\ug=nd la sf=r[itul liniei suma lor. &n). for (i = 2. itera]ia se opre[te dac\ se cite[te un caracter ce nu este cifr\ hexazecimal\ [i. scanf ("%d". 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. Calculul factorialului. i < = n. aliniat\ la sf=r[it de linie. printf ("Introduceti un numar natural ->"). Soluţii la exerciţii 1.h> int main (void) { int n. i.afi[area rezultaului. /* Calculul lui n! */ # include <stdio. ~n bucla de citire.9.

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

i++) { printf ("Introduceti o valoare intreaga: "). int main (void) { int i. for (i = 0. &val). transmiterea parametrului se face prin valoare. i < 10. } return n. } return 0. return 0.h> const n = 10. la st=nga se adaug\ un zero. Prin instruc]iunea x >>=1 se decaleaz\ bi]ii lui x cu o pozi]ie la dreapta. c = getchar ( ) . } int numarbit(int x){ int n = 0. } 3. Numărarea biţilor 1 într-un număr Determinarea bi]ilor 1 se face prin decalaj succesiv [i testarea bitului.Ultima linie contine suma sumelor */ # include <stdio. Prezentare de date /* Se citesc n intregi si se afiseaza cate l pe **linie impreuna cu suma acestora la sfarsit de **linie. 4. printf ("Numarul bitilor 1 este: %d\n".h> int numarbit(int). const l = 3. /* Numararea bitilor 1 din reprezentarea binara a unui numar intreg */ # include <stdio. scanf ("%d". x >>=1.Programare_ Limbajul_C (c>= 'a') && (c<='f ')|| (c>= 'A') && (c<='F') { numar = numar*16 + conversie (c). } ~n func]ia numarbit. se poate a[adar utiliza x ca variabil\ de lucru. int val. int main (void){ 45 . numar). } printf ("Conversia zecimala: %d\n". while (x!=0) { if (x & 01) n++. numarbit(val)).

i < l. } 46 . printf ("%d\n". return 0 . sumap). &val). val). if (nl == l ) { printf (" %6d\n". suma += sumap. ++nl. /*ultima valoare intreaga citita */ sumap=0. } } if (nl! = 0) { /*ultima linie este incompleta: se **completeaza cu spatii*/ int i. sumap = 0. sumap). printf ("%6d\n". nt < n. /*numarul total de intregi */ printf ("Introduceti%d numere intregi". printf ("%6d". suma p+= val. nt++) { scanf ("%d". for (i = 0. /*suma din linia curenta*/ nl=0. for (nt = 0. i < l. } /* alinierea sumei totale pe ultima linie */ int i.Gheorghe GRIGORAŞ int val. n). for (i = nl. /* suma sumelor par]iale */ nt. i++) printf (" "). nl = 0./*numarul intregilor pe linie */ suma=0. i++) printf (" "). suma). suma += sumap.

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". . 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. permite ob]inerea adresei acesteia: int i. Operatorul unar "&" numit operator de referen]iere sau adresare. 6. De exemplu. indirectare.9. Un pointer este o variabil\ ce con]ine adresa unei alte variabile.5. dereferen]iere. 6. 6. 6.Cap 6 TABLOURI ŞI POINTERI 6.11. permite derefen]ierea unui pointer.3. 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. furniz=nd valoarea variabilei pointate de acesta: int x.1. 6. char *pc. 6. Pointeri tip *identificator. pi = &i. 6.1. 6.7. chiar periculoas\ am spune: acesta permite citirea sau scrierea `n orice zon\ de memorie. Utilizarea operatorului "*" este destul de delicat\.12. x = *pi ⇔ x = i. aplicat unei variabile. 6.10.8.4. 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.2. 6. Operatorul unar "*".6. prin declara]iile: int *pi.

y (actuale) pentru c\ func]ia lucreaz\ cu variabilele ei locale a [i b. Un tablou este o colec]ie de elemente(date) de acela[i tip. Iniţializarea unui tablou Ini]ializarea unui tablou se face prin semnul "#" dup\ declara]ia acestuia urmat de o list\ de valori ini]iale. este: void schimbare (int a. trebuie transmis\ func]iei adresa variabilei iar `n corpul func]iei s\ se foloseasc\ operatorul de dereferen]iere.Gheorghe GRIGORAŞ O aplica]ie important\ privind utilizarea pointerilor este transferul prin referin]\ al parametrilor unei func]ii. schimbare_corecta (&x. A[a cum s-a precizat la capitolul "Func]ii". o declara]ie de tablou cu o dimensiune con]ine tipul tabloului (tip). dimensiune.) nu are nici un efect asupra variabilelor x.2. int vector[10]. 6. Exemplul clasic pentru acest procedeu este acela al func]iei de interschimbare a dou\ variabile. Forma "clasic\" a func]iei. y).numit\ expresie indice . Primul element al tabloului este cel de indice 0 iar ultimul este cel de indice dimensiune -1. a = b. } Apelul corespunz\tor este: int x = 1.care este un identificator precum [i dimensiunea sa. separate prin virgule. Dac\ se dore[te modificarea unui parametru formal. int b) { int temp = a. vector[1]. Varianta corect\ este: void schimbare_corecta (int *p. fiecare din acestea putând fi accesibilă. 6. } Un apel al acestei func]ii (prin schimbare (x. y = 2.2. `n limbajul C transferul implicit al parametrilor este prin valoare. Declaraţia int vector[10]. Adresa primului element (cel de indice 0) este [i adresa tabloului iar celelalte elemente se raporteaz\ la acesta. incorect\ (semantic) `n limbaj C. 6.1.2. A[adar. `ntreg. *q = temp. Dimensiunea este o constant\ `ntreag\ [i specific\ num\rul elementelor tabloului.1.care trebuie s\ aib\ valoarea `ntre 0 [i dimensiune . define[te un tablou cu numele "vector" care are 10 elemente de acela[i tip. *p = *q.2. Tablouri cu o dimensiune tip nume[dimensiune]. int *q){ int temp. b = temp. numele tabloului (nume) . ~n declara]ia de mai sus. vector[9] La declararea unui tablou se aloc\ o zon\ de memorie contigu\ care s\ stocheze toate elementele tabloului. cele 10 elemente ale tabloului vector sunt: vector[0]. 48 . temp = *p. Referenţierea unui element al tabloului Elementele unui tablou pot fi accesate prin numele tabloului urmat de o expresie `ntre paranteze p\trate . care se `nchid `ntre acolade.…. &y).

char tab[marime]. 'f'}. 2. '\o'}. acest caracter noteaz\ sf=r[itul [irului( vezi paragraful 6. '\0'}. tab[1] = tab[2] = 'b'. 'b'. Exemple: 1. 3. 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.5). aceasta se determin\ de c\tre compilator: float x[ ] = {2. 'b'.1] = 'e'. 'f'.Programare_ Limbajul_C tip nume[dim] = { valoare_1. este echivalent\ cu: char s[6] = {'a'. }. 1}. . 3. 'e'. char s[4] = {'a'. are ca efect crearea tabloului: 5 2 3 1 0 0 0 0 0 0 ~n cazul unui tablou care se ini]ializeaz\. este echivalent\ cu: char s[ ] = {'a'. 'e'. tab[marime/2] = 'c'. 49 . 2 0 5.2 3 4 0 ~n cazul tablourilor de caractere. 'c'. 0}. 0.. 'd'. int a[4] = {1. 2. Tabloul va avea structura: 'a' 'b' 'b' 'd' 'd' tab[marime . 'c'. 5. ultimul element al tabloului este caracterul ‘\0’. 2. ini]ializarea se poate face [i cu [iruri de caractere incluse `ntre ghilimele.. Spre exemplu int a[10] = {5. 'd'. declara]ia: char s[6] = "abcdef" . 'c'. valoare_2. iar declara]ia: char s[ ] = "abcdef" . poate fi omis\ dimensiunea. # define marime 5. tab[0] = 'a'. Ini]ializarea unui tablou se poate face [i prin citirea succesiv\ a tuturor elementelor sale: int i. atunci celelalte valori se ini]ializeaz\ cu zero. 4}.2. De notat c\ `n cazul sirurilor de caractere ce se memoreaz\ `ntr-un tablou. 3. tab[3] = tab[4] = 'd'. 4. 'b'.

Gheorghe GRIGORAŞ

float x [20]; for (i=0; i < 20; i++) { scanf (" %f", &x[i]); } 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. Spre exemplu dac\ se declar\ int a[3], b[3], c[3]; [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], b[1], c[-2], sunt echivalente, `n sensul c\ ele reprezint\ adresa aceleia[i zone de memorie.

6.3. Relaţia între pointeri şi tablouri
S\ consider\m urm\toarea secven]\: int tab[10]; int *pa; pa = &tab[0]; Ultima instruc]iune asigneaz\ variabilei pointer pa adresa primului element al tabloului tab. Nota]ia "*pa" este echivalent\ cu nota]ia tab[0] iar nota]ia "*(pa+1)" este echivalent\ cu nota]ia tab[1]. A[adar, `n general "*(pa+i)" este totuna cu tab[i]. Urm\toarele secven]e for sunt echivalente: for ( i = 0; i < 10; i++) tab[i] = 100; for ( i = 0, pa = &tab[0]; i < 10; i++) *(pa+i) = 100; for ( i = 0, pa = &tab[0]; i < 10; i++) *(pa++) = 100;

~n limbajul C, numele unui tablou poate fi utilizat ca pointer (constant) la adresa de `nceput a tabloului. De aceea, cu declara]iile de mai sus, este perfect valid\ asignarea pa = tab; care este echivalent\ cu "pa=&tab[0];". Nu sunt valide (e lesne de dedus) expresiile: tab = pa; sau tab ++; A[adar se poate scrie [i: for ( i = 0, pa = tab; i < 10; i++, pa++) *pa = 100; ~n rezumat, echivalen]a `ntre elementele unui tablou [i numele s\u se exprim\ prin:
tablou[i] *(tablou + i) &tablou[i] tablou + i

50

Programare_ Limbajul_C

6.4. Operaţii aritmetice cu pointeri
Opera]iile aritmetice permise asupra pointerilor sunt adunarea/ sc\derea unei constante, incrementarea/decrementarea (^^, --) [i sc\derea a doi pointeri de acela[i tip. Trebuie precizat `ns\ c\ unitatea care intr\ `n discu]ie nu este octetul ci adresa obiectului pointat. S\ urm\rim urm\torul exemplu: float ftablou[10]; float *pf = ftablou; pf++; ~n acest exemplu, dup\ incrementare, pf pointeaz\ la cel de-al doilea element al tabloului ftablou. Iat\ [i alte exemple: `n partea st=ng\ se descrie o expresie `n care apar pointeri iar `n dreapta expresia echivalent\ `n termenii tabloului. Nota]ia pointer ptr = tablou ptr1 = ptr + 5 ptr + i ptr + 4 ptr - 3 ptr1 - ptr ptr ++ Nota]ia tablou i=0 i=i+5 tablou [i] tablou [4] tablou [-3] j-i i ++

6.5. Şiruri de caractere
~n limbajul C, nu exist\ un tip de baz\ pentru [iruri (lan]uri) de caractere. Pentru a reprezenta un [ir de caractere, se utilizeaz\ tablourile de caractere. Prin conven]ie, ultimul caracter dintr-un astfel de lan] este caracterul NULL (' @0'). 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','a','l','u','t','!', '\o'}; char mesaj[7] = "salut!"; char mesaj[ ] = "salut!"; Citirea respectiv tip\rirea acestui [ir se face prin instruc]iunile: scanf("%s", mesaj); printf("%s", mesaj); scanf("%s", &mesaj[0]); printf("%s", mesaj[0]); Exist\ o bibliotec\ de func]ii standard pentru manipularea [irurilor de caractere care se prezint\ `n anex\.

6.6. Tablouri cu mai multe dimensiuni
Declararea unui tablou cu N dimensiuni se face prin:
tip nume[dim_1][dim_2]...[dim_n];

~n aceast\ declara]ie, dim_1, dim_2, ..., dim_n trebuie s\ fie constante. Un tablou declarat `n acest mod se compune din dim_1*dim_2*...*dim_n elemente de acela[i tip (declarat) stocate `ntr-o zon\ contigu\ de memorie.
51

Gheorghe GRIGORAŞ

Pentru a accesa un element dintr-un tablou exist\ mai multe moduri de notare, `n concordan]\ cu modul de stocare a elementelor tabloului `n memorie. 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). int t[3][4]; 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, datorit\ numerot\rii indicilor de la 0). 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 [1][1] t [2][1] t [0][2] t [1][2] t [2][2] t [0][3] t [1][3] t [2][3]

Elementul t[1] reprezint\ un tablou cu o dimensiune iar elementul ha[urat este referen]iat prin *(t[1]+3). ~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] 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\). O problem\ important\ relativ la tablourile cu mai multe dimensiuni este cea a ini]ializ\rii acestora. A[a cum referen]ierea unui element al tabloului poate fi f\cut\ `n mai multe moduri, [i ini]ializarea unui tablou se poate face `n moduri diferite (sintactic vorbind). S\ exemplific\m aceste moduri cu referiri la acela[i tablou pe care l-am reprezentat mai sus, t[3][4]: • ini]ializarea prin enumerarea tuturor elementelor tabloului ( `n ordinea liniilor dac\-i vorba de matrice): int t[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; • ini]ializarea fiec\rei dimensiuni de tablou, separat: int t[3][4] ={{1, 2, 3, 4},{5, 6, 7, 8},
52

"joi". 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\. char *temp. for (i = 0. 7).7. "vineri". i++) if (strcmp (tabp [i]. Tablouri de pointeri Pointerii fiind variabile. zi[0] 'l' 'u' 'n' 'i' zi[1] 'm' 'a' 'r' 't' 'i' zi[2] 'm' 'i' 'e' 'r' 'c' 'u' 'r' 'i' zi[3] 'j' 'o' 'i' zi[4] 'v' 'i' 'n' 'e' 'r' 'i' zi[5] 's' 'a' 'm ' 'b' 'a' 't' 'a' zi[6] 'd' 'u' 'm ' 'i' 'n' 'i' 'c' 'a' S\ consider\m un tablou de pointeri de tip char. Astfel t [0][0] va fi ini]ializat cu 1. 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 [ ]. tabp[i] ). 10. "marti". 6. cu numele tabp. 12} }. t [1][0] cu 5 iar t [1][1] cu 6. 6}}. i++) if (tabp [i] != NULL) printf ( "%s\n". i < n. int n) { int i. while (! sortat) { sortat = 1. S\ mai d\m un exemplu de func]ie care sorteaz\ lexicografic (alfabetic) [irurile pointate de tabp: void sortare (char* tabp[ ]. "miercuri". restul elementelor sunt ini]ializate cu zero. }. } Apelul acestei func]ii pentru scrierea zilelor s\pt\m=nii este: scrie (zi. 11. Un tablou unidimensional de pointeri corespunde la un tablou (cu dou\ dimensiuni) de elemente de tipul pointat. "duminica").Programare_ Limbajul_C {9.{5. "sambata". sortat = 0. i < n-1. pot intra `n componen]a unui tablou. tabp [i+1]) > 0) { 53 . char *zi[7] = {"luni". for (i = 0. • ini]ializarea numai a unor elemente din tablou: int t[3][4] = {{1}. int n){ int i.

Gheorghe GRIGORAŞ

temp =tabp [i]; tabp [i] = tabp [i+1]; tabp [i+1] = temp; sortat = 0; } } } Apelul pentru sortarea alfabetic\ a zilelor s\pt\m=nii este sortare(zi, 7); ~n corpul func]iei sortare s-a folosit un apel la func]ia strcmp care compar\ 2 [iruri de caractere s1 [i s2; rezultatul este negativ dac\ s1 < s2, pozitiv dac\ s1 > s2 [i zero dac\ s1 # s2.

6.8. 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. Acest spa]iu este posibil de accesat cu ajutorul variabilelor de tip pointer. # include <stdlib.h> void *malloc (size_t dim); void free(void *ptr); 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. ~n cursul execu]iei programul poate aloca memorie `n limitele impuse de sistem. 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. Pointerul returnat este de tip "void" ce corespunde unui pointer la o variabil\ de tip oarecare. Pentru specificarea m\rimii unui tip particular, se poate utiliza operatorul "sizeof" (vezi sec]iunea urm\toare). Dac\ nu mai este memorie disponibil\ (nu se poate face alocarea) func]ia malloc returneaz\ valoarea NULL. Iat\ un exemplu: char *tampon; element *ptr; /*presupunem ca tipul element este definit undeva */ -------tampon = malloc(512); /* s-a alocat o memorie tampon de 512 caractere*/ ptr = malloc(32*sizeof(element)); /*s-a alocat o zona de 32 de "elemente"*/ if ((tampon == NULL || ptr == NULL)) { printf ("Alocare imposibila ! \n"); ... ... Func]ia "free" permite dealocarea spa]iului de memorie alocat `n prealabil de malloc. De pild\, dup\ utilizarea memoriei tampon [i ptr (`n exemplul de mai sus) se scrie (`n program) free (tampon); free (((char*)ptr);

54

Programare_ Limbajul_C

6.9. Operatorul “sizeof”
sizeof expresie; sizeof(tip);

Operatorul “sizeof” ofer\ dimensiunea `n octe]i a tipului expresiei considerate(tipului respectiv). Dac\ se aplic\ unui tablou, operatorul sizeof ofer\ dimensiunea `n octe]i a memoriei ocupat\ de `ntreg tabloul. Pentru a ob]ine num\rul elementelor tabloului t se utilizeaz\ expresia “sizeof t” sau “sizeof t[0]”. S\ not\m `n acela[i timp c\, atunci c=nd este parametrul unei func]ii, un tablou este considerat ca [i un pointer; prin urmare operatorul sizeof nu ofer\ dimensiunea memoriei ocupat\ de tablou ci dimensiunea tipului pointer. Acest lucru se ilustreaz\ `n exemplul urm\tor: double tab [100]; void f(double[ ]); /*declaratia este echivalenta cu void f(double*)*/ int main( ){ int i = sizeof tab; /* i este initializat cu 100 * sizeof(double)*/ f(tab); ... } void f(double t[ ]){ int i = sizeof t; /* i este initializat cu sizeof(double)*/ } Pentru a ob]ine dimensiunea memoriei ocupat\ de un tip anume se folose[te: sizeof(tip); De aceast\ dat\ parantezele sunt obligatorii. Apelul sizeof(long); ofer\ num\rul de octe]i utiliza]i pentru a memora un `ntreg “long” (este incorect a scrie sizeof long).

6.10. Pointeri către funcţii
O func]ie are un nume care este identificator dar acesta nu constituie o variabil\ `n C. Este posibil, pe de alt\ parte, de a defini o variabil\ de tip pointer c\tre o func]ie. Declara]ia unui pointer la o func]ie este de forma:
tip(*nume)(lista_arg);

tip: este tipul returnat de func]ia pointat\; nume: este identificatorul pointerului la func]ie; lista_arg : este lista argumentelor func]iei pointate. De exemplu declara]ia: char *(*p)(char*,const char*); precizeaz\ c\ p este un pointer la o func]ie de tip char* (pointer la tipul char), are doi parametri, unul de tip char*, cel\lalt de tipul const char*. Este important a se pune “*nume” `n parantez\ deoarece declara]ia “tip *nume (lista_parametri)” precizeaaz\ c\ nume este o func]ie de tip “tip*”.

55

Gheorghe GRIGORAŞ

Un exemplu de utilizare a tipului pointer la o func]ie este func]ia de comparare “cmp” ce apare ca argument la func]ia de sortare “qsort” (vezi anexa ): void qsort(const void* baza, size_t n, size_n t, int(*cmp)(const void* val1, const void* val2)) Func]ia qsort este o func]ie de sortare general\ care permite sortarea unui tablou de elemente de tip oarecare(baza) prin specificarea unei func]ii de comparare. Iat\ un program ce utilizeaz\ func]ia qsort : # include <stdio.h> # include <stdlib.h> # include <string.h> enum {n_max = 10}; int tab_int[n_max]; /* tab_int este tabloul ce contine lungimile liniilor **ce trebuie sortat */ char* tab_nume[n_max] = { "Ionescu Ion", "Constantin Vasile", "Ion Gheorghe", "Constantin Mircea", "Constantinescu Ioana", "Vasiliu Catalina", "Vasilescu Maria", "Constantiniu Calin", "Vasile Radu", "Vasilescu Cristi" }; /* tab_nume este tabloul ce trebuie ordonat **lexicografic */ /* se definesc functiile de comparatie */ int comp_int (const void* n1, const void* n2) { return(*(int*)n1- *(int*)n2); } int comp_nume (const void* p1, const void* p2) { return(strcmp(*(char**)p1,*(char**)p2)); } int main(void) { int i; printf("Lista initiala de nume : \n"); for(i = 0; i < n_max; i++) printf("%2d: %s\n",i,tab_nume[i]); for (i = 0, i < n_max; i++) tab_int[i] = strlen(tab_nume[i]); qsort(tab_int, n_max, sizeof(int), comp_int); qsort(tab_nume,n_max,sizeof(char*),comp_nume); printf("Lungimile numelor sortate:\n"); for(i = 0; i < n_max ; i++) printf("%2d: %d\n",i,tab_int[i]); printf("Nume ordonate lexicografic: \n"); for(i = 0; i < n_max; i++) printf("%2d: %s\n",i,tab_nume[i]); return 0; }
56

12. } char *strcpy(char* dest. dac\ s1 = s2 se returneaz\ 0 [i dac\ s1 > s2 se returneaz\ o valoare pozitiv\. b) char* strcpy(char* dest. return s1[i] .11. int strlen(const char *s){ int i = 0. const char *s2){ int i = 0. i++ } dest[i] = '\0'.s2[i]. Dac\ are loc rela]ia s1 < s2. d) int strcmp(const char* s1. const char *sursa){ int i = 0. while(*scr != '\0') *dest++ = *src++. } char *strcmp(const char *s1. A[a cum s-a mai precizat. Soluţii 1. while((s1[i] == s2[i] && (s1[i] != '\0')) i++. *dest = '\0'. } 57 . Exerciţii 1.const char* sursa): func]ie ce concateneaz\ [irul sursa la sf=r[itul [irului dest [i returneaz\ valoarea lui dest. while(sursa[i] != '\0') { dest[i] = sursa[i]. 6. S\ se scrie programe C care s\ implementeze func]iile: a) int strlen(const char*s) : func]ie ce returneaz\ dimensiunea [irului s. se returneaz\ o valoare negativ\. c) char* strcat(char* dest. `n C. while(s[i++] != '\0') . return dest. return -. Implementarea func]iilor de la a) la d) se poate face folosind nota]ia tablou sau aritmetica pointerilor.Programare_ Limbajul_C 6. [irurile de caractere sunt memorate `n tablouri `n care ultimul element este un delimitator de sf=r[it de [ir: caracterul NULL(‘\0’).i . const char* s2) : func]ie ce compar\ [irurile s1 [i s2 conform ordinii lexicografice. const char *sursa){ while(*dest != '\0') dest++. return dest. } char *strcat(char *dest. ~n anex\ sunt date func]iile din biblioteca standard care se aplic\ [irurilor de caractere.const char* sursa) : func]ie ce copie [irul sursa `n [irul dest [i returneaz\ dest.

return 0. assert(strcmp(mesaj.inceput) > 0). int main(){ char *inceput = "Iat\". assert(strcmp(mesaj. Dac\ evaluarea acestui parametru este valoarea fals (0) atunci assert returneaz\ un mesaj de eroare.mijloc).Gheorghe GRIGORAŞ Iat\ [i un program care testeaz\ aceste func]ii. int lungime. const char *s2). lungime = strlen(inceput)+ strlen(mijloc) +strlen(sfarsit). int strcmp(const char *s1. const char *sursa). } 58 . char *mijloc = "un mic". const char *sursa). strcat(strcat(strcopy(mesaj. char* strcat(char *dest. "Iat un micut exemplu!") < 0). Se folose[te func]ia assert (anexa ) care are ca parametru o expresie logic\ ce descrie o proprietate ce trebuie verificat\. mesaj = malloc(lung + 1).inceput).h> int strlen(const char *s) char* strcopy(char *dest. char *mesaj. "Iata un mic exemplu !")== 0). char *sfarsit = "exemplu ! ". assert(lungime==strlen("Iata un mic exemplu ! ")). # include <stdlib. assert(strcmp(mesaj.h> # include <assert. sfarsit).

Cap 7 CONSTRUIREA DE NOI TIPURI 7.5 7.1 7. Luna ianuarie = "ianuarie". typedef char Luna[10].1.8 Redenumirea unui tip Tipul structur\ Accesul [i ini]ializarea c=mpurilor unei structuri Structuri autoreferen]iate Tipul enumerare Uniuni Exerci]ii Solu]ii ~n capitolul al doilea au fost introduse tipurile de baz\ ale limbajului C.2 7. Redenumirea unui tip Instruc]iunea typedef permite redenumirea unui tip. De asemenea exist\ posibilitatea de a renumi (redenumi) un anume tip.b. Instruc]iunea permite redenumirea at=t a tipurilor de baz\ (deja existente) c=t [i a tipurilor construite. De pild\ un tablou permite a regrupa o mul]ime de elemente de acela[i 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.6 7. . Iat\ c=teva exemple: typedef long Mare.7 7. Mesaj salut="!Bine a-ti venit la cursul<Limbajul C>". Aici “tip” este tipul ce se dore[te a fi redenumit iar nume_nou este numele ce se d\ acestuia. 7.4 7. typedef char Mesaj[49].3 7. Mare a. ~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.

char *prenume. ~n instruc]iunea de mai sus “nume” este facultativ. Structura este o colec]ie de una sau mai multe variabile (numite membri) grupate sub un singur nume. }. 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]. struct Persoana colegul.Gheorghe GRIGORAŞ 7. } amicul. S\ observ\m c\ structurile se pot defini f\r\ nume. } struct Student ionescu. 60 . short luna. } Persoana. char prenume[20] Data data_nasterii. int an. el este totu[i util pentru a identifica structura definit\.2. short luna. short anul. typedef struct{ short ziua. Tipul structură Instruc]iunea pentru definirea structurilor este: struct nume{ declara]ii }. int varsta. struct Data{ short ziua. } Data. short anul. char *grupa. struct Student{ char *nume. prin typedef li se atribuie un nume. popescu. struct Data data_nasterii. Fiecare linie din partea “declara]ii” define[te un c=mp al structurii. typedef struct { char nume[20]. Persoana ionescu. char prenume[20]. popescu.

dan. `ntr-un arbore binar. Elementul desemnat `n acest mod este echivalent cu o variabil\ de acela[i tip cu c=mpul definit `n structur\.varsta este de tip int. 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 (“. S\ consider\m acum declara]ia: typedef struct{ char nume[40] . 61 . iar necunoscut este o variabil\ de tip pointer la structura Persoana . De pild\. 42 }. 7. variabilele “ionescu” [i “dan” sunt definite ca fiind de tip Persoana . c=mpurile din variabila “ionescu” sunt copiate `n c=mpurile corespunz\toare din variabila “necunoscut”. Accesul la c=mpurile unei astfel de variabile(pointer la o structur\) se face ad\ug=nd dup\ numele varibilei pointer o “s\geat\” (“->”) . int varsta. Persoana necunoscut = { " " .data_nasterii. urm\rind exemplele din paragraful precedent. char prenume[40]. dan. } valoare.Programare_ Limbajul_C 7. liste..nume = necunoscut->nume. } Persoana. Iat\. necunoscut ->varsta = 41. 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".ziua este de tip short. "Vasile" . Aici. urmat\ de numele c=mpului. Are sens asfel: necunoscut = ionescu . Dou\ structuri de acela[i fel pot s\ apar\ `ntr-o expresie de atribuire. Exemplu: necunoscut = &ionescu. Structuri autoreferenţiate Utilizarea structurilor permite construirea de structuri de date evoluate ca: fi[iere.4.3. O atribuire de structuri este o copiere bit cu bit a elementelor corespunz\toare. arbori etc.varsta = (*necunoscut). 0}. Persoana ionescu. *necunoscut.nume.. `nc=t o astfel de expresie are sens doar dac\ structurile sunt de acela[i tip. O form\ echivalent\ este urm\toarea: (*necunoscut). ionescu.varsta = 41. Prin aceasta.nume este de tip char*.. amicul. care este un tip structur\. dan.”) [i de numele c=mpului selec]ionat.de pild\. avem: ionescu. " " . fiecare nod este compus dintr-o informa]ie (valoarea nodului) [i doi pointeri. unul la subarborele st=ng altul la cel drept. Iat\ cum poate fi definit\ o astfel de structur\: typedef struct { .

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”). adauga(3. Arbore* d){ Arbore* c. Programul Arbori binari. 62 . return c. c->stang = s. struct Arbore* stang. # include <stdio. NULL. NULL. NULL)). printf("Al doilea arbore este: \n"). printf("\n"). struct Arbore *drept. c=malloc (sizeof (Arbore)). Arbore* s. NULL). NULL)). printf("Primul arbore este: \n"). c->val = v. Arbore* d).h> typedef int valoare. adauga(2. afisare (a->stang). struct Arbore* drept. } Arbore* adauga(valoare v.Gheorghe GRIGORAŞ /* s-a definit tipul "valoare" pentru **informatia din nodurile arborelui*/ typedef struct Arbore{ valoare val. NULL). void afisare (Arbore* a). adauga(20.h> # include <stlib. Arbore* a2. a1=adauga(1. Din acest motiv structura are un nume: Arbore. " "). Arbore* s. adauga(4. int main( ){ Arbore* a1. a2=adauga(10. a1. typedef struct Arbore{ valoare val. printf("\n"). afisare(a2). struct Arbore *stang. c->drept = d. return 0. } Arbore. } Arbore. } void afisare (Arbore* a){ if (a! = NULL){ printf ("(%d". a->val . S\ observ\m c\ structura Arbore se autoreferen]iaz\: printre c=mpurile structurii arbore sunt dou\ care sunt de acela]i tip struct Arbore. afisare (a->drept). printf (" "). Arbore* adauga(valoare v. NULL. afisare(a1).

enum Luna {ian=1. sept. celelalte luni vor avea respectiv valorile 2. spre deosebire de cea de la structur\.6. Similar cu definirea variabilelor de tip structura se definesc variabilele de tip enumerare: enum Bool raspuns. 12. cu excep]ia cazului `n care programatorul ofer\ valori ini]iale acestor identificatori. enum Bool {da=1. . pentru c\ lui ian i s-a dat valoarea ini]ial\ 1. enum Bool spune=da. mai. Un tip enumerare permite ca. Primul identificator constant din lista de identificatori cap\t\ valoarea 0.5. Uniunea trebuie privit\ ca o structur\ `n care membrii ocup\ aceea[i zon\ de 63 . Aici. nu are valoarea 0 iar da are valoarea 1.s\ definim un tip care nu poate lua valori dec=t `ntr-o mul]ime precizat\ de valori constante. care definea c=mpurile acesteia. De fapt. al doilea valoarea 1. april.. 7.. dec}. oct. august. iunie. feb. etc. mar. Evident se poate redenumi [i tipul enumerare: Typedef enum {da. } else printf ("nil"). da} ~n ambele situa]ii. enum Bool {nu. nu} Bool Bool raspuns=nu. la un moment dat con]in un anume tip de variabil\ iar la alt moment acest tip se poate schimba. Tipul enumerare Definirea unui tip enumerare se face prin instruc]iunea: enum nume { lista_de_identificatori}. nu}. este vorba despre zone de memorie care. Exemple: enum Bool {da. Sintaxa este similar\ cu cea care define[te o structur\: union nume { declara]ii }.Programare_ Limbajul_C printf (")"). nu=0}. Uniuni Uniunile sunt structuri care pot con]ine (la momente de timp diferite). nov. 3. } 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)) 7. iulie. define[te o list\ de alegeri posibile. `ntr-o maniera elegant\.. obiecte de tipuri diferite. Lista de declara]ii. Aici da are valoarea 0 iar nu are valoarea 1.

Typedef union { struct { long abscisa. } cart.tip sau p1. union { struct { long abscisa.cart. typedef union { TipCoord tip. struct { float ro..teta). float pi=3. float teta. cum sunt de pild\ p1 [i p2. O variabil\ de tip Coordonate.p2.pol. } pol.p1.1415926.pol. long ordonata. C=mpul “tip” este prezent `n toate alternativele uniunii [i el poate fi consultat prin referin]a p1. struct { TidCoord tip. long ordonata. printf("%d%d\n".p2.ordonata). . Coordonate p1.tip.pol=2. 64 . poate con]ine fie valori `ntregi reprezent=nd coordonatele carteziene fie valori flotante reprezent\nd coordonatele polare.Gheorghe GRIGORAŞ memorie.p1. struct { TipCoord tip. S\ not\m c\.nec=0} TipCoord. } pol. float teta. } Coordonate.cart.tip sau p1.cart. Desigur c\ `n acest caz se presupune c\ prin program se afl\ c\ p1 este de tip cart iar p2 este de tip pol. la un moment dat doar un membru al uniunii poate ocupa memoria. float ro. ~n exemplul urm\tor se specific\ faptul c\ un punct `n plan poate fi definit fie prin coordonatele sale carteziene fie prin cele polare. printf("%f%f\n".pol.abscisa. long abscisa.ro. long ordonata. p2.. Se mai poate elimina [i aceast\ redondan]\ prin urm\toarea declara]ie: typedef struct { TipCoord tip. dimensiunea memoriei alocat\ pentru o variabil\ de tip uniune este dimensiunea celui mai mare membru al uniunii. } cart. Declara]iile precedente pot fi modificate astfel (pentru a memora `n variabil\ `ns\[i tipul de reprezentare ales) : typedef enum {cart=1. } Coordonate.

val.cart. Exerciţii 1.teta .Programare_ Limbajul_C } cart. } val.: 2143 quit 2.ro p2. struct { float ro. dac\ p1.val.val.val.tip=2 7. Dezavantajul este c\ numirea coordonatelor se face printr-o “cascad\” mai mare : p1.ordonata . De exemplu: anca tel. dac\ p2. b) consultarea agendei: la furnizarea unui nume programul ofer\ num\rul de telefon corespunz\tor (dac\ acesta exist\).pol. c) afi[area pe ecran a listei de adrese. ora[. Pentru aceasta va trebui s\ se realizeze urm\toarele: 1. codul po[tal).pol.1 crearea agendei telefonice sub forma unui fi[ier text.tip=1 p2. 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.abscisa p1. Acest fi[ier va con]ine o mul]ime de linii. Scrie]i un program pentru consultarea unei agende telefonice la nivelul personalului unei societ\]i.: 2130 anuta persoan\ necunoscut\ [tefan tel.cart. } pol. float teta. } Coordonate. strada. b) completarea tabloului de structuri cu noi adrese. Iat\ un exemplu: andrei 1427 anca 2130 ana 2131 barbu 2140 bogdan 1430 … … [tefan 2143 victor 2114 zeno 1442 1. 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.7. 65 .2 crearea programului care realizeaz\ urm\toarele: a) ini]ializarea unui tablou de elemente structurate prin citirea fi[ierului ce reprezint\ agenda telefonic\.

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\). } return (compar==0)? i-1:-1. int i. /* s-a definit o structura de tip persoana*/ persoana agenda[dim_agenda]. while ((compar>0) && (i<n)) { compar=strcmp(cineva. /* numarul persoanelor din agenda */ /* urmeaza functia de cautare secventiala */ int cauta_secv(char cineva[ ]) { int compar=1. } int main(void){ FILE* fisier./* se cauta in prima parte */ else if (compar>0) a=i+1. } persoana.agenda[i]. Soluţii 1. int b=n-1.h> # include <string. int i=0. fin=0.Gheorghe GRIGORAŞ 7. int a=0. sir cineva.h> # define dim_agenda 100 # define lung_nume 20 typedef char sir[lung_nume] typedef struct { sir nume./* se cauta in a doua parte */ } return (compar==0)? i:-1. while ((compar!=0) && (a<=b)) { i=(a+b)/2. compar=strcmp(cineva. /* s-a definit agenda ca un tablou de persoane */ int n=0. int i. /* initializarea agendei telefonice */ fisier=fopen("telefon. do { 66 . # include <stdio.8.nume). int tel. agenda[i]. i++. } /* urmeaza functia de cautare dihotomica */ int cauta_dih(char cineva[ ]){ int compar=1. if (compar<0) b=i-1.nume).txt"."r").

init_lista(). afiseaza(void).Programare_ Limbajul_C fscanf(fisier.tel)). 67 . else printf("tel. void init_lista(void). & cineva). if (!fin) { i=cauta_secv(cineva). introducere -ad\ugarea unui nou nume `n urm\toarea structur\ liber\. printf("\t Dati prenumele celui cautat \n").nume)."%s%d". unsigned long int numar. int select_meniu(void). printf("\t sau "quit" pentru sfarsit \n").agenda[i].&(agenda[n]. sterge -[tergerea unei adrese.h> # include <stdlib. /* Program pentru listarea unor adrese folosind un **tablou de structuri*/ # include <stdio. "quit")==0). gaseste_liber(void). void sterge(void).%s:%d\n". char strada[40]. unsigned long int cod_postal. &(agenda[n].%s:necunoscut!\n". fin=(strcmp(cineva. gaseste_liber -exploreaz\ tabloul de structuri `n c\utarea unui element nefolosit. } } return 0. scanf("%s". while (!fin) { printf(">"). } adresa_info[MAX].h> # define MAX 100 struct adresa { char nume[30]. n++.cineva. void main(void){ char optiune.tel). /* sau i=cauta_dih(cineva). afiseaz\ -afi[area listei de adrese. */ if (i==-1) printf("tel. Programul con]ine func]iile: init_lista -ini]ializarea listei. } while (!feof(fisier)). printf("Consultare agenda telefonica\n"). select_meniu -afi[area op]iunilor.cineva). char oras[20]. } 2. introducere(void).

10). printf("Introduceti numele strazii: "). "). gets(s). printf("4. case 2: sterge(). gets(adresa_info[liber].numar=strtoul(s. return.oras). case 3: afiseaza().strada). } printf("Introduceti numele: "). switch(optiune) { case 1: introducere(). return c. gets(s). gets(adresa_info[liber]. do { printf("\n Introduceti optiunea dvs. printf("2. Stergeti un nume \n").t<MAX. printf("Introduceti codul postal: "). c=atoi(s). Afisati fisierul \n"). } void introducere(void){ int liber. printf("Introduceti numarul: "). } while (c<0 || c>4). Introduceti un nume \n"). case 4: exit(0). } int select_meniu(void){ char s[80]. } } } void init_lista(void){ register int t. printf("1. adresa_info[liber].cod_postal= strtoul(s. for(t=0. if (liber==-1) { printf("\n Lista este completa.nume). °\0°. printf("Introduceti numele orasului: "). gets(s). Iesire din program \n").) { optiune=select_meniu(). liber=gaseste_liber(). break.++t)adresa_info[t].: "). gets(adresa_info[liber].10).Gheorghe GRIGORAŞ for(. int c. char s[80].nume[0]= °\0°. adresa_info[liber]. °\0°.. break. 68 . printf("3. break.

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

~n general programatorul nu trebuie s\ se g=ndeasc\ explicit la un mecanism anume de memorare.1 8. Memorarea poate fi: • static\.3 8. Acest mecanism se refer\ la gestionarea memoriei `n cursul execu]iei programului.7 8. ~n acela[i timp `ns\. . • `ntr-un registru al calculatorului. 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.6 8.5 8. `n segmentul datelor programului. `n stiva de execu]ie. `n memoria disponibil\.9 Precizarea unui mecanism de memorare Gestiunea automat\ a memoriei Gestionarea “register” a memoriei Gestionarea static\ a memoriei Variabile globale Declararea variabilelor externe Gestiunea dinamic\ a memoriei Exerci]ii Solu]ii Limbajul C ofer\ programatorului posibilitatea de a preciza mecanismul pe care-l dore[te pentru memorarea unei variabile. • automat\.Cap 8 GESTIUNEA MEMORIEI 8.4 8. Compilatorul asociaz\ `n mod automat unei variabile un tip de memorare care corespunde locului unde sa f\cut declararea.8 8.2 8. • dinamic\.

2. Precizarea unui mecanism de memorare Programatorul are posibilitatea s\ precizeze un mecanism de memorare prin instruc]iunea: mem tip identificator. S\ mai not\m c\ limbajul C standard (ISO) permite ini]ializarea tablourilor [i structurilor `n cazul gestiunii automate a memoriei. Cuv=ntul cheie “register” permite programatorului s\ indice faptul c\ variabila ce se define[te se memoreaz\ `n unul din regi[trii calculatorului. `ncep=nd cu locul de declarare. Utilizarea acestei clase de memorare trebuie 71 . A[adar.Programare_ Limbajul_C 8. Declararea se face prin: auto tip identificator . auto float *p = &x. Ini]ializarea unei variabile “auto” se va efectua la fiecare intrare `n bloc. Gestionarea “register” a memoriei register tip identificator . /*cuvantul auto a fost omis. Vom trece `n revist\ aceste mecanisme de memorare. va fi nedefinit\. valoarea ini]ial\. Durata de via]\ [i vizibilitatea unei variabile “auto” vor fi limitate la interiorul blocului `n care este definit\.3.1. durata de via]\ a variabilei: perioada de timp `n care variabila este accesibil\. `n lipsa acestuia. Exemple: auto float x. 8. identificator – este numele variabilei. Cum num\rul de regi[tri este limitat [i depinde de tipul de ma[in\ pe care ruleaz\ programul.el este implicit */ /* x are o valoare nedefinita pe cand p este un **pointer care are ca valoare adresa lui x */ 8. interpretarea con]inutului variabilei atunci c=nd ea este supus\ unor instruc]iuni. cerin]a aceasta este satisf\cut\ `n mod real doar dac\ este posibil\. Categoria de memorare (mem) c\reia-i apar]ine variabila va determina: vizibilitatea variabilei: identificarea p\r]ii din program capabil\ s\ foloseasc\ acea variabil\. ini]ializarea variabilei: con]inutul implicit (dac\ exist\ unul) al variabilei la crearea sa. o variabil\ este identificat\ printr-un nume (identificator). Tipul variabilei va determina: dimensiunea zonei de memorie alocat\ pentru a reprezenta variabila. static. Cuv=ntul cheie “auto” nu este obligatoriu. posed\ un anume tip [i este administrat\ de un anume mecanism de memorare. [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. char mesaj[ ] = "Mesaj initial". unde: mem –este unul din cuvintele cheie: auto. tip – este cuv=ntul cheie ce define[te tipul variabilei. dac\ nu este dat\ explicit. register. o variabil\ definit\ `ntr-un bloc va fi o variabil\ cu gestiune automat\. extern.

ini]ializarea structurilor [i tablourilor fie `n mod explicit indic=nd valori ini]iale. Ea este definit\ `ncep=nd cu declara]ia sa. `n exteriorul unui bloc: va fi vizibil\ `ncep=nd cu definirea sa p=n\ la sf=r[itul fi[ierului.Gheorghe GRIGORAŞ v\zut\ ca o directiv\ de optimizare dat\ compilatorului.4. Exemple de utilizare a unor astfel de variabile sunt `n solu]ia exerci]iului 2 din capitolul precedent. se folose[te cuv=ntul cheie “extern”. [i av=nd `n fi[ierul local specificarea extern. `ntregi. 8. O astfel de variabil\ se declar\ prin: tip identificator . ~n plus. acesta ]ine cont de ea at=ta timp c=t exist\ regi[tri disponibili `n ma[in\. utilizarea unei variabile globale vine `n contradic]ie cu principiile program\rii modulare. fie implicit cu valori 0. p=n\ la sf=r[itul fi[ierului surs\. Ea este efectiv\ doar pentru variabilele care pot fi codificate pe un cuv=nt-ma[in\: caractere. declarate `n alte fi[iere. Aten]ie `ns\ c\ o variabil\ global\ poate fi modificat\ indirect pe perioada apelului la o func]ie.5. Declara]ia “register” trebuie s\ fie plasat\ `n interiorul unui bloc. `n exteriorul oric\rui bloc. `nainte de execu]ia func]iei main. oferindu-le posibilitatea s\ accead\ la aceste argumente. Declararea variabilelor externe O variabil\ extern\ poate fi declarat\ `n orice punct al programului prin: extern tip identificator . implicit. 8. pointeri. Gestionarea statică a memoriei static tip identificator . Pentru a defini o variabil\ global\ `n alt fi[ier. ~n acela[i timp ele permit: evitarea transmiterii unor argumente la func]ii apelate. Este u[or de `n]eles c\. ansamblul c=mpurilor va fi ini]ializat cu zero. 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. 8. nedefinit\. 72 .6. Aceast\ declara]ie permite declararea local\ a unei variabile definit\ `n alt fi[ier(cu acela[i nume). Variabilele statice sunt alocate `n segmentul de date al programului. Implicit sunt ini]ializate cu 0 la `nc\rcarea programului. Vizibilitatea unei astfel de variabile statice depinde de locul `n care a fost declarat\: `n interiorul unui bloc: va fi vizibil\ doar `n blocul acela (la fel ca variabilele auto). este imposibil a se ob]ine adresa unei astfel de variabile. Variabile globale O variabil\ global\ este o variabil\ static\ care poate fi referen]iat\ `n orice loc al programului. prin urmare nu se poate defini o variabil\ global\ `n corpul unei func]ii. 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. ~n cazul tablourilor sau structurilor. durata lor de via]\ este timpul de execu]ie al programului `nsu[i. Valoarea ini]ial\ a unei variabile registru este.

}.h” care are con]inutul: # define dimensiune_sir 80 # define dimensiune_stiva 10 typedef char sir[dimensiune_sir]. Modulele vor fi: -stiva.8. care con]ine declara]iile func]iilor din modulul stiva. Fi[ier 2 extern int x. Defini]i un modul pentru gestionarea unei stive de [iruri de caractere. S\ se construiasc\ un program. fun1(void){. S\ not\m c\ o variabil\ alocat\ dinamic nu are un nume explicit.. y.. 73 .. 2. care s\ implementeze func]iile uzuale aplicate unei stive de caractere: push.. char c.c. funct1(void) { x=. } . . format din trei module. } ~n cazul declar\rii func]iilor ce se definesc `n alt modul (fi[ier). Declara]ia: extern void functie(char). care con]ine implementarea func]iilor. main(void){ . De exemplu: Persoana *ptr. Aceast\ gestiune se efectueaz\ `n memoria disponibil\ care se nume[te “gr\mad\” (heap).7. Gestiunea dinamică a memoriei Gestiunea dinamic\ a memoriei permite crearea de noi variabile pe parcursul execu]iei programului. Caracteristicile modulului sunt definite `n fi[ierul header “stiva.. Exerciţii 1. este echivalent\ cu: void functie (char). stiva_vid\. adic\ tipul rezultatului [i al parametrilor de apel.. . void pop(sir ch)..Programare_ Limbajul_C Exemple: Fi[ier 1 int x.... De aceea.. -prog.x=. pop. ~n cazul func]iilor important este s\ se descrie signatura sa.. top.c. care con]ine modulul principal. 6) care con]ine adresa sa.. 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++). 8.y. -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.h. stiva_plin\. Fi[ier 2 extern int x.c.. vizibilitatea unei variabile alocat\ dinamic este legat\ de tipul de gestiune al pointerilor care referen]iaz\ indirect acea variabil\. fun2(void){. int stiva_plina(void). extern char c.y=.y.. -stiva. ptr=malloc(sizeof(Persoana)). cuv=ntul extern este facultativ. 8. void push(const sir ch).}.. extern char c. Avem aici de-a face cu o variabil\ alocat\ dinamic care este referen]iat\ cu ajutorul pointerului ptr prin *ptr. int stiva_vida(void).

&element)!=EOF){ push(element).c 74 . int stiva_plina(void).} char top_stiva(){return(stiva[index-1]). /* stiva.} void pop(){--index. 8.c : modulul principal */ # include "stiva.element). static char stiva[dim].} int stiva_vida(){return(index==0). pop(). int stiva_plina(void). static int index=0. void push(char c){stiva[index++]=c. while(!stiva_plina()&&scanf("%c". int stiva_vida(void). citirea se va face p=n\ la `nt=lnirea sf=r[itului de fi[ier sau p=n\ la umplerea stivei. void pop(sir ch). void push(const sir ch). /*modul. printf("<%c\n".} /* prog. char top_stiva(void). while (!stiva_vida()) { element=top_stiva().h*/ # define dimensiune_sir 80 # define dimensiune_stiva 10 typedef char sir[dimensiune_sir]. int stiva_vida(void). Soluţii 1.Gheorghe GRIGORAŞ Utiliza]i func]iile de manipulare a [irurilor de caractere (Anexa ) pentru definirea func]iilor acestui modul. /* stiva. printf("Incarcati stiva: \n>"). 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).h" # include "stiva. void pop(void). } return 0. printf("Iata continutul stivei: \n").h> # include <stdio. b) scoate [irurile din stiv\ [i le afi[eaz\ (evident `n ordinea invers\ stivuirii). /*stiva. } 2.c : modul de gestionare a stivei de **caractere */ # define dim 100.h : header ce contine declaratiile **functiilor din modulul stiva.h> int main() { char element.9.c" # include <stdlib. printf(">").c */ void push(char).} int stiva_plina(){return(index==dim). } printf("\n").

printf("Iata continutul stivei: \n").h> # include "stiva.} int stiva_plina(void){ return(index==dimensiune_stiva). Inainte de aceasta se apeleaza functia **assert care impune o conditie pentru a continua **executia: stiva sa nu fie plina.h> # include "stiva.h" int main(void){ sir x. printf("Se incarca stiva: \n>"). printf("<%s\n". } void pop(sir c){ /* se decrementeaza index apoi se copie top-ul **stivei in c */ assert(!stiva_vida()). */ assert(!stiva_plina()). } printf("\n"). index++.h> # include <assert.stiva[index]). printf(">"). strcpy(c. **nevizibile in alte fisiere. */ # include <stdio.x).h> # include <string. a doua pentru **afisarea rezultatului destivuirii. while (!stiva_goala()) { pop(x).x)!=EOF) { push(x). } 75 .Programare_ Limbajul_C ** Gestionarea unei stive de siruri de caractere. while(!stiva_plina()&&scanf("%s". */ # include <stdio. strcpy(stiva[index]. } int stiva_vida(void){ return(index==0). */ static int index=0.c : programul de test ce consta din doua **iteratii: prima pentru citirea din fisierul de **intrare si stivuirea informatiei.h" /* ** variabile cu clasa de memorare *static*. --index. } /* test. } return 0.c). void push(const sir c){ /* Se copie c in stiva dupa care se incrementeaza **index. /* indicile top-ului stivei */ static sir stiva[dimensiune_stiva].

evaluarea unei expresii aritmetice sau logice în care componentele expresiei au tipuri diferite: float pi=3.1. 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\..1.1.1. asignarea cu tipuri diferite ale variabilelor termeni ai asignării: float f. 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. 2. int i=10. utilizarea operatorilor de conversie: float f1=(float)14/5.8 */ . Mecanisme de conversie Se disting patru cazuri `n care `ntr-un program C se aplică un mecanism de conversie: 1. . Evaluarea expresiilor aritmetice 9. Conversii explicite 9.1.1 Mecanisme de conversie 9.5. if (pi>2) pi=pi/i. ca o consecin]\ se pierde valoarea frac]ionar\ a variabilei reale. int i=2.14.2. ~n primul caz de pild\. ~n al doilea caz se poate converti o valoare real\ la o valoare `ntreag\.3. Evaluarea expresiilor logice 9.. Conversia de tip `n limbajul C ofer\ un mecanism simplu pentru evaluarea expresiilor aritmetice [i pentru transmiterea parametrilor.Cap 9 CONVERSIA DE TIP 9... 3. /* f1=2.4.1. Pointerul universal. Conversia la asignare 9. 9. Conversii de pointeri.1. f=i..

se alege tipul de evaluare: `ntreg. 3. real. compilatorul este cel care gireaz\ aceste conversii.’z’).tipul float este convertit la double. Poate ap\rea [i aici eroarea “Floating point exception” dac\ partea exponent este prea mare pentru o variabil\ real\ `n simpl\ precizie. .2 Evaluarea expresiilor aritmetice tipurile `ntregi mai mici dec=t int sunt convertite la int. /*caracterul ‘z’ este convertit la un intreg */ ~n cazul `n care se utilizeaz\ operatori de conversie. bitul semn `n schimb nu se mai “transfer\”: unsigned long=int/short/char unsigned=short/char unsigned short=char 2. lucrurile se petrec astfel: - 77 . mecanismul este acela[i. Dac\ valoarea p\r]ii `ntregi a sursei este prea mare pentru a fi reprezentat\ `ntr-un `ntreg. apare o eroare (Floating point exception). Alte conversii `n care intervin tipuri definite de programator sunt considerate ilicite [i sunt respinse de compilator. poten]ial. o pierdere de informa]ie. 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. etc. Vom detalia `n continuare aceste mecanisme. 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. lucrurile se petrec dup\ cum urmeaz\: 1.0 */ apelul unei funcţii: printf(“%d\n”. (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).Programare_ Limbajul_C float f2=14/5. /* f2=2.1 Conversia la asignare ~n conversia la asignare. 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. Faza II: . 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\. Dac\ destinatarul este un tip far\ semn. 9. c=nd apar dou\ tipuri diferite. 9.1. f\r\ semn. ~n rezumat.1.

valoarea asignat\ acesteia este 0 (1).. i are valoarea 10 deci expresia cap\t\ valoarea “true”. Ace[tia pot fi utiliza]i: pentru for]area conversiilor `n expresii. dup\ care. Operanzii ce apar `n aceast\ expresie r\m=n neschimba]i. etc. 78 ...1.3.-“. Evaluarea expresiilor logice Rezultatul evalu\rii unei expresii logice va fi 0 (reprezent=nd “false”) sau 1 (reprezent=nd “true”). b=(x>0) && (x<31)..Gheorghe GRIGORAŞ Dac\ un operand este: double unsigned long long unsigned Exemple: i (int) int int i (int) Faza 1 Faza 2 Rezultat Faza 1 Faza 2 Rezultat + 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: int (a (long) long double int double double double double double 9. rezultatul expresiei este convertit la tipul indicat. } ~nainte de prima evaluare a expresiei “i. 9. • asignarea valorilor 0-1: dac\ evaluarea expresiilor este “false” (true). `n caz contrar prin “true”.4 Conversii explicite Conversiile explicite se exprim\ prin: (tip) expresie sau tip ( expresie ) At=ta timp c=t conversia este permis\. Exemple: x=50. i se decrementeaz\. Ace[ti operatori de conversie permit programatorului s\ specifice o conversie care nu se face implicit de c\tre compilator. De aceea evaluarea unei expresii logice se face prin: • evaluarea operanzilor: dac\ valoarea aritmetic\ este 0 atunci aceasta se interpreteaz\ prin “false”.1. /* b capata valoarea 0 */ i=10 while (i--) { .

int* ptr1 double* ptr2 ptr1=alocare(10). ~n cea de-a treia linie a secven]ei de mai sus apare o asignare `ntre pointeri incompatibili. float f. */ f=a/(float)b. O a doua solu]ie const\ `n a utiliza tipul pointer universal void*.. O variabil\ pointer de tip void* poate primi ca valoare pointer la un tip oarecare. a=(int)ceil(r). schimbarea tipului valorii returnate de o func]ie. double r... /* f=5. ptr2=alocare(20).. Compilatorul for]eaz\ conversia [i afi[eaz\ un mesaj de avertisment (“warning”) `ntotdeauna c=nd `ntr-un program apare o astfel de conversie.25.Programare_ Limbajul_C pentru transmiterea valorilor cu tipurile cerute ca parametri `n func]ii. /* f5..5 Conversie de pointeri. Aceast\ incompatibilitate se poate evita `n dou\ moduri. Reciproc. int *ptr. Exemple: int a=21. o valoare de tip void* este implicit convertit\ la o valoare pointer de un tip oarecare... . /*functia ceil returneaza o valoare de tip intreg*/ 9.0.. ptr=(int*) alocare(100). r=sqrt(double(a)). S\ consider\m de pild\ urm\toarea secven]\: char *alocare(int dim). */ . /* f=5. 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. 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.1. Asign\rile pentru ptr1. Pentru exemplul precedent se procedeaz\ astfel: void* alocare(int dim). f=a/b.. O prim\ solu]ie const\ `n a utiliza o conversie explicit\: .25. 79 . b=4. Pointerul universal Conversia `ntre pointeri la tipuri diferite nu este implicit\. */ f=(float)a/b. ptr = alocare(100).

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

2. Aceste fi[iere con]in: 1. # undefine UNU . prin [irul de caractere asociat. • a insera fi[iere “header” (care au extensia ‘... 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. Exemplu Pentru a folosi func]iile din biblioteca matematic\ se include fi[ierul math. Preprocesorul `nlocuie[te fiecare apari]ie a identificatorului.. # define UNU .. Acest mecanism permite: • a asigna unui identificator un [ir de caractere. 10. constante simbolice [i macroinstruc]iuni standard. Forma acestei directive este: # include <nume_fisier> /* se caut\ fi[ierul `ncep=nd cu directoarele standard */ 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.. 4. cu excep]ia cazului c=nd `n acesta apare o directiv\ #undefine pentru identificatorul corespunz\tor.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. 3.. Exemplu: # define EOF (-1) . `n textul surs\. declara]ii de func]ii incluse `ntr-o bibliotec\.1 Constante simbolice.1. • 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..h care con]ine declararea acestor func]ii: 81 . defini]ii de tipuri.Programare_ Limbajul_C 10.h’)...

Are forma: # error mesaj La `nt=lnirea directivei este `ntrerupt\ compilarea [i se afi[eaz\ “mesaj”-ul ce este scris `n linia directivei.Gheorghe GRIGORAŞ # include <math.. • optimizarea unor coduri utiliz=nd avantajele specifice fiec\rei ma[ini. val=pow(M_PI. /* se calculeaza puterea a n-a a lui π */ ~n fi[ierul math. 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. ~n concluzie.3 Compilare condiţionată Directivele de compilare condi]ionat\ permit compilarea selectiv\ a unor por]iuni din programul surs\. # elif expresie2 cod2... Se utilizeaz\ la depanarea programelor. doar dac\ expresia este evaluat\ la “true” (`n caz contrar aceast\ por]iune de cod este ignorat\ de compilator)... # endif 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.4 Directiva #error Directiva #error cere compilatorului s\ sisteze compilarea.. . (double)n). • traseul de execu]ie al programelor `n faza de test. 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.1. 82 . Directiva “elif” are sensul de “else if”.h se afl\ defini]ia constantei M_PI [i a func]iei pow( ). # elif expresie1 cod1. 10. # elif expresien codn.h> . Directiva “else” ofer\ o alternativ\ `n cazul `n care “if” e[ueaz\.1. este asem\n\toare instruc]iunii ifelse din limbajul C. Ambele directive pot folosi o alternativ\ de forma #else dar nu [i #elif. 10. ea poate determina un lan] de if-else-if: # if expresie cod.

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\. iar “nume_fi[ier” este un identificator valid de fi[ier care devine noua valoare a lui _FILE_. 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\.2.1 Macroinstrucţiuni predefinite Limbajul standard ANSI C define[te cinci nume de macroinstruc]iuni predefinite. 83 . utilizat `ntr-un text surs\.2. Ora la care a fost executat\ aceast\ conversie este con]inut\ `n _TIME_ sub forma [irului ora/minute/secunde.1. “nume_macro” poate fi un identificator ce reprezint\ numele macroinstruc]iunii. Macroinstruc]iunea _STDC_ con]ine constanta 1 scris\ `n baza 10.Programare_ Limbajul_C 10. # line “nume_fi[ier”. Acestea sunt: _LINE_. dac\ dimensiunea macroinstruc]iunii tip func]ie este mare. an sunt compuse din c=te dou\ cifre ce reprezint\ `n ansamblu data conversiei fi[ierului surs\ `n cod obiect. _FILE_. Dac\ _STDC_ nu-i definit\ sau con]ine altceva dec=t 1. _STDC_.ABS(1)). acest supliment de vitez\ este “anihilat” de cre[terea dimensiunii programului. 10. datorit\ codului care apare de mai multe ori. Exemplu: # define <stdio.ABS(-1). Acesta. zi. # line num\r “nume_fi[ier”. Identificatorul _LINE_ con]ine num\rul liniei de cod la compilare iar _FILE_ este un [ir care con]ine numele fi[ierului surs\ compilat. implementarea nu este `n variant\ standard. va fi `nlocuit cu “secven]\_caractere” care poate `nsemna o secven]\ de instruc]iuni C (vezi [i 10. pe de o parte. } Folosirea func]iilor definite ca macroinstruc]iuni are. Aici “num\r” este orice `ntreg pozitiv. Macroinstruc]iunea _DATE_ con]ine un [ir de forma “lun\/zi/an” `n care lun\.2 Macroinstrucţiuni tip funcţie Aceste macroinstruc]iuni utilizator se definesc cu directiva #define: # define nume_macro secven]\_caractere Aici. 10. acesta devine noua valoare a lui _LINE_ `n punctul `n care se `nt=lne[te directiva. Aceasta semnific\ faptul c\ implementarea este conform standardului ANSI C. _DATE_. _TIME_.1). `ncorporate `n compilator.2 Macroinstruţiuni Prin acest mecanism programatorul asociaz\ o secven]\ de instruc]iuni unui identificator. Con]inutul acestor doi identificatori poate fi modificat prin directiva #line: # line num\r.h> # define ABS(a) (a)<0?-(a):(a) void main(void){ printf(″Valoarea absoluta a lui -1 si 1: %d%d″.

cifrele [i celelalte caractere(la un loc) dintr-un text(fi[ier). S\ se scrie un program numit sumedia. … Num\r … Min …. unde Min(Max) `nseamn\ cel mai mic(mare) dintre numerele citite p=n\ `n acel moment. Max …. if (( r = p % q ) == 0 ) return q. scrie]i un program ce s\ verifice conjectura lui Goldbach pentru toate numerele pare dintr-un interval dat [a. S\ se foloseasc\ aceste func[ii `ntr-un program principal. 5. 7. 702 = 11 + 691.Cap 11 EXERCIŢII 1. recursiv. 6. citirea unui intreg pozitiv n. Descrie]i [i implementa]i trei algoritmi de sortare.b] : Orice num\r par n mai mare ca 2 este suma a dou\ numere prime. Media …. S\ se scrie func]ii recursive pentru calculul factorialului unui num\r dat n. cel mai mare divizor comun a dou\ numere `ntregi pozitive p [i q: int cmmdc_r(int p. 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). k a unui num\r n. 704 = 3 + 701. 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. pentru fiecare s\ scrie un r=nd `ntr-un tabel ce are forma: Nr. S\ se foloseasc\ cele dou\ func]ii pentru a verifica dac\ al nulea termen din [irul lui Fibonacci este num\r prim ( n = 1. …. .c care s\ execute : a. etc. Suma …. cu numele : int cmmdc_i (int p. b. r). 9. S\ se scrie un program numit maxmin. literele mari . int q) { int r. a puterilor 1. else return cmmdc_r(q. S\ se scrie un program care s\ numere literele mici. Suma [i Media fiind suma (media) numerelor citite p=n\ `n acel moment 3. S\ se testeze aceast\ func]ie pentru un [ir anume(fi[ier). } 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.crt. Urm\toarea func]ie calculeaz\. Folosind func]ia “este_prim( … )” de la exerci]iul precedent. S\ se scrie o func]ie “ fibonacci ( int n) “ care s\ returneze al n-ulea termen al [irului lui Fibonacci. 4. c. 12). citirea a n numere reale.2 …. 2.c care s\ citeasc\ niste numere reale [i. int q) 8. De exemplu: 700 = 17 + 683 . a sumei numerelor naturale m [i n. determinarea valorilor maxim [i minim dintre cele n numere citite.

23. aaaa nu sunt palindroame.43.j0] = min{a[i0. Se da o matrice patratica. const void *)) pentru a sorta o list\ de numere reale `n ordinea cresc\toare relativ la p\r]ile frac]ionare a acestor numere. Scrieti o procedura care determina.01. bababbcbbabab.98 12. avand la intrare doua siruri de caractere. Scrieti un program care. a unui triunghi. Scrieti proceduri de citire si scriere a unui punct. 45. aca.98 este sortat\ astfel: 45.90.j0] : 0<=i<=m-1} Scrieti un program care determina punctele sa (daca exista) ale unui tablou bidimensional. Fie a un tablou bidimensional (m x n). etc). calculeaza data calendaristica care urmeaza unei anumite date. 15. acb. 123. 18. c.04. calculeaza data calendaristica care precede o anumita data. 2. Proiectati o structura de date pentru reprezentarea datei calendaristice si scrieti subprograme care: • • • verifica daca valoarea unei variabile din structura este o data valida.90. determina cel mai lung subsir comun si pozitiile la care acesta incepe in fiecare dintre cele doua siruri.01. ccab. aaaaaaaacaaaabb. 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. S\ se scrie un program `n care s\ se foloseasc\ func]ia sistemului : void qsort(void *array. 123. 16. c este palindrom cu centrul ‘c’: [irurile: aabacabaa . pentru un triunghi dat. S\ se foloseasc\ acestea pentru a verific\ dac\ un [ir de caractere format numai din literele a. b. 0. cerc.j0] cu proprietatea: a[i0. triunghi etc.size_t el_size. 13. 11. Un punct sa al acestui tablou este un element a[i0. dreptunghi. int compare(const void *. size_t n_els.43.j] : 0<=j<=n-1} = max{a[i.04. Scrieti o procedura similara pentru cerc. numarul punctelor de coordonate intregi aflate in interiorul sau. 14. De exemplu lista: 2. pop. Sa se ordoneze crescator fiecare linie a matricii. Proiectati structuri de date pentru reprezentarea unui punct. bbcbb sunt palindroame pe c=nd [irurile: aabbcbb. S\ se scrie [i apoi s\ se testeze func]ii pentru adunarea a doi vectori [i pentru adunarea a dou\ matrice. apoi sa se rearanjeze liniile astfel incat suma elementelor de pe diagonala sa fie minima. S\ se scrie func]iile care implementeaz\ o stiv\ `n C(push. 23. 85 . 17.Programare_ Limbajul_C 10. 0. top.

V. [i al]ii. Editura “Spiru Haret”. manual pentru licee de informatic\. Editura Teora. Bucure[ti 1998 86 . Bucure[ti. Editura Teora. Cristea. Cluj-Napoca Volumul I .Giumale.P\nsiu. Programarea calculatoarelor:Fundamente. Bucuresti. A. vol I. Ia[i.. Editura Didactic\. 1998. Informatic\ aplicat\.Gheorghe GRIGORAŞ BIBLIOGRAFIE 1. P\tru]. Teora 1998 2. B. 6. 5. E. Herbert Schildt C . Grigora[. Aplica]ii `n C [i C++.Limbajul C++ Volumul III .Limbajul C Volumul II .Limbajele C si C++ in Aplicatii 3. Limbajul C standard.Manual Complet.XI..C. Liviu Negrescu Limbajele C si C++ pentru incepatori.Kalisz.III. 1999. Musc\. Ed. Gh. 1992. 4. Gh. cls.

h> <ctype. int iscntrl(int c). . int islower(int c). Fi[ierul <errno. este tip\rit un mesaj(diagnostic) [i se iese din program.h> <math. Fi[ierul <assert.h> con]ine macrouri folosite pentru raportarea erorilor. 4.h> <stdarg.h> <stdio.h> 1. DBL_MIN.h> con]ine defini]iile unor constante ce caracterizeaz\ `ntregii: CHAR_BIT.h> <string. 2.h> con]ine macro-ul assert() • void assert (int expr). 3. CHAR_MAX.h> <time.ANEXA Biblioteca standard C FI{IERE HEADER <assert. Fi[irerul <float. int isxdigit(int c).h> con]ine macrouri (func]ii) pentru testarea caracterelor: • • • • • • • • • • • int isalnum(int c).h> <errno. int isalpha(int c). DBL_EPSILON etc.h> <limits. 5.h> <locale.h> <signal. int isprint(int c). grafic? */ /* c este litera mica? */ /* c este tiparibil? */ /* c este car. FLT_MAX. /* c este alfanumeric? */ /* c este alfabetic? */ /* c este car.h> <stdlib.h> <float. int isspace(int c).h> con]ine defini]iile unor constante pentru limitele unor valori flotante: DBL_MAX.h> <stddef. int ispunct(int c). de control? */ /* c este cifra? */ /* c este car. Fi[ierul <ctype. punctuatie? */ /* c este spatiu? */ /* c este litera mare? */ /* c este 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. int isgraph(int c). INT_MAX etc. int isdigit(int c). Dac\ expr este zero.h> <setjmp. Fi[ierul <limits. int isupper(int c).

4). /* 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). Fi[ierul <math. double exp ( double x). 7. EOF. De asemenea sunt defini]i pointerii stdin. double sqrt ( double x). 11. const char *to). stdout. FILENAME_MAX. informa]ii monetare etc. De asemnea fi[ierul mai con]ine prototipurile func]iilor de intrare/ie[ire (vezi cap. int fflush (FILE *fp). double cosh ( double x). Fi[ierul <setjmp> con]ine declara]ii [i prototipuri ce permite programatorului s\ utilizeze salturi nelocale. 12. FOPEN_MAX. int fclose (FILE *fp).h> con]ine construc]ii ce permit programatorului s\ m=nuiasc\ condi]ii sau semnale excep]ionale. Fi[ierul <stdarg. FILE *tmpfile (void). Fi[ierul <stddef. /* Seteaz\ indicatorul la `nceputul fi[ierului */ int fsetpos (FILE *fp. /*tipul diferen]\ de pointeri */ unsigned size_t. 9. /* tipul wide character*/ int ptrdiff_t. /*tipul ob]inut din sizeof() */ NULL. Sunt definite aici constantele BUFSIZ. double fmod ( double x. defini]iile de tip [i prototipurile func]iilor utilizate de programator pentru a accesa fi[iere.h> con]ine macrourile.h> con]ine construc]ii (structuri. double asin ( double x). /* Returneaz\ valoarea indicatorului de pozi]ie a fi[ierului pointat de fp*/ void rewind (FILE *fp). 8. double sin ( double x).h> con]ine defini]ii de tip [i macrouri ce se folosesc `n alte defini]ii: • • • • typedef typedef typedef #define char wchar_t. double log10 ( double x). double x). double atan2 ( double y. const fpos_t *pos).h> con]ine prototipuri pentru func]iile matematice: • • • • • • • • • • • double cos ( double x). Fi[ierul < signal. double sinh ( double x). long offset. double y). 10. double log ( double x). NULL. Func]ii pentru accesul la fi[iere: • • • • • • • • • 88 FILE *fopen (const char *filename. double tan ( double x). . double fabs ( double x). double tanh ( double x). Fi[ierul <locale. double pow ( double x. int fseek (FILE *fp. int place). func]ii) ce permit setarea unor propriet\]i “locale”: forma punctului zecimal.Gheorghe GRIGORAŞ 6. double atan ( double x). /* Seteaz\ indicatorul la valoarea pos */ int rename (const char *from. double flor ( double x). TMP_MAX.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 ). double ceil ( double x). Fi[ierul <stdio. stderr [i pentru structura FILE. double y).

generare de numere aleatoare. long labs(long i). Fi[ierul <string. int denom).h> con]ine prototipuri ale func]iilor pentru ob]inerea datei. int c. char *strcat(char *s1. Se folose[te structura tm care este definit\ astfel: 89 . const char *s2). const char *s2). /* comparare a cel mult n caractere din [irurile s1 [i s2*/ • char *strncpy(char *s1. double strtod(const char *s). const void *a_ptr. ldiv_t ldiv(long numer.Programare_ Limbajul_C 13. void exit(int status). long atol(const char *s). size_t el_size. c\utare binar\. int abs(int i).h> con]ine prototipuri de func]ii pentru manipularea blocurilor de memorie sau a [irurilor: • • • • • • • • • • • void memcmp(const void *p. const char *s2).etc. Fi[ierul <time. void qsort(void *a_ptr. int compare(const void *. size_t size). int base). size_t n). /*concatenare*/ char *strchr(const char *s. /* comparare [iruri*/ char *strcpy(char *s1. int compare(const void *. void free(void *ptr). size_t n). /* caut\ `n s1 prima apari]ie a lui s2 */ • char *strtok(char *s1. char **end_ptr. void *from. /* caut\ tokenuri `n s1 folosind caracterele din s2 ca separatori */ 15. div_t div(int numer. size_t n). long strtol(const char *s. void srand(unsigned seed). orei ]i cele privind ceasul intern al calculatorului. void *memmove(void *to. const char *s2. /*cauta c `n [irul s*/ int strcmp(const char *s1. size_t n). const char *s2) /* copie s2 `n s1 */ size_strlen(const char *s). void abort(void). Iat\ unele dintre ele: • • • • • • • • • • • • • • • • • • • void *calloc(size_t n. int atoi(const char *s). int rand(void). double atof(const char *s). int c). size_t el_size).h> con]ine prototipurile func]iilor de uz general : alocarea dinamic\ a memoriei. const char *s2. size_t n) /* copie cel mult n caractere din s2 `n s1 */ • char *strstr(const char *s1. Fi[ierul <stdlib. size_t n_els. const void *)). const void *q. void *from. void *bsearch(const void *key_ptr. const char *s2). conversie de stringuri. const char *s2. size_t n_els. size_t el_size. const void *)). void *realloc(void *ptr. 14. sortare. long denumer). size_t n). void *memset(void *p. /*lungimea [irului s */ char *strncat(char *s1. void *memcpy(void *to. comunicarea cu sistemul. void *malloc(size_t size). size_t n). /*concatenarea a cel mult n caractere din s1 la s2*/ int strncmp(const char *s1.

/*ziua lunii 1. asctime(localtime(acum))). are ca efect scrierea datei calenderistice. ctime(&acum).data*/ • struct tm *localtime(const time_t *t_ptr). • typedef long time_t. /*converte[te timpul inregistrat [i pointat de tp `ntr-un string ce reprezint\ data*/ • char *ctime (const time_t *t_ptr). printf("%s\n%s ".. /*anul de la 1900 */ int tm_wday.. / 0 1 5 2 3 4 5 6 7 8 9 : . de secunde trecute de la 1 Inuarie 1970 */ • char *asctime(const struct tm *tp).. • clock_t clock(void). /*ore 0.31 */ int tm_mon. /*returneaz\ nr.60*/ int tm_min. /*zilele din an 0. Codul ASCII American Standard Code for Information Interchange 0 1 2 3 4 5 6 7 8 9 0 nul soh stx etx eot enq ack bel bs ht 1 nl vt np cr so si dle dc1 dc2 dc3 2 dc4 nak syn etb can em sub esc fs gs 3 ’ rs us sp ! “ # $ % & 4 ( ) * + . /*returneaz\ num\rul de tacturi CPU utilizate de program p=n\ aici*/ • time_t time(time_t *tp). ..Gheorghe GRIGORAŞ struct tm { int tm_sec...11 */ int tm_year. 6 < = > ? @ A B C D E 7 F G H I J K L M N O 8 P Q R S T U V W X Y 9 ‘ Z [ \ ] ^ _ a b c 10 d e f g h i j k l m 11 n o p q r s t u v w 12 x y z { | } ~ del 90 . /*secunde 0. /*luna anului 0. Func]ii: • typedef long clock_t. /*minutr 0.. /* zilele de la 0 la 6 */ int tm_yday. acum = time(NULL).59 */ int tm_hour. De exemplu: … time_t acum.23 */ int tm_mday. /* Indicator de timp */ }. . ?8 converte[te timpul pointat de t_ptr la string .365 */ int tm_isdst.

Codurile caracterelor 0-9. comanda man ascii produce afi[area tabelei codurilor ASCII pe ecran. 91 . bel bs cr esc ~n]elesul unor abrevieri audible bell ht tab orizontal backspase nl linie nou\ retur car nul null escape vt tab vertical ~n sistemele UNIX.Programare_ Limbajul_C • • • • • Observa]ii: Caracterul G este `n linia 7 [i coloana 1 deci are codul ASCII 71. Caracterele cu codurile 0-31 [i 127 nu sunt tip\ribile. ~n tabela urm\toare se da “semantica” unora din caracterele de pe liniile 0-2.Z [i a . A .z sunt contigue. 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.

Sign up to vote on this title
UsefulNot useful