Download as pdf
Download as pdf
You are on page 1of 166
DANIELA SARU STEFAN MOCANU PROGRAMAREA CALCULATOARELOR TEORIE SI APLICATII Partea I Editura PRINTECH BUCURESTI 2012 Editura Printech “TIPAR: S.C. ANDOR TIPO $.R.L. - EDITURA PRINTECH Str. TUNARL, nr. 11, sector 2, BUCURESTI ‘Tel. /Pax: 021.211.37.12; 021.212.4951 E-mail: andortipo@yahoo.com [Descrierea CIP a Bibliotecii Nationale a Romaniei ISARU, DANIELA Programarea calculatoarelor : teorie si aplicatii / Daniela Saru, Istefan Mocanu. - Bucuresti : Printech, 2012 ISBN 978-606-521-887-1 I. Mocanu, Stefan 1004.42 Referenti stiintifici: Prof. dr. ing. Radu Dobresou Prof. dr. ing. Dorin Carstoiu Contributia autorilor: Prof. dr. ing. Daniela Saru — intregul volum $1. dr. ing. Stefan Mocanu — sectiunile 3.4, 4.4, 5.5, 6.6 si 7.9 © Copyright 2012 Toate drepturile prezentei edi{ii sunt rezervate editurii si autorilor. Nicio parte din aceast& lucrare nu poate fi reprodusa, stocati sau transmis indiferent prin ce forma, fara acordul prealabil scris al autorilor. PREFATA Programarea calculatoarelor este, deopotriva, stiinta si arta. Un sistem de calcul, oricat de performant, nu poate realiza ceva deosebit fara a primi ,,minte si suflet” din partea omului. Extraordinara putere de calcul a unui procesor se aseamand cu cea a duhului fermecat ce traia in lampa lui Aladin si care, la porunca stapanului, putea distruge sau putea fauri un intreg univers. Inteligenta ormului este cea care da ,.viafa” sistermului de calcul. Gandurile, ideile si dorinfele programatorului sunt exprimate cu ajutorul unor limbaje specializate, numite limbaje de programare, si sunt apoi transpuse in practic’ de catre sistemul de calcul. Succesul sau esecul sunt datorate in intregime programatorului, mai exact modului in care el gandeste si exprima comenzile ce trebuie executate de citre sistem. Acesta este motivul pentru care programarea calculatoarelor implici o bund cunoastere a tehnicilor de elaborare a algoritmilor (metode de rezolvare a problemelor) dar si a particularitatilor de utilizare a diferitelor limbaje de programare. Seria de volume ,,Programarea calculatoarelor. Teorie si aplicatii” se adreseazi tuturor celor care doresc sa invete sa rezolve probleme dintr-o gama larga de domenii (aplicatii de uz general, aplicatii utilitare, sisteme de operare, jocuri, baze de date etc.) folosind facilitatile limbajelor de programare moderne. Exemplele de program si problemele rezolvate incluse in acest volum au fost alese astfel inct s4 ajute procesul de infelegere treptatd a notiunilor de sintaxa, oferind cititorului posibilitatea de a folosi apoi cunostintele dobandite in elaborarea unor programe oricat de complexe. Actuala editie a primei par{i din serie, revizuita gi adaugitd, include si seturi de probleme propuse spre rezolvare, selectate astfel incat sa faciliteze abordarea scrierii de programe intr-un mod simplu, incurajator si motivant chiar gi in cazul celor care sunt doar la inceputul activititii de descifrare a tainelor programarii calculatoarelor. Bucuresti, 2012 CUPRINS 1, Introducere 1.1. Algoritmi 1.2. Limbaje de programare 2. Nofiuni de baz pentru scrierea programelor in limbajul C 2.1. Etape de creare a programelor in limbajul C 2.2. Notafii si vocabular in limbajul 2.3. Exemple simple de programe scrise in limbajul C.... 3. Date si tipuri de date in limbajul C .... 3.1. Nofiunile de date si tip 3.2. Tipuri de date specifice limbajul 3.3. Tipuri de date scalare . 3.3.1. Declararea variabilelor 3.3.2. Dimensiunea (in numar de octefi) a reprezen datelor 3.3.3. Tipul int (valori numerice intregi) 3.3.4. Tipuri pentru valori numerice reale . 3.3.5. Tipul char (reprezentarea caracterelor) 3.3.6. Tipul pointer 3.4, Probleme rezolvate 3.5. Probleme propuse 26 28 28 229 interne (binare) a .29 4, Operatori si expresii. Instruetiunile limbajului C ..... 4.1. Operatori si expresii 4.2, Instructiunile limbajului C . 4.2.1. Instruefiunea de atribuire 4.2.2. Instructiunea compusi (sec 4.2.3. Instruetiunea if (decizie logic’) 4.2.3.1, Operatori relationali (de comparafie) 42.3.2. Operatori logici . 42.3.3. Operatori aritmetici 42.3.4. Operatori de atribuire aritmetic’ 4.23.5. Exemple de utilizare a instructiunii if 44 4.2.3.6. Instructiuni if pe mai multe niveluri . . 46 4.2.3.7. Operatorul conditional . 47 4.2.4. Instructiunea switch (selectia) . 48 4.2.5. Instructiuni repetitive .... 49 4.2.5.1. Operatorii de incrementare/decrementare ... on 50 4.2.5.2. Efecte secundare ale operatorilor de incrementare si decrementare .... 4.2.5.3. Instructiunea while 4.2.5.4. Instructiunea do ... while . 4.2.5.5. Instructiunea for 4.2.6. Instructiunile break, continue si goto 4.3. Alfi operatori ai limbajului C 4.3.1. Operatori la nivel de bit . 4.3.2. Operatorul virgula .. 4.3.3. Operatorul pentru conversie explicit de tip 4.4, Probleme rezolvate 4.5. Probleme propuse 5, Tipul tablou (masiv) ... 5.1. Declararea variabilelor tablou unidimensional 5.2. Utilizarea variabilelor tablou unidimensional 5.3. Tablouri (masive) cu mai multe dimensiuni 5.3.1. Tablouri (masive) bidimensionale 5.3.2. Particularitati legate de declararea cu inifializare . 5.3.3. Exemple simple de prelucrare a tablourilor bidimensionale 5.4, Metode de cautare sau sortare a valorilor in tablouri unidimensionale .. 88 5.4.1. Metode de cautare ... 88 5.4.2. Metode de sortare (ordonare) 92 5.4.2.1. Algoritm simplu de sortare cu interschimbare 92 5.4.2.2. Metoda selectiei 93 5.4.2.3. Sortarea prin insertie 94 5.4.2.4. Metoda bulelor (Bubble sort) . 95 5.5. Probleme rezolvate ..... 97 5.5.1. Declararea si prelucrarea datelor de tip tablou .. 97 5.5.2. Cautarea si ordonarea valorilor in entitafi de tip tablou 101 5.6. Probleme propuse 6. Funcfii definite de citre programator ... 6.1. Definirea functiilor in limbajul C . 6.2. Variabile locale, variabile globale 6.3. Funcfii definite de catre programator care apeleazi alte functii, definite tot de catre programator 120 6.4. Parametri transmisi prin valoare, parametri transmisi prin referinfa 121 6.5. Funcfii recursive 6.6. Probleme rezolvate 6.7. Probleme propuse 125 129 133 7, Relagia pointeri — tablouri - functii 7.1. Pointeri si operafii cu pointeri 7.1.1, Adunare/scidere de constante la o valoare pointer 7.1.2. Incrementarea/decrementarea valorilor pointer . 7.1.3. Pointer NULL..... 7.1.4. Pointer void * .. 7.1.5, Scliderea a doi pointeri de acelasi tip 7.1.6. Atribuirea de valori pointer 7.1.7. Compararea valorilor pointer 7.2. Calificatorul const aplicat variabilelor de tip pointer 7.3. Pointeri si tablouri unidimensionale .. 7.3.1. Utilizarea variabilelor tablou unidimensional ca parametri ai functiilor 7.3.2. Pointeri catre tablouri unidimensionale 7.4. Pointeri si tablouri cu mai multe dimensiun 7.5. Utilizarea variabilelor tablou multidimensional ca parametri ai functiilor 7.6. Pointeri la functii . 7.7, Functii cu rezultat de tip pointer 7.8. Alocarea dinamica a memoriei 7.8.1. Utilizarea operatorului sizeof( ) 7.8.2. Functii de bibliotecd destinate alocai descrise in stdlib.h 7.9. Probleme rezolvate 7.10. Probleme propuse .. Anexa - Setul de caractere ASCII/ASCII extins Bibliografie .. Capitolul 1 INTRODUCERE Programarea calculatoarelor este 0 componenta de baz a stiintei si ingineriei calculatoarelor, functionarea sistemelor de calcul fiind guvernata de inteligenta inglobata in programe create de oameni cu ajutorul limbajelor de programare. De aceea, dobandirea cunostintelor de bazi necesare pentru proiectarea si realizarea proiectelor software reprezint un prim pas, extrem de important, in formarea oricirui viitor specialist din domeniile Automatica si Calculatoare, Electronica si Telecomunicatii dar si din multe alte domenii in care sistemele de calcul au devenit deja instrumente de lucru cotidiene. 1.1 Algoritmi Algoritmul poate fi definit simplu si intuitiv ca metoda de rezolvare a unei probleme. La fel ca in viata de zi-cu-zi, 0 aceeasi problema poate fi rezolvatd in moduri diferite, deci prin folosirea unor algoritmi diferiti. Oricare ar fi ins& metoda aleas, pentru a fi pus& in practica trebuie si indeplineascd un minimum de condifii: si fie descrisd clar, fard ambiguitati si si specifice toate operatiile ce trebuie realizate pentru rezolvarea problemei, exprimate prin comenzi pe care executantul le cunoaste si le poate indeplini. Deoarece limbajul natural nu permite o descriere a algoritmilor care sa corespunda cerinfelor mentionate, in acest scop sunt folosite, de obicei, instrumente specializate. in domeniul programarii calculatoarelor, doua dintre cele mai populare instrumente de scriere a algoritmilor sunt schema logica (organigrama) si limbajul pseudocod care evidentiazd cu claritate fluxul controlului algoritmilor (succesiunile posibile ale actiunilor). Schema logic (organigrama) utilizeaza reprezentiri grafice: © forme geometrice pentru specificarea actiunilor; © sgeti de legatura pentru precizarea ordinii in care se vor realiza actiunile. Formele geometrice nu sunt standardizate (impuse), de aceea exemplele ce vor fi prezentate in continuare constituie doar variante de utilizare. WL Reprezentare grafic Semnificatie List&_Date Bloc pentru introducerea datelor (citire) © List’&_Date contine nume simbolice c&rora li se asociaza valori preluate (citite) de pe suport de informatie extern. Pentru algoritm, acestea sunt date de intrare”, List8_Rezultate Bloc pentru extragerea rezultatelor (scriere) © List&_Rezultate contine nume simbolice reprezentand rezultatele problemei ce vor fi scrise pe suport de informatie extern. Pentru algoritm, acestea sunt ,date de iesire”. | V € Expresie Bloc de atribuire © se evalueazi Expresie; © se pastreaza in V valoarea astfel calculat’ Bloc de decizie (,,salt conditionat”) * Conditie poate sa aiba valoarea ,adevirat” sau ,,fals”, selecténd astfel pentru a fi executat urmatorul bloc conectat la una sau alta dintre cele doua ramuri. Blocuri pentru inceput/sfargit organigrama © marcheazi inceputul/sfarsitul schemei logice (organigramei) Limbajul_pseudocod permite scrierea algoritmilor cu ajutorul limbajului natural prin: © enunturi (fraze) standard sau nestandard, pentru specificarea actiunilor; © gruparea si alinierea enunturilor, pentru precizarea ordinii in care se vor realiza actiunile. Enunturile pentru specificarea actiunilor pot si confina cuvinte-cheie, adic niste cuvinte cu semnificatie stabilita de catre utilizator. De exemplu: Citeste sau Read pentru acfiunea de citire a ,datelor de intrare” si Afiseaz3 sau Write pentru actiunea de scriere sau transmitere a rezultatelor (,.datelor de iesire”) etc. Exemplu: Sa se scrie algoritmul pentru calcularea sumei primelor n numere intregi pozitive. Pentru reprezentare se vor folosi, comparativ, doua variante: schemi logic si limbaj pseudocod. Schema logica Limbaj pseudocod Citeste n START suma € 0 Pentru i € 1...n, cu Pas=1 Execut& ‘suma € suma + i Wi, Afiseaz’ suma suma € 0 i€1 + suma € suma +i ieitt STOP Oricare ar fi varianta aleas& pentru reprezentarea algoritmului, rezolvarea unei probleme presupune parcurgerea unui numar minim de etape: * analiza problemei — se stabilesc informatiile de prelucrat (,date de intrare”), rezultatele cerute (,,date de iesire”) si functiile pe care trebuie si le realizeze produsul final. Se iau in considerare condifiile concrete in care se va realiza functionarea gi toate cerintele beneficiarului. Se stabileste forma de organizare si reprezentare a datelor de intrare si iesire. Pentru exemplul anterior, acestea sunt: - date de intrare: n (numa intreg pozitiv, citit de la tastatura); 1B - date de iesire: suma (numar intreg, afigat pe o linie a ecranului, in forma sum: : - funcfia: calculeazi suma primelor n numere intregi pozitive prin iteratii succesive. © proiectare — se cauta si se stabileste algoritmul de rezolvare a problemei. Este cea mai dificilé si cea mai complex etapa, pentru stabilirea algoritmului find necesare de multe ori cunostinje si colaborare interdisciplinara. in cazul problemelor de mare complexitate, elaborarea algoritmului se face, in general, prin detalieri succesive. Se trece astfel, treptat, de la o reprezentare general, abstract, a problemei, la o reprezentare detaliati, orientaté pe sub-probleme. Fiecare sub-problema poate fi tratat separat, constituind un modul al algoritmului. Organizarea modulara se va reflecta si in produsul final, usurand munca in cadrul etapei de implementare si a celei de testare; * implementare — pe baza specificatiei de proiectare si utilizind in mod adecvat instrumentele si materialele necesare, se realizeaz produsul final (programul scris cu ajutorul unuia sau mai multor limbaje de programare, in cazul programirii calculatoarelor); © testare si validare — se verified produsul final cu ajutorul unor planuri di testare. In cazul programelor, verificarea se face in scopul elimindrii erorilor de sintaxa (de utilizare a limbajului de programare) si a celor de logica. Pentru ultima categorie, se folosesc seturi de date de intrare cu rezultat cunoscut si se verificd daca programul produce rezultatul dorit. Observatie: Activitatea de dezvoltare a unui produs nu se incheie in momentul validarii, Din acel moment incepe etapa de intrefinere (maintenance — engl.), care, spre deosebire de celelalte etape, este nelimitata. in etapa de intretinere se realizeazi modificari ale produsului, fie in scopul corectarii unor deficienfe de functionare depistate in cursul utilizarii sale, fie pentru a-I adapta unor noi cerinfe. O importanféi deosebitd o are in aceasti etapi documentafia produsului care ugureazi activitatea de intretinere, mai ales pentru alte persoane decat cele care |-au creat. 1.2 Limbaje de programare Unui calculator numeric i se pot transmite comenzi (instructiuni) prin apasarea tastelor functionale, dar nu poate fi folosit eficient daca instructiunile nu ii sunt furnizate rapid, la o vitez apropiati sau identicd celei cu care lucreaza procesorul. De aceea, se preferi ca instructiunile necesare pentru rezolvarea unei probleme, codificate numeric (binar), sé fie plasate in memorie, alaturi de date. Grupul de instructiuni prin care se implementeaz4 algoritmul de rezolvare a problemei poarti numele generic de program. 14 Daci sistemul de calcul infelege si lucreazi la nivel hardware (fizic) cu instructiuni exprimate binar (secvente de valori 0 si 1), utilizatorul uman are nevoie, la nivel logic, de o exprimare mai apropiata de limbajul natural si/sau matematic. Acesta este motivul pentru care, de-a lungul anilor, instrumentele cu ajutorul c&rora oamenii au scris programele destinate rezolvarii problemelor cu ajutorul sistemelor de calcul au evoluat de la nivelul criptic al ,codului masina” la cel mult mai accesibil al limbajelor de programare modeme. Codul_masina” reprezenta conventia de programare prin care instructiunile destinate unui anumit tip de procesor se scriau direct in forma numericd binard. Evident, metoda avea cteva dezavantaje importante: © datorité naturii primitive a instructiunilor exprimate in cod masind, folosirea lor era greoaie si genera multe erori; © programele scrise in cod masina erau greu de injeles si de modificat; © programarea reprezenta o activitate consumatoare de timp si costisitoare, motiv pentru care se dorea folosirea unui acelasi program pe sisteme de calcul diferite. Aceasta cerinf, numita portabilitate, nu era satisfacuta de programele scrise in cod masind, care erau specifice unui anumit procesor si nu puteau fi executate pe nici un altul, Pentru usurarea muncii programatorului, s-a trecut la un nivel de abstractizare mai ridicat, prin crearea limbajelor_de_asamblare care permiteau scrierea instrucfiunilor cu ajutorul unor convenfii de notafie in care se foloseau litere, cifre gi alte cdteva caractere cu rol de operatori si separatori, similare celor din matematica, De exemplu, ADD 3, 25; putea reprezenta instructiunea de adunare a valorilor 3 si 25, cu memorarea rezultatului intr-un registru al unitatii centrale. Pentru ca instructiunile sé poata fi infelese la nivel hardware, au fost create programe specializate (utilitare), numite asambloare, care s&_,,traduca” programul in forma binara, incercarile de gasire a unui limbaj de programare usor de folosit si performant au continuat pana cand s-a ajuns la un compromis intre lizibilitatea si generalitatea limbii engleze si precizia si modul direct de adresare al codului masina. Astfel au luat nastere limbajele de programare de nivel inalt, ale céror principale avantaje sunt: © naturalefea — sunt apropiate de limbajele naturale si/saulimbajul matematic; © usurinta de intelegere si de utilizare; * portabilitatea — posibilitatea ca un acelasi program s& se execute, cu modificari minime, pe sisteme de calcul de tipuri diferite; © eficienta in scriere — se pot defini noi tipuri si structuri de date, operatii ete, 15 Limbajele de nivel inalt, la fel ca oricare alte limbaje, pot fi studiate atat din punctul de vedere al sintaxei (gramaticii) cat si al semanticii (infelesului). Sintaxa precizeazi elementele de limbaj si regulile ce guverneaz folosirea acestora iar semantica specifica semnificatia fiecdrui element sau combinafie de elemente. Un program soris cu ajutorul unui limbaj de programare de nivel inalt, numit gi program sursi, nu poate fi executat direct de catre hardware-ul sistemului de calcul, ci trebuie tradus mai intai intr-un set echivalent de instructiuni exprimate in cod msin& (program obiect), operatie realizata de catre un program de sistem (utilitar), specializat, numit compilator. in timpul compilarii pot fi semnalate erori de folosire a limbajului, raportate de compilator sub forma unor mesaje de eroare sau a unor numere care se refer la o lista de astfel de mesaje. in cazul anumitor sisteme de calcul, codul masind rezultat prin compilarea unui program sursi ar ocupa un spatiu de memorie inacceptabil de mare in raport cu cel disponibil. De aceea se prefer ca in locul compilatorului sé se foloseasca un interpretor care si efectueze la acelasi moment de timp atat analiza sintacticd a instructiunii, cat si executia ei. Principalul dezavantaj al acestei metode este acela ca folosirea interpretorului determina o executie mai lenta a programelor decét in cazul compilarii. Un mare avantaj este ins faptul cd interpretoarele sunt capabile si detecteze mai usor erori de programare ce nu ar putea fi depistate decit, eventual, in faza de executie a programelor compilate. in prezent, in lume se folosesc sute de limbaje de programare ce se conformeazi diferitelor paradigme adoptate de-a lungul timpului. Clasificarea si prezentarea caracteristicilor fiecaruia dintre acestea depageste cu mult scopul acestei lucrari. De aceea, in cele ce urmeaza vor fi abordate problemele de baza referitoare la utilizarea unui limbaj procedural de nivel mediu pentru programarea sistemelor de calcul, folosind ca instrument principal limbajul C, Cunoasterea acestui limbaj reprezinta o etapa necesara in formarea oric&rui programator, asigurand si instrumente adecvate pentru intelegerea gi invatarea usoara gi rapidi a caracteristicilor altor limbaje de programare, inclusiv a celor orientate-obiect (CH, Java etc.). Limbajul C este considerat un limbaj de nivel mediu deoarece combina avantajele limbajelor de nivel inalt cu funcfionalitatea limbajelor de asamblare (permite manipularea bitilor, octetilor si adreselor de memorie, elemente de bazi la nivel hardware). Este un limbaj structurat, avand drept componenta principala functia — un bloc de instructiuni dedicat rezolvarii unei probleme specifice, organizat intr-o forma speciala, reglementata de sintaxa limbajului. Creat si implementat pentru prima data in anul 1972 de catre Dennis Ritchie de la AT&T Bell Laboratories, limbajul C a cunoscul 0 evolutie constant si spectaculoasd 16 alaturi de sistemul de operare UNIX. Pentru a asigura compatibilitatea aplicatiilor scrise cu ajutorul acestui limbaj, ANSI (American National Standard Institute) a infiinfat in anul 1983 un comitet care si creeze un standard dedicat. A fost elaborat astfel standardul cunoscut sub numele de ANSI C, publicat in anul 1988, urmat de standardul C99, publicat in anul 1999 si adoptat ca standard ANSI in anul 2000. Activitatea comitetului a continuat, sub egida TSO/TEC (International Organization for Standardization / International Electrotechnical Commission), urmarind modernizarea si adaptarea limbajului la cerintele impuse de evolutia hardware/sofiware a lumii deosebit de complexe a sistemelor de calcul. Detalii legate de aceasta activitate gi un set de documente de standardizare elaborate sau in curs de elaborare pot fi gasite pe site-ul ISO/IEC: http://www.open-std.org/jtc1/sc22/wg14/. Limbajul C este un limbaj agreat de programatori, o contributie esentiald la cresterea popularitafii sale avand-o faptul ca a putut fi utilizat cu succes in locul limbajului de asamblare, permijind un control riguros al hardware-ului si al dispozitivelor periferice. Folosit initial pentru scrierea programelor de sistem (sisteme de operare, editoare, compilatoare, interpretoare etc.), a devenit treptat un limbaj utilizat tot mai des pentru scrierea programelor de aplicatii (inclusiv a celor de timp real), carora le asigura un nivel ridicat de eficienta si portabilitate. Capitolul 2 NOTIUNI DE BAZA PENTRU SCRIEREA PROGRAMELOR IN LIMBAJUL C Scrierea programelor cu ajutorului limbajului C necesita cunoasterea sintaxei si semanticii limbajului, a notatiilor si vocabularului cu care acesta opereazi, a modului de structurare a instructiunilor dar sia principalelor etape ce trebuie parcurse pani la obtinerea produsului program final. 21 Etape de creare a programelor in limbajul C Crearea unui program cu ajutorul limbajului C se realizeazd prin parcurgerea a cel putin patru etape principale: * scrierea programului sursa (editarea) — se realizeaza, de obicei, cu ajutorul unor programe de sistem (utilitare) specializate, numite generic editoare. Acestea ajuté programatorul, oferind facilitati de copiere, inserare, stergere a unor caractere sau grupuri de linii de text, salvare a textului scris pe suport magnetic sub forma de fisier etc. Numele fisierului poate fi stabilit de c&tre programator, extensia folosita fiind de cele mai multe ori .C, pentru a sugera natura informatiilor continute; © compilare — se realizeaz& cu ajutorul altui program de sistem (utilitar), numit compilator. Acesta verificd programul sursi pentru a depista eventualele erori legate de folosirea sintaxei limbajului. Erorile sunt semnalate utilizatorului prin mesaje adecvate si trebuie corectate prin revenire la etapa de editare. Daca fisierul sursi nu contine erori de sintaxa, compilatorul ,,traduce” continutul pe intelesul hardware-ului, creand un nou fisier, numit program obiect. Numele de ,,obiect” este preluat din limba engleza (object) si se asociaz cu extensia .0B) a fisierului (in sisteme de tip Windows); © editare de legituri_(Jink-editare) — se realizeazi tot cu ajutorul unui program de sistem (utilitar), numit editor de legdturi sau link-editor care adaugi programului obiect module din biblioteca asociata limbajului (detalii in Partea a Il-a) sau alte module obiect, in cazul unei aplicatii software formate din mai multe fisiere (detalii in Partea a II-a), Erorile depistate in aceasta etapa pot impune revenirea la etapa de compilare sau chiar la etapa de editare. Rezultatul etapei de editare de legaturi este figierul executabil, cu extensie .EXE (in sisteme de tip Windows, de exemplu); lansare in executie — programul executabil este adus in memorie si lansat in executie. Se realizeazi citirea datelor de intrare, prelucrarea informatiilor si afigarea sau transmiterea rezultatelor (datelor de iesire) exact in forma precizata initial in programul sursé. Se verific, pe baza unor seturi de date prestabilite, corectitudinea rezultatelor. Dacd apar erori, acestea tin de logica programului: fie nu a fost gandit corect, fie a fost scris eronat. In acest caz, se revine la etapa de editare. Etapa de executie poate fi repetati de cate ori este necesar. 1. EDITARE - se foloseste un program utilitar: EDITOR = se creeazi programul surs: Exemplu.C : LN 2, COMPILARE - se foloseste un program utilitar: COMPILATOR (traduce sursa pe injelesul hardware-utui) - se creeazi programul obiect: Exemplu.OB) Erori de folosire a limbajului sau de scriere: MESAJE (umir, text) + 3. EDITARE DE LEGATURL - se foloseste un program utilitar: EDITOR DE LEGATURI (LINK EDITOR — engl.), care adaugi programului obiect module din biblioteca asociata limbajului sau alte module obiect - se creeazii programul executabil: Exemplu. EXE Erori de definire functii, specificare module de bibliotecd etc: MESAJE 4, LANSARE fN EXECUTIE - se citese datele se efectueaza calculele - se afigeaza rezultatele Frori de logic’: REZULTATR INCORFCTE Observatii: Revenirea la etapa de editare pentru corectarea unor erori presupune ca, dupa salvarea modificarilor in noua versiune a fisierului surs&, s4 se parcurgé secvential toate celelalte etape schitate in figura anterioara pentru a fi creat astfel un nou figier executabil, care s& contina schimbarile efectuate. in cazul programelor scrise cu ajutorul limbajului C, etapa de compilare contine si o sub-etapa preliminard, numita preprocesare. Aceasta se realizeazi automat, inaintea compilarii propriu-zise, si va fi explicati, pe scurt, in cadrul sectiunii 2.3 si detaliat, in cadrul celei de-a L1-a pirti a acestei serii de volume. 2.2 Notatii si vocabular fn limbajul C Vocabularul limbajului C este format din simboluri de bazi, clasificate in trei mari categorii: - literele alfabetului englez; - cifrele arabe: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; - simboluri speciale (operatori si delimitatori):.;,:2'"()[1{}<>!1 \/~ _#% RN +-*= Tot in categoria simbolurilor speciale se incadreazi si cuvintele rezervate, numite si cuvinte-cheie (keywords — engl.), care au un infeles bine stabilit si nu pot fi folosite de catre programator decat in contextul permis explicit de sintaxa limbajului C. Lista cuvintelor-cheie conforme standardului ANSI C este: asm continue —_—extern long static void auto default float register struct volatile break do for return switch while case double goto short typedef char else if signed union const enum int sizeof unsigned Scrierea unui program cu ajutorul limbajului C este similar scrierii de fraze in limbaj natural: se folosesc combinafii de ,,cuvinte” si ,,separatori”. »Cuvintele” limbajului C pot fi: - simboluri speciale; - identificatori obisnuiti sau predefiniti; - constante (numér, caracter sau gir de caractere). »Separatorii” se incadreazi, in general, in una dintre urmatoarele categorii: = spagiu; > comentariu; - sfiirsit de linie. Toate aceste elemente vor fi prezentate in cele ce urmeaz in contextul utilizarii lor pentru scrierea de programe. Dintre ele, vor fi definite deocamdata doar cele strict necesare pentru intelegerea primelor notiuni de sintaxa a limbajului. 20 Identificatorii reprezinti modalitatea de denumire a constantelor, tipurilor de date, variabilelor si functiilor. Constantele reprezinta date a caror valoare nu se modifica’ pe tot parcursul executiei programului. Prin contrast, variabilele reprezinti date a ciror valoare trebuie si poate fi modificati in program. Notiunile de tip de date si functie vor fi explicate in cadrul capitolelor 3 si, respectiv, 6. Un identificator este un nume simbolic care incepe cu o literd sau cu caracterul de subliniere (_ ), ce poate fi urmata/urmat de niciuna sau mai multe litere, cifre zecimale si/sau caracterul de subliniere. Limbajul C este un limbaj de programare case-sensitive (engl.), sesizand diferenta existent intre litere mari gi litere mici in cazul identificatorilor. De aceea, suma si Suma vor fi considerati identificatori distincti, 1a fel ca $i b13, respectiv B13 sau _azi i _AZI. Identificatorii ,obisnuifi” sunt nume scrise de citre programator, alese astfel inet si sugereze cat mai bine rolul entitatii pe care o reprezint& in cadrul programului, Identificatorii ,predefinifi” sunt nume cunoscute de catre compilator (de exemplu, numele unor functii de biblioteca), cu semnificatie bine stabilita si care, de obicei, sunt folositi de cltre programator si nu definiti sau redefiniti de c&tre acesta. Lungimea maxim& a unui identificator (numérul maxim de caractere) depinde de compilator, dar poate fi, in general, de cel putin 31 de caractere. Constantele folosite in scrierea programelor C pot fi clasificate astfel: © constant numericd — scrisi ca o secventi de cifre, cu sau fara semn (in cazul valorilor de tip intreg), la care se adauga punctul zecimal in rol de avirgula” (in cazul valorilor de tip real). De exemplu: -328 sau +14372 sau -27.135. Alte detalii vor fi prezentate in sectiunile 3.3.3 si 3.3.4; © constanta caracter — scrisi ca un caracter incadrat intre caractere apostrof. De exemplu: 'g' sau 'S' sau 'p'. Alte detalii vor fi prezentate in sectiunea 3.3.53 © constanta sir de caractere — scisi ca o secventa de caractere incadrata intre caractere ghilimele. De exemplu: "mesaj” sau “Buna ziua! ". Alte detalii vor fi prezentate in Partea a Il-a. Observatie: deoarece caracterele ”,', \ si ? au un rol special in sintaxa limbajului C, atunci cénd se doreste includerea lor in cadrul unei constante sir de caractere, sorierea trebuie facut astfel: \", \, \\, \2. De exemplu: “Anii \'90 au favorizat dezvoltarea unor noi tehnologii” “Citez: \”Munca il innobileaz’ pe om\".” in cadrul limbajului C, spatiul (blank — engl.), sfarsitul de linie si comentariul sunt considerate ,separatori”. intre oricare doua simboluri C consecutive este permisa aparitia unui numar arbitrar de separatori, cu urmatoarea exceptie: este 2 interzisd aparitia separatorilor in cadrul identificatorilor, constantelor numerice sau simbolurilor speciale. Deoarece numarul separatorilor consecutivi este arbitrar, limbajul C are un format liber, care permite alinierea frazelor din program (indent-are) astfel incat sa rezulte un text clar, usor de urmarit. Un comentariu este o portiune de text cuprinsa intre simbolurile speciale /* i */ care, desi face parte din programul sursa, este ignorati complet de catre compilator, rolul sau fiind doar de a usura infelegerea programului de catre cel care il citeste. Un comentariu poate cuprinde informatii despre autorul programului, despre continutul unui grup de instructiuni, despre data la care a fost creat sau modificat programul etc. Toate acestea constituie ,documentatia” programului sursa, un element extrem de util pentru faza de intretinere (maintenance — engl.) a produsului final. 2.3. Exemple simple de programe scrise in limbajul C Pentru a infelege cateva dintre regulile generale ce trebuie respectate in scrierea programelor cu ajutorul limbajului C, vom folosi mai intéi exemphul clasic al afisirii unui mesaj pe ecranul sistemului de calcul: #include int main () { printf("Buna ziua!\n"); return 0; } Daca vor fi parcurse corect etapele de compilare si editare de legaturi, lansarea in executie a programului va produce afigarea pe ecran a textului Bund ziua! si trecerea pe urmatoarea linie (datorita utilizarii constantei caracter speciale ‘\n’ despre care vor fi prezentate detalii in sectiunea 3.3.5). Este important de refinut faptul c& orice program C este compus din una sau mai multe entitati numite functii O functie poate grupa mai multe instructiuni dedicate rezolvarii unei probleme sau sub-probleme, intr-o forma specific’, bazati pe reguli clar stabilite in sintaxa limbajului, Aceste reguli vor fi prezentate in detaliu in cadrul capitolului 6. Deocamdaté este suficient s& se precizeze c& la scrierea unei functii trebuie si se stabileascd numele su, tipul rezultatului, informatiile cu care lucreazi (numite parametri si cuprinse intre paranteze rotunde) si instructiunile din care este format (corpul functiei), cuprinse intre simbolurile { si } (inceput si sfarsit de functie) si incheiate cu simbolul punct si virgula: Tip_rezultat_ Nume_functie (Lista_parametri) { Declaraii ; Instructiuni ; + 22 Funcfia numiti main() este o functie speciald, care trebuie scrisi in orice program C. in momentul lansarii in executie a programului, sistemul de operare transfer controlul acestei functii, prima instruciune a functiei main() find prima instructiune ce va fi executati. In functie de compilatorul utilizat si de modul de functionare dorit pentru program, tipul rezultatului functiei main() poate fi int, void sau poate lipsi, caz in care este considerat implicit ca fiind int. Tipul void este interpretat ca orice tip” sau ,nimic” si poate fi folosit atat pentru specificarea tipului rezultatului unei functii cat si pentru specificarea listei de parametri, in cazul in care se doreste ca aceasta si fie vida (functia nu are parametri). Detalii suplimentare legate de acest subiect vor fi prezentate in capitolele dedicate tipurilor de date, functiilor si pointerilor. Daca tipul precizat pentru rezultatul unei functii este altul decat void, functia trebuie si confind instructiunea return ce va fi explicati in cadrul capitolului 6. {in cele ce urmeazi, exemplele de program vor fi scrise in varianta: a} void main (void) { ... in exemplul de program prezentat anterior, pentru afisarea textului pe ecran se foloseste 0 functie de bibliotecd (nu creati de catre programator!), numité printf). Pentru ca aceastd functie si fie recunoscuté de ctre compilator, in program a fost introdusa inainte de main() linia de program: #include . Aceasta reprezinta o directiva preprocesor, nofiune ce va fi discutata in detaliu in cadrul capitolului dedicat, din Partea a Il-a. Pe scurt, se poate spune ci .preprocesorul” este un program utilitar ce examineaz4 programul sursd inainte de compilarea propriu-zisa si, in cazul considerat, introduce in locul liniei unde apare directiva continutul unui fisier sau, in general, al entitatii specificate dupa #include. Ulterior, compilatorul prelucreaza programul sursa astfel modificat (completat). in cazul exemplului ales, fisierul stdio.h este un fisier ,,antet” (header — engl.) care contine descrierea functiilor standard de citire/scriere (I/O), numele sdu reprezentand abrevierea denumirii STanDard Input Output (engl.). Parantezele unghiulare folosite in directiva indicd preprocesorului locul in care se afla fisierul stdio.h pe discul magnetic: directorul ,,standard”, implementat ca atare in compilator. Dupa cum s-a mentionat deja, mai multe detalii referitoare la aceste aspecte vor fi prezentate in cadrul unui capitol din Partea a II-a. Rolul includerii unor informatii succinte in aceasta sectiune este doar crearea unei imagini de ansamblu, care s permit programatorului s scrie, in cunostinta de cauzi, cu ajutorul limbajului C, primele programe simple. Urmiatorul exemplu de program ilustreaza stilul de lucru interactiv, concretizat in preluarea informatiilor, respectiv producerea gi transmiterea rezultatelor, pe baza unei conversatii om-calculator. Programul permite introducerea de la tastaturé a doud valori numerice intregi, calculand i afisand ulterior suma acestora. Programul satisface cerinta de generalitate (poate calcula suma oricdror 23 doua numere intregi) si include un comentariu care precizeaz’ scopul scrierii sale. I* program pentru calcularea sumei a doud valori numerice intregi */ #include void main(void) q 3 int nri, nr2, rezultat; -~—————‘ecleratie de variabile printf(“Introduceti cele 2 numere ce trebuie adunate:\n"); printf(“Primul numar="); scanf("%ed", &nr1); «<——4 printf(“Al doilea numar="); scanf("%d", &nr2); |_| instructiune de atribuire Itat = nrl + nr2; rezultat = nri + nr2; 17 printf("Suma este: %d \n", rezultat); | SPecificator de format aaa sir de control citeste 0 valoare de la tastatur’ Ca efect al lansatii in executie a acestui program si ca urmare a afisdrii pe ecran, in ecou, a celor doua valori numerice tastate de catre utilizator, se vor vizualiza urmitoarele informatii: Introduceti cele 2 numere ce trebuie adunate: Primul numéai Al doilea numar=: Suma este: 10 Elementele de sintaxa utilizate in cadrul exemplului precedent vor fi detaliate in cadrul capitolelor urmatoare, Pentru moment insé, iat o scurta descriere a lor: 24, © declaratia de variabile — precizeaza entitatile ce vor fi folosite in cadrul programului, prin nume simbolic (identificator) si tip de date asociat. Pe baza acestor informatii, compilatorul aloci spatiu de memorie pentru fiecare variabilé declaraté. in exemplul prezentat, cu ajutorul cuvantului cheie int se declard 3 variabile de tip intreg, numite nr1, nr2 si rezultat; © instructiunea de atribuire — ,umple” spatiul de memorie alocat variabilei rezultat cu valoarea calculata efectiv a expresiei nr1+nr2; © specificator de format — specifica tipul de data citita/afisata cu ajutorul functiilor din biblioteca standard descris& prin stdio.h; © functia de biblioteca scanf() — permite citirea de la tastatur a unor valori si memorarea lor la adresele asociate variabilelor din lista de parametri. in exemplul prezentat, specificatorul de format "%d" arataé ca se doreste citirea de la tastatura a unei valori de tip intreg exprimate in baza de numeratie 10 (decimal — engl.) si depunerea ei la adresa de memorie asociat variabilei nr1. Este important de retinut forma corecta de scriere: &nri si nu nri; Observatie: functiile de bibliotecd scanf() si printf() sunt functii cu numar variabil de parametri (aceast& notiune va fi prezentat’ detaliat in cadrul altui capitol din Partea a Il-a). Cele doua functii pot fi folosite in mod flexibil, cu conditia ca primul parametru si fie intotdeauna un gir de caractere (sit de control), iar urmatorii sa fie adrese de memorie - pentru scanf()), respectiv expresii - pentru printf(). In exemplul anterior, sirul de control "Suma este: %d \n" precizeazA att mesajul ce trebuie afisat pe ecran cat si tipul de data (%d) si pozitia pe care ea o va ocupa in cadrul mesajului. Dacd, de exemplu, in program s-ar fi folosit ca forma de apelare a functiei de bibliotecd printf("%d + %d = %d \n", nri, nr2, rezultat); informatiile afisate pe ecran ar fi fost: 6 + 4 = 10. Cel de-al treilea si ultimul exemplu de program prezentat in cadrul acestei sectiuni este 0 variant de implementare in limbaj C a algoritmului de calcul pentru suma primelor n numere intregi pozitive. Algoritmul a fost descris in sectiunea 1.1, comparativ, prin schema logica si limbaj pseudocod. Varianta sctisd in pseudocod avea forma: Citeste n suma € 0 Pentru i € 1...n, cu Pas=1 Executa suma € suma + i Afiseazi suma Chiar daca instructiunile do...while gi for vor fi descrise abia in cadrul capitolului 4, este usor de infeles semnificafia lor in cadrul programului, corespondenta limbaj pseudocod — limbaj C fiind extrem de sugestiva. In exemplu, instrucfiunea do...while este utilizaté cu scopul de a impune introducerea corect a datelor de intrare de la tastatura: atta timp cat valoarea variabilei n nu este strict pozitiv, programul va continua si execute ,,bucla” do...while si nu va trece la instructiunea urmitoare. /*program de calcul, scris in limbaj C */ #include void main (void) {int n, i, suma; do { printf("Introduceti valoarea lui n>0: "); scanf("%d", &n); }while (n<1); suma = 0; for (i=1; i<=n; i++) suma=sumati printf("Suma=%d\n", suma); + 25 Capitolul 3 ATE SI TIPURI DE DATE iN LIMBAJUL C 3.1 Nofiunile de date gi tip Date: = yinformatii furnizate” sistemului de calcul pentru a obfine de la acesta rezultatele dorite; - pot fi situate in afara sistemului de calcul (caz in care sunt citite prin intermediul unui dispozitiv periferic) sau se pot afla in memorie, find rezultatul unor calcule anterioare; - de obicei, sub forma de text — secvena de caractere ce apartin unui anumit set de caractere, bine definit. - uneori, sub forma de sunete sau imagini, dar nu abordim acum acest aspect! Din motive economice, sistemele de calcul folosesc un set de caractere cu numér de componente destul de redus, care include ins: = literele; - cifrele zecimale; ~ semnele de punctuatie uzuale; =o mare parte a simbolurilor matematice. Prin combinarea caracterelor din set poate fi exprimata sub forma de text o larga gami de date, Tip de date = stabileste atat semnificatia datelor cat si restrictiile de folosire a acestora; = compilatorul este cel care verific’ ,potrivirea” tipului datelor cu operatiile cerute (scrise) de programator. in afara sistemnului de calcul, valorile de orice tip se pot reprezenta ca text: = numere intregi: 27, -56, +234 (semn si cifre zecimale); 26 = numere reale: 32.5, -4.752, +3.1 (semn, cifre zecimale, punct); - caractere, fn interiorul_sistemului_de calcul, pentru reprezentarea valorilor se foloseste 0 alté forma. Hardware-ul unui calculator electronic este format din dispozitive ce se pot afla in doua stiri fizice distincte. Se spune cA un astfel de dispozitiv memoreazi 0 cifra binard sau un bit. Cu alte cuvinte: Numar | Denumire Numar | Semnificafia ce poate fi asociati stirilor de biti de stiri 1 | bit (cifra binara) | 2'=2 | valoarea 0 ; valoarea 1 8 | octet (byte) 2°= | Pot fi folosite pentru a codifica un set de 256 | caractere: se asociazd cite o stare (cod numeric) fiecdrui caracter 16 | 2 octeti (word) 2'6= | Pot codifica numerele intregi cu valori in 65536 | domeniul -32768...+32767, in acelasi mod ca pentru setul de caractere Reprezentarea interna este 0 codificare sub forma binard a valorii datelor. Ea respect reguli bine stabilite si permite specificarea unor seturi finite de valori deoarece numérul valorilor din set este restrictionat de numarul de biti folosit. De exemplu, in cazul reprezentarii pe 8 biti a caracterelor din setul ASCII (American Standard Code for Information Interchange): Caracterul | Reprezentarea binar& (codul ASCID_| Codul ASCII (in baza 10) A 0100 0001 65 B 0100 0010 66 a 0110 0001 97 b 0110 0010 98 5 (0011 0101 53 Observatie: reprezentarea numirului intreg 5 este diferita de reprezentarea caracterului cifra 5, atat ca numér de bifi folosit cat si ca valoare, Presupunand ci se lucreaz& cu un compilator ce reprezint& numerele intregi pe 2 octeti, pentru numirul intreg 5 se foloseste urmitoarea reprezentare intern’: Numirul Reprezentarea binara Valoarea (in baza 10) intreg 3 0000_0000 0000 0101 3 27 3.2 Tipuri de date specifice limbajul Scalare (valori sue- cesive, ordonate) Structurate (compuse pe baza celor scalare) caracter - char pointer (adresa) enumerare -enum tablou (masiv) vor fi prezentate in cadrul altor capitole structura - struct ‘uniune - union Tipul void - se foloseste mai ales pentru lucrul cu funetii si pointeri, cu semnificatia de ,nimic” sau de worice tip”, dupa caz! 3.3 Tipuri de date scalare Limbajul C asigura posibilitatea de declarare a variabilelor astfel incat ele si fie memorate eficient din punctul de vedere al spatiului ocupat (numar de octeti). Programatorul are la dispozitie mai multe tipuri de baza si atribute cu ajutorul clrora pot fi declarate variabile care s& se incadreze in diverse domenii de valori. Atribute short long signed unsigned Presupunand ca se lucreaz cu un compilator ce reprezint& numerele intregi pe 16 biti (conventie ce va fi utilizata pe tot parcursul acestor note de curs), iata citeva exemple de tipuri de date ce pot fi declarate in cadrul programelor C: Tip de date Numa de octefi Domeniul de valori int 2 32768 ... +32767 long int (sau long) 4 -2147483648 ... +2147483647 peg 4 0... +4294967295 (sau unsigned long) char 1 128... 127 28 Numérul de tipuri de date pe care sintaxa le permite prin combinarea tipurilor de bazi cu atribute este mult mai mare decdt cel prezentat ca exemplu. Informatii complete pot fi gisite in documentajia compilatoarelor, in sectiunile de ajutor (help) oferite de acestea etc. Compilatoarele confin anumite fisiere in care sunt pastrate sub forma de constante predefinite valorile minim’/maxima ale tuturor tipurilor de date pe care programatorul le poate utiliza in declararea variabilelor. Un exemphu in acest sens sunt fisierele values.h si limits.h. 3.3.1 Declararea variabilelor Fiecrei variabile declarate in cadrul unui program C i se alocd automat un spatiu cu dimensiune corespunzitoare tipului siu, la o anumité adresi de memorie care rimane neschimbati pe tot parcursul executiei programului. Spatiul de memorie este folosit apoi pentru pastrarea valorii variabilei. Programatorul este cel care stabileste pentru fiecare variabild cate un nume (identificator) cat mai sugestiv pentru rolul pe care aceasta il va avea in cadrul programului. Declararea unei variabile se face intotdeauna inainte de utilizarea acesteia intr-o instructiune, apel de functie etc. Declarare simpli; float x, y; /*se declara 2 variabile, numite x si y, numere reale, pentru care se _rezerva automat in memoria asociaté programului C cte 0 zond format din exact atatia octeti cAti corespund tipului float*/ Declarare cu initializare: int a, b=5, c=0; /*- se declar& 3 variabile, numite a, b sic, numere intregi, pentru care se_rezervl automat in memoria asociat’ programulul C cate © zona formata din exact atatia octeti cati corespund tipului int; - in zona de memorie asociat8 variabilei b se inscrie reprezentarea binar& a valorii intregi 5; - in zona de memorie asociat& variabilei c se inscrie reprezentarea jar a valorii intregi 0;*/ 3.3.2 Dimensiunea (in numéar de octefi) a reprezentirii interne (binare) a datelor Limbajul C posed un operator care permite aflarea numarului de octeti folosit pentru reprezentarea interna a valorilor de orice tip. Operatorul poate fi aplicat asupra unui tip de data sau asupra unei expresii (pe care o analizeazi pe baza tipului rezultatutui) in una dintre urmatoarele dou’ forme: sizeof(tip_de_dat3) sau sizeof(expresie). 29 De exemplu, fragmentul de program: printf("Tipul int se reprezinta intern pe %d octeti\n”, sizeof(int)); printf(’Tipul long int se reprezint& intern pe %d octeti\n”, sizeof(long); printf("Valoarea %d se reprezint& intern pe %d octeti\n”, 25+7, sizeof(25+7)); va avea ca efect afisarea pe ecran a urmatoarelor informatii: Tipul int se reprezinta intern pe 2 octeti Tipul long int se reprezintd intern pe 4 octeti Valoarea 32 se reprezinta intern pe 2 octet 3.3.3 Tipul int (valori numerice intregi) in limbajul C se pot utiliza urmatoarele tipuri intregi: int, long int (sau long), short int (sau short), unsigned int (sau unsigned), unsigned long int (sau unsigned long), unsigned short int (sau unsigned short). Primele 3 tipuri au semnificatia si pot fi chiar specificate explicit ca: signed int, signed long int, respectiv signed short int. Constantele de tip intreg pot fi exprimate in bazele de numeratie 10, 8 sau 16, precedate sau nu de semn (+ sau -), dup’ cum urmeaza: © zecimal - un sir de cifre zecimale, dintre care prima nu este 0 (zero). De exemplu; 15, -27, +33; © octal - cifra 0 (zero), urmati de un sir de cifre octale. De exemplu: 017, -033, +041; © hexazecimal - grupul de doud caractere 0x sau OX (zero gi x sau X), urmat de un sir de cifre hexazecimale, De exemplu: OxF, -0x1B, +0x21; Cu ajutorul sufixelor u sau U, respectiv | sau L se pot specifica si valori constante de tip intreg unsigned sau long. De exemplu: 13u sau 13U, respectiv 1171 sau 117L. Acest mod de scriere a constantelor este utilizat frecvent pentru specificarea valorilor parametrilor unor functii de biblioteca. Citirea sau afisarea (scrierea) valorilor de tip intreg cu ajutorul functiilor de biblioteca standard se face folosind descriptori de format adecvati: - zecimal - %d sau %i - octal - %o - hexazecimal - %x; -variante- %ld %lo %Ix (pentru tong - %hd %ho =%hx (pentru short - Yu (pentru unsigned) = %lu (pentru tong unsigned) = %lmu_—_ (pentru short unsigned) 30 Observatie: daca nu se foloseste un descriptor de format adecvat tipului declarat, valoarea cititi/afisati va fi afectaté de erori. Aceste erori pot influenta semnificativ rezultatele programului si sunt, in general, greu de identificat. Descriptorii de format permit afisarea ,tabelata” a valorilor, oferind programatorului posibilitatea s foloseasca si alte elemente. De exemplu: © numérul minim de pozitii al campului de afisare, in care valoarea va fi aliniata la dreapta iar pozitiile ramase libere se completeaz cu spatii printf("m=%7d", m); /* dac& m are valoarea 23, pe ecranaparem= 23*/ © semnul - dupa % indica alinierea valorii la stnga in cdmpul de afigare: printf(“m=%-7d", m); /* daca m are valoarea 23, pe ecran apare m=23 */ Observatie: daci valoarea confine mai multe cifre decat numarul minim de pozitii specificat in descriptor, ea va fi afisati pe atdtea pozitii cate ii sunt necesare (informatia furnizata de descriptor va fi ignorata). 3.3.4 Tipuri pentru valori numerice reale Pentru valori numerice reale, in limbajul C se pot utiliza urmatoarele tipuri: float, double si long double. Acestea diferd atat prin marimea valorilor cat si prin precizia reprezentarii acestora (numarul de cifre semnificative). in ipoteza c& se lucreaza cu un compilator ce reprezinta tipul int pe 2 octeti, tipul float asigura o precizie de 7 cifte zecimale semnificative si exponentul maxim 38, reprezentarea valorilor fcdndu-se pe 4 octeti. Tipul double asigura o precizie de 16 cifte zecimale semnificative (dublé precizie) si exponentul maxim 306, reprezentarea facdndu-se pe 8 octeti. In cazul tipului long double reprezentarea valorilor se face pe 10 octeti (precizie extinsa). Constantele de tip real pot fi scrise precedate sau nu de semn (+ sau -), astfel: - in notafie obignuiti: intreg.parte_fractionaré sau intreg. sau -parte_fractionar8. De exemplu: -5.1723, 5., 327, +0.02, -.364, +6. etc.; - in notafie stiinfificd: mantisé E exponent sau mantis’ e exponent. in acest caz, valoarea exprimata este mantis’ x 10°°"*", De exemplu: 0.3125 reprezint& valoarea 31200.0 iar 3.5E-3 reprezint& valoarea 0.0035. Observatie: pentru constantele de tip real se considera, implicit, cd sunt reprezentate in dubli precizie (tipul double). Pentru a impune reprezentarea constantei ca valoare float sau long double se folosesc sufixele f (sau F), respectiv | (sau L). De exemplu: 3.2 este constanté de tip double; 3.2f gi -5.23F sunt constante de tip float; -56.32! si 0.45L sunt constante de tip long double. 31 Citirea sau afisarea (scrierea) valorilor reale cu ajutorul functiilor de biblioteca standard se face folosind descriptori de format adecvati: - pentru tipul float - %f (notatie obisnuita) = %e (notatie stiintifica) = %Bg (minimizeazi numérul de cifre afigate) - pentru tipul double - %If = pentru tipul long double - %Lf Descriptorii de format pot confine si alte elemente utile programatorului. De exemplu, se poate preciza numarul minim de pozitii al cémpului de afigare si, in cadrul acestuia, numarul de cifre care s& fie afisate dup’ punctul zecimal: printf("x=%6.2f", x); /* dac& x are valoarea 3.2, pe ecran apare x= 3.20 deoarece numarul minim de pozitii al cémpului de afigare este 6 iar dintre acestea 2 sunt rezervate cifrelor de dupa punctul zecimal*/ Celelalte observatii facute in cadrul sectiunii 3.3.3 sunt valabile si in cazul reprezentarii valorilor reale. 3.3.5 Tipul char (reprezentarea caracterelor) in limbajul C deosebirea intre numere gi caractere se estompeaza, caracterele putand fi tratate ca valori numerice intregi pe baza numirului de ordine asociat in set (de exemplu, codul ASCII): charc; — /*declararea unei variabile ce poate memora un singur caracter*/ c=‘a'; —_/*echivalent cu c=97; unde 97 este codul ASCII asociat caracterului a */ Exemplu; urmatorul fragment de program citeste de la tastaturd un caracter si apoi afigeaz& pe ecran codul siu, exprimat in baza 10. char caracter; printf(’Tastati un caracter si ENTER: scanf("%c", &caracter); printf(”Codul numeric al caracterului %c este %d \n”, caracter, caracter); Se observa c& descriptorul de format utilizat pentru citirea/scrierea unei valori de tip char este %c si c& variabila numit’ caracter se va afisa mai intai sub form’ de caracter (utilizdnd %c) si apoi sub forma de numar intreg (utilizand %d). Atunci cénd in program se doreste utilizarea in rol de constante a unor caractere neimprimabile, acestea se scriu cu ajutorul codului numeric asociat, in una dintre urmatoarele forme: cifre_zecimale sau \xcifre_hexazecimale sau \Ocifre_octale. 32 in program pot fi folosite si anumite constante caracter mai speciale, numite secvenfe de control. Acestea se scriu tot intre caractere apostrof dar au urmatorul continut: \a__avertizare sonora \b _revenire la caracterul precedent (backspace) \f —_avans la pagina noua (form feed) \n__ sfarsit de linie (new line) \r _revenire la inceput de linie (carriage return) \t_ tab orizontal \ tab vertical \\ caracterul \ Vv caracterul ’ \" caracterul ” \? caracterul ? Constantele sir de caractere se scriu intre caractere ghilimele, De exemplu: “Mesaj” sau “Acesta este un sir de caractere”. Detalii legate de declararea si utilizarea unor variabile care si memoreze si si permit prelucrarea entitajilor sir de caractere vor fi prezentate in cadrul capitolului 5, si a altor dowd capitole din Partea a Il-a (despre pointeri si, respectiv despre siruri de caractere). Deoarece in cadrul acestui capitol s-au facut numeroase referiri la codul ASCII, trebuie mentionat faptul cA acesta este un cod standard pentru transmiterea de date folosit atét pentru reprezentarea textului (litere, numere, semne de punctuatie), ct si a comenzilor de non-input (caractere de control). Codul ASCII standard foloseste grupuri de 7 biti pentru fiecare simbol si poate reprezenta 128 caractere. Codul ASCII extins foloseste un sistem de codare cu 8 bifi si poate reprezenta 256 de caractere. Codul ASCII nu este singurul folosit in programare. De exemplu, un alt cod — numit Unicode - cu versiunile de 8, 16 si 32 de biti, a devenit codul standard pentru sistemele de operare moderne si pentru browsere Web, in special versiunea de 32 de biti permitand codificarea tuturor caracterele din principalele limbi ale lumii. Cele doud tabele din Amexa, preluate de pe site-ul Web http://bestofthisweb.com/blogs/ascii-character-set/, ofera informatii detaliate despre codurile numerice specifice codului ASCII/ASCII extins. 3.3.6 Tipul pointer Fiecarei variabile declarate in cadrul unui program C i se alocd automat un spatiu cu dimensiune corespunzatoare tipului séu, la 0 anumité adres de memorie care rimane neschimbati pe tot parcursul executiei programului. Spatiul de memorie este folosit apoi pentru pistrarea valorii variabilei, Adresa 33 de memorie este ea insisi o valoare ce poate fi folosita in program. Variabilele care pot reprezenta o valoare adres’ de memorie se numesc variabile pionter (adres). La fel ca si celorlalte variabile, la declarare li se alocd automat un spatiu in memorie, similar ca numar de octeti cu cel al tipului long int. Exemplu: int m, k; int *p; — /*se declara variabila p ca pointer la valori de tip int*/ &k; — /*se atribuie variabilei p valoarea: adresa variabilei k* *p; _/*se atribuie variabilei m valoarea de tip int ce se afl adresa inscris& in variabila p (continutul de la adresa p)*/ in memorie la - variabila pointer se declara intotdeauna impreuna cu tipul de date a c&rui adresi de memorie o va putea reprezenta; = simbolul * se foloseste atat la declararea variabilei pointer cét si la utilizarea acesteia, dar cu semnificatii diferite; - simbolul & se foloseste in acest context pentru a obfine ca valoare adresa de memorie a unei variabile. Detalii referitoare la utilizarea variabilelor de tip pointer si a importantei pe care © au acestea in cadrul limbajului C vor fi prezentate gradual, in cadrul capitolelor urmatoare, 3.4 Probleme rezolvate Aceasti sectiune prezinté cfteva probleme care sa familiarizeze cititorul cu utilizarea datelor de tip scalar in cadrul unor operafii simple si cu facilitatile de citire a informatiilor de la tastatura, respectiv afisarea acestora pe ecran, oferite de functiile C standard scanf() si printf). Deoarece atat instructiunile cat si operatorii specifici limbajului C constituie subiectul urmatorului capitol, rezolvarile problemelor nu sunt foarte elaborate, in sensul ci nu includ, de exemplu, secvente dedicate verificarii datelor introduse de la tastatura, Pastrarea simplitatii a avut drept obiectiv usurarea infelegerii notiunilor prezentate, mai ales pentru ,,incepitori”, Capitolele urmitoare vor prezenta, in mod gradat, rezolvari de probleme din ce in ce mai complexe si mai complete. Problema 1, O dati calendaristica, introdusd de la tastatura sub forma a trei valori intregi (zi, lund, an), trebuie afisat& pe ecran sub forma zi/lund/an, pastrand din valoarea anului doar ultimele doua cifre. Scrieti programmul care sa realizeze aceasta cerinti. #include void main( ) 34 {int zi,luna,an; printf("Introduceti ziua: printf(“Introduceti luna: "); scanf("%d", 8luna); printf(“Introduceti anul: "); scanf("%d", &an); printf("%2d/%2d/%02d",zi,luna, an%100); /* Formatul de afisare %02d este folosit pentru functionarea corect’ a programului chiar gi in situati ilare anului 2003, deoarece restul impartirii la 100 a valorii 2003 este 3 (0 singurd cifra), iar cerinta era sa se afiseze 03 (doué cifre) "); scanf("%d", &zi); */ } Observatie: in expresia an%100 din cadrul ultimei instructiuni se foloseste simbolul % cu semnificatia de operator aritmetic asociat operatiei de calculare a restului intreg provenit din imparfirea a doua valori intregi. Detalii despre acest operator sunt prezentate in sectiunea 4.2.3.3. Problema 2, Doud momente de timp sunt exprimate in ore, minute si secunde (valori de tip intreg). Sa se calculeze suma lor, exprimatd in acelasi mod. #include void main( ) {int h1,h2,m1,m2,s1,s2,h,m,3; printf(*Introduceti primul moment de timp): \n"); %Fod%d%d", Bhi, &N1, &s1); printf(“Introduceti al doilea moment de timp: \n"); scanf("%d%d%d", &h2, &m2, &S2); s=si+s2; 1+m2+s/60; h=(hith2+m/60)%24; m=m%60; printf("suma este: %02d : %02d : %02d", h, m, s); } Observatie: simbolul / reprezintd operatorul aritmetic asociat operatiei de calculare a catului intreg provenit din impartirea a doua valori intregi. Simbolul + reprezint& operatorul aritmetic asociat operatiei de adunare a doua valori. Detalii despre acesti operatori sunt prezentate in sectiunea 4.2.3.3. Problema 3. Scrieti un program care si citeascd de la tastaturd trei valori intregi, pozitive, strict mai mici decdt 1000, pe care apoi sa le tipareasca impreund cu media lor aritmetica sub forma: A=*** B= Co4 MEDIA=* $-a notat prin * o pozitie pe care se va afisa un caracter ce face parte din reprezentarea valorii numerice respective. #include void main( ) 35 {int a,b,c; float media; printf("Valorile pe care urmeaza sa le introduceti de la tastatura trebuie sa fie:\n\t de tip intreg, pozitive si strict mai mici decat 1000.\nIn caz contrar, programul va furniza rezultate eronate!\n); printf("Introduceti A: "); scanf("%d",8a); printf(“Introduceti 8: "); scanf("%ed",&b); printf("Introduceti C: ");_scanf("%ed",&c); media = (float)(a+b+c)/: printf("\nA = %3d B= %3d C= %3d Media = %6.2f\n",a,b,c,media); 3 Observatie: in cadrul rezolvarii se foloseste operatorul de conversie explicita de tip, sub forma (float). Detalii despre semnificatia, utilitatea si modul de folosire ale acestui operator sunt prezentate in sectiunea 4.3.3. Problema 4. Considerand Raza - raza unui cere, Lung - lungimea cercului si ‘Aria — suprafaja acestuia (valori numerice de tip real), sd se scrie un program care si realizeze urmitoarele operati = si citeascd Raza de la tastaturd (0 valoare strict pozitiva); - si calculeze lungimea si aria cercului, folosind formulele consacrate, si si afigeze urmitoarele informatii Raza cercului: **#*,4#* Lungimea cercului: ****,*** Aria cercului: ***#*.106* #include #include void main( ) {float raza, lung,aria; printf(“Introduceti raza cercului (neaparat o valoare strict pozitiva!):"); scanf("%f",&raza); lung= 2 * 3.1415 * raza; i .1415 * raza * raza; /* Din biblioteca math.h putem folosi constanta predefinita M_PI. Liniile anterioare devin: lung= 2 * M_PI * raza; M_PI * raza * raza; */ printf("Raza cercului: %8.3f\nLungimea cercului: %8.3f\nAria:%10.4f", raza, lung, aria); 3 Problema 5, Scriefi un program care si citeasca de la tastaturé un numir si sd afiseze sub forma de tabel: numérul respectiv, numarul ridicat la puterea a doua, aumérul ridicat la puterea a treia si numirul ridicat la puterea a patra. #include #include 36 void main( ) {double nr; printf(“Introduceti nr: "); scanf("%IF",8inr); printf("%6.2IR\t%6.2IF\t%6.21F\t%6.2IF\n", nr, nrénr, nrénrnr, nrénrénrénr); /*Din biblioteca math.h se poate folosi functia pow() pentru a ridica un numar la o anumit& putere specificat&. Linia anterioara poate fi scris& astfel: printf("%6.2IF\t%6. 2IF\t%6. 2IF\t%6.2IF\n" nr, pow(nr,2),pow(nr,3),pow(nr,4)); di 3 3.5 Probleme propuse Problema 1, Sa se scrie un program care citeste o valoare real si o afiseazi repetat, cu una pana la cinci zecimale. Problema 2. De la tastaturd se citesc dou numere intregi. Sa se afiseze pe ecran cele dou’ numere astfel: a) Primul numar, doua randuri libere, al doilea numar; b) Ambele numere pe acelasi rand, in zone de afisare de cate 20 de pozitii, aliniate la dreapta; Problema 3. Scrieti un program prin care, folosind operatorul sizeof(), sa afisati numérul de octeti pe care se reprezinté intern valorile de tip intreg (toate variantele existente in limbajul C), real (idem) si caracter. Observatie: numirul de octeti poate fi diferit in functie de compilatorul folosit (Iucra pe 16, 32 sau 64 de biti). Problema 4, Folosind setul de caractere ASCII/ASCII extins, scrieti un program care s& citeasci de la tastaturi codul unui caracter si si afigeze pe ecran caracterul respectiv. Reciproc, scrieti un program care si citeasca de la tastatur’ un caracter si s& afiseze pe ecran codul ASCII al acestuia. Se recomanda si nu folositi in acest scop caracterele netiparibile sau care nu se regasesc pe tastaturi. Problema 5. Scriefi un program care si citeascd de la tastaturi trei valori de tip int, long int, respectiv unsigned long int si apoi sa le afigeze pe ecran. Observati apoi ce se intimpla dac& modifcati programul si scrieti gresit formatele de citire sau de afigare (de exemplu, folositi numai formate pentru int si in cazul celorlalte tipuri de valori). Problema 6. Rezolvati o problema similaré Problemei 5 folosind valori de tip float, double si long double. 37 Capitolul 4 OPERATORI SI EXPRESII. INSTRUCTIUNILE LIMBAJULUI C 4.1 Operatori si expresii Limbajul C permite folosirea unui numar mare de operatori (mai mult de 40). Un operator se reprezint& cu ajutorul unuia sau mai multor caractere speciale, alaturate. De exemplu: = sau + sau + ete. Tipuri de operatori: © unari— folosese un singur operand; © binari— folosesc doi operanzi; © ternar— foloseste trei operanzi. O expresie este 0 combinafie de operanzi si operatori scrisi astfel incdt, respectand regulile limbajului de programare, si conduca la calcularea unei valori unice de tip intreg, real sau pointer, numita rezultat, Expresia poate contine subexpresii a cdror evaluare si implice si conversii de tip automate (implicite) sau explicite. Regulile de realizare a acestor conversii vor fi prezentate in sectiunea 4.3.3. La fel ca si in matematici, ordinea efectuirii operatiilor in cadrul unei expresii este stabilité de prioritatea operatorilor, care poate fi modificata prin utilizarea parantezelor rotunde () pe oricat de multe niveluri este necesar. Observatie: spre deosebire de matematica, in limbajul C nu este permisi folosirea in expresii a parantezelor drepte [ ] sau a acoladelor { } pentru modificarea ordinii de efectuare a operatiilor. Atunci cdnd intr-o expresie apar operatori_cu_aceeasi_prioritate, ordinea de efectuare a operatiilor este impusi de ordinea de asociere a operatorilor. in general, aceasta este ,,de la stanga la dreapta” dar exist si doua excepfii, operatorii unari si operatorii de atribuire, in cazul carora ordinea de asociere este de la dreapta la stinga”. 38 Ordinea de evaluare a subexpresiilor de cAtre compilatoare nu este, in general, impusi de standard. De exemplu, in cazul expresiei (3+5)*(7+2), se considera c& nu este important faptul ci se evalueazd mai intai expresia din stinga operatorului de inmultire si apoi cea din dreapta sau invers, deoarece rezultatul final este acelasi, Exist ins si excepfii. Un exemplu in acest sens sunt expresiile ce contin operatori logici, caz in care care standardul impune compilatoarelor si evalueze mai intai expresia din stanga operatorului. Categoria Semnifie Mod de asociere Primari ‘Apel functi, selectie tanga - dreapta Conversie explicita de tip Dimensiune in octet Adresa Una Continutul adresei dreapta - stinga + = | Stabitire semn 1 ~ | Negare logics bit cu bit ++ — _| incrementare/decrementare Multiplicativi = % sting -dreapta ‘Adunare, scidere ome stanga dreapta Deplasare (nivel bi) <> stinga - dreapta Relasionali 23 = stnga -dreapta Testare egalitate =i stinga - dreapta I (nivel bit) & stinga - dreapta SAU exclusiv 5 ‘ (aivel bit) stings - drespea ania | stinga - dreapta ogic ak stings -dreapta SAU logic i stinga -dreapta Conditional , ; (operator tornar) UG emcee Atribuire dreapia - stinga Virgula : stinga - dreapta 4.2 Instructiunile limbajului C Instructiunile limbajului C asigura instrumentele necesare pentru a descrie operatiile ce trebuie executate prin program si pentru a controla ordinea in care ele se vor executa. 4.2.1 Instructiunea de atribuire Instructiunea de atribuire se scrie cu ajutorul unei expresii de atribuire urmate de caracterul ,,punct si virgula”. 39 Operandul din partea stingé a expresiei trebuie s fie o variabili deoarece operatorul de atribuire = are ca efect o dubla actiune: © produce ca rezultat al expresiei valoarea operandului din partea dreapta; © memoreaza valoarea rezultatului in spatiul de memorie asociat variabilei. operator. indicd terminarea instructiunii Variabilé “= expresie’ ; expresie de atribuire instructiune de atribuire Exemplu: int a, b, c, d; b=5; /*se atribuie variabilei b valoarea S*/ a=b+7; —_/*se evalueaza expresia b+7 si rezultatul acesteia se atribuie variabilei a*/ c=d=a; —_/*atribuire multipl&: se atribuie variabilelor d si c valoarea variabilei a*/ Observatie: in cazul atribuirii multiple, ordinea de asociere a operatorului de atribuire este de la dreapta la stanga, instructiunea fiind scrisa cu ajutorul a doud expresii de atribuire. 4.2.2 Instructiunea compusi (secventa) Aceasti instructiune permite folosirea unui grup de instrucfiuni acolo unde sintaxa limbajului impune | { instructiune_1; utilizarea uneia singure. instructiune_2; Instructiunile din grup se scriu una dupa alta si se |, stuctiuneni incadreaz intre acolade, ca in exemplul generic aliturat. 4.2.3 Instructiunea if (decizie logica) Instructiunea if permite alegerea unei variante de executie in functie de valoarea de adevar a unei expresii. Poate fi folosita in form& completa sau in varianta cu ,,o ramuri nuld”, ca in exemplele generice urmatoare. Cuvintele if si else sunt cuvinte-cheie. 40 Forma complet Sintaxa: Efectul: if (expresie) instructiune_1 ; E else instructiune_2; ns ¥ instructiune ; Observati - instructiune_I poate fi o instructiune simpla sau o instructiune compusa; - expresie poate fi orice expresie conforma cu sintaxa limbajului C dar, de cele mai multe ori, este 0 expresie relationala (de comparare a doua sau mai multe valori de acelasi tip); - yaloarea de adevar a expresiei poate fi: »fals” - dac& rezultatul evaluarii expresiei are valoarea 0 (zero); »adevarat” - daca rezultatul evaluarii expresiei are valoare diferita de zero; 4.2.3.1 Operatori relationali (de comparatie) Operatorii relationali permit compararea a doua valori de acelasi tip scalar. fn ordinea prioritatii, acestia sunt: Grup de operatori Operator Semnificatie < ~mai mic” Pentru testarea relatiei <= wmai mic sau egal” > mai mare” = wmai mare sau egal” Pentru testarea egalitafii 5 widentic” adiferit” 41 Exemplu - presupunind ca au fost declarate variabilele int i urmatoarele expresii vor fi evaluate astfel: k=1; i>k _ valoarea expresiei este 0 (,,fals”) ia>3 are, din punct de vedere Daca ins expresia anterioaré apare Pentru ca expresia si fie evaluat intr-un program C, ea va fi evaluati similar. cu cazul_matematic este de la stinga la dreapta, pe _necesara folosirea operatorului logic subexpresii, astfel: 8B: 7>a>3 (7 > a) 8& (a> 3) as SMe? 1 (adevarat) 1 (adevarat) 1 (adevarat) eee 0 (fals) 1 (adevSrat) Observatie: in cazul operatorilor logici binari, ordinea aluare a subexpresiilor este impusa prin standard: compilatoarele evalueazi mai inti expresia din stanga operatorului si apoi pe cea din dreapta, De cele mai multe ori, pentru cresterea vitezei de executie, se optimizeaza functionarea astfel: - daca prin evaluarea subexpresiei din partea stinga se obtine valoarea 0 (in cazul folosirii operatorului &&) sau 1 (in cazul folosirii operatorului I), se genereaza rezultatul cu valoarea 0, respectiv 1, fara si se mai evalueze si expresia din partea dreapta; - altfel, se evalueazi si expresia din partea dreapta si apoi se genereazi rezultatul, in functie de valoarea acesteia. 4.2.3.3 Operatori aritmetici in ordinea prioritafii, operatorii aritmetici sunt: Grup de operatori Operator Semnificatie Stabilire semn + valoare pozitiva : valoare negativa Multiplicativi * inmultire 7 imparfire % restul impirfinii a doud valori intregi ‘Adunare, scidere + adunare : scaidere Observat © Limbajul C nu are operator pentru ridicare la putere. Existd ins 0 functie specializaté, ce face parte din biblioteca matematica a compilatorului descrisi prin math.h; © Expresiile 7/3 si 5/7 vor produce intotdeauna rezultatul 2, respectiv 0 (valori intre; 4B © Operatorul % se foloseste numai impreuna cu operanzi de tip intreg. De exemplu, expresia 7%4 produce rezultatul 3 (restul impartirii intregi a lui 71a 4); © Pentru operanzi negativi, operatorul % poate genera probleme de portabilitate. 4. 4 Operatori de atribuire aritmetica Operatorul de atribuire, scris cu ajutorul simbolului =, a fost descris in cadrul sectiunii 4.2.1. Limbajul C permite si folosirea unor operatori ce combina efectul operatorului de atribuire cu efectul operatorilor aritmetici, permitand 0 scriere mai compacta a codului program. Operator Forma de utilizare Semnificatie = ab a a—=b a a*=b a arb a a%eb a Observatie: utilizarea operatorilor aritmetici trebuie facuté cu multa grija la semnificajia acestora. De exemplu: expresia a=a*b+4 nu se poate scrie in forma compacti ca a*=b+4, Ultima expresie are de fapt semnificatia: a=a*(b+4). 4. 5 Exemple de utilizare a instructiuni Exemplul_1, Program pentru calcularea valorii unei funcfii intr-un i 3x? 41-1 punct x, precizat. pentrux#0 Funcfia se expliciteaza prin: SQ)= 3 x Rezolvare: 3 pentru x=0 #include #include /*pentru folosirea functiei sqrt()*/ void main(void) { double x,f; printf("Tastati valoarea lui x:"); (°%IF", Bx); *x este de tip double*/ /*se poate scrie, echivalent: if (x) */ art (3*x*x+1)-1)/00%) .0/2.0; /*pentru c& 3/2 genereaza ca rezultat 1 (unu)*/ printf("Rezultatul: (%F)=%F\n", x, f); Observatie: $4 presupunem cA lucrdm cu o variabild de tip int k=13. Observati efectul folosirii operatorilor de atribuire, respectiv de testare a identitatii valorii, in cadral expresiilor din urmatoarele instructiuni if: * if (k=5) instructiune; + se atribuie variabilei k valoarea 5 (nu mai are, deci, valoarea 13); * expresia k=5 are ca rezultat valoarea atribuita (adica 5) si, din punct de vedere logic, aceasta inseamni ,adevarat” (valoare diferiti de zero); + se executi instructiune, deoarece expresia are valoarea ,adevarat”. * if (k==5) instructiune; + nu se modifica valoarea variabilei k; + se compara valoarea variabilei k (13) cu valoarea 5 si, deoarece diferd, rezultatul expresiei va fi 0 (zero), adica ,.fals”; + nuse executa instructiune, deoarece expresia are valoarea ,,fals”. Expresia utilizati in cadrul unei instructiuni if poate fi, in general, orice expresie conforma cu sintaxa limbajului C. fn rol de expresie poate fi utilizat si un apel de functie, cu rezultat de tip simplu, nestructurat, ca in exemplul urmitor. Exemplul 2, Sa se verifice daca un caracter introdus de la tastatura este sau nu caracter cifra. fn acest scop se va utiliza functia de biblioteca isdigit(), descris& in ctype.h, care are drept rezultat valoarea 1 atunci cand caracterul testat este caracter cifra si valoarea 0 in caz contrar, Rezolvare: #include #include _/*pentru folosirea functiel isdigit()*/ void main (void) {char car; printf(“Tastati un caracter: scanf("%c", &car); if (Isdigit(car)) printf("%c este cifra\n", car); else printf("%c nu este cifra\n", car); 3 Observati + Instructiunea if (isdigit(car))... poate fi inlocuiti cu una dintre urmatoarele forme echivalente: if (isdigit(car) != 0)... if (car >= '0' && car <= '9'), Ultima forma de scriere evita utilizarea functiei de bibliotecd, bazindu-se pe posibilitatea oferité de limbajul C de a compara valori de tip caracter cu ajutorul operatorilor relationali. La nivel intern, aceste comparatii se fac prin intermediul codului numeric asociat, deoarece in orice set de caractere cifrele si literele sunt dispuse in aceeasi ordine ca in matematica, respectiv alfabet. 45 + Citirea de la tastaturd a valorilor de tip caracter poate fi ficuti si cu ajutorul unor functii specializate: + getchar() - furnizeazd ca rezultat caracterul pe care il citeste de la tastatura; se utilizeaza in forma: car=getchar(); dupa caracterul tastat trebuie apisata tasta ENTER, la fel ca in cazul utilizrii functiei scanf(); caracterul tastat este afigat in ecou pe ecran; este descrisa in stdio.h; * getch() - furnizeazi ca rezultat caracterul pe care il citeste de la tastaturd; se utilizeaza in forma: car=getch(); ‘nu necesit apsarea tastei ENTER dupa caracterul tastat; caracterul tastat nu este afisat in ecou pe ecran; este descrisd in conio.h; nu este prezentd in toate compilatoarele; + getche() - furnizeazd ca rezultat caracterul pe care il citeste de la tastatur: se utilizeazi in forma: car=getche(); nu necesita apasarea tastei ENTER dupa caracterul tastat; caracterul tastat este afigat in ecou pe ecran; este descrisa in conio.h; nu este prezenti in toate compilatoarele; + Scrierea pe ecran a valorilor de tip caracter poate fi facut si cu ajutorul functiei specializate putchar() care poate fi utilizata in forma: © putchar(car) — afiseaz pe ecran valoarea variabilei caracter car. 4.2.3.6 Instructiuni pe mai multe niveluri Rezolvarea anumitor probleme impune luarea unor decizii de executie succesive, ceea ce se poate traduce la nivelul limbajului de programare prin utilizarea unor instructiuni if pe mai multe niveluri, adic’ instructiuni if cuprinse unele in altele (,,imbricate” sau ,,incuibate”). De exemplu, fiind date 3 valori de tip intreg, daca se doreste identificarea valorii maxime, se poate scrie urmatorul fragment de program: 46 int a, b, c, max; if (a > b) if (@ > c) max=a; else max=c; else if (b > c) max else max=c; Observatie: Regula de asociere a cuvintelor cheie if...else este: ,else corespunde if-ului imediat anterior”. Daca programatorul doreste si impund o alté asociere, trebuie si scrie explicit acest lucru, folosind acolade pentru delimitarea instructiunii / blocului de instructiuni avute in vedere, ca in exemplul urmitor: if (a>=0) {if (a<9) printf(’numéar intreg pozitiv format dintr-o singura cifr3\n"); else printf(”numér intreg negativ\n”); Observatie: Atunci cand este posibil, se preferi si se evite folosirea de instrucfiuni if pe mai multe niveluri, De exemplu, logica programului poate fi evidentiati mai clar si mai concis prin scrierea unor expresii complexe, ce combina testarea mai multor relafii. Astfel, in cazul in care, din punct de vedere matematic, ar trebui testata indeplinirea a 2 relatii, a directivi cu majuscule; #define PUNCT'.' *—preprocesor )- poate fi scris& in alt zond a programului, : - dar neapirat inainte de folosirea constantel void main (void) tn instructiuni sau expresii { int numa&r_spatii=0; char car; printf(“Tastati o frazi ce se incheie cu punct si apoi ENTER:\n car=getchar(); /* valoarea ce va fi testat& la prima trecere prin while*/ while (car != PUNCT) { /* corpul buclei este, in acest caz, 0 instructiune compusa! */ if (car ‘*) numar_spatii ++; car=getchar(); —/*modific’ valoarea expresiei testate tn while*/ printf(“n fraz& exist’ %d spatii\n", numar_spatii); 53 Observatie: in exemplul anterior, grupul de instructiuni: car=getchar(); while (car != PUNCT) { if (car == '*) num&r_spatii ++; car=getchar(); } poate fi scris mai compact astfel (parantezele fiind obligatorii): while((car=getchar()) != PUNCT) if(car == '') num&r_spatii ++; in lipsa parantezelor, deoarece operatorul != este mai prioritar decat operatorul expresia capata alta semnificatie iar programul va functiona necorespunzator: while (car = getchar() != PUNCT) ccnsnaecgeeaiasy “adevérat” (1) sau “fals” (0) Seen geen se atribuie variabilei car valoarea 1 sau 0 Exemplu: Programul urmator calculeazi suma unui numar neprecizat de valori numerice pe care le citeste de la tastaturd. Pentru a marca incheierea operatici de introducere de date, utilizatorul programului trebuie si tasteze dupa ultimul numir o litera si ENTER. #include void main(void) { double nr, sum=0.0; /*in nr se va citi de la tastatur’, pe rand, cate 0 valoare numeric&*/ int indicator, nr_val_citite=0; /*citirea unei valori numerice va determina incrementarea nr_val_citite*/ printf (“Introduceti toate valorile pe care doriti si le insumati.\n"); printf ("Dupa ultima valoare introdus’, tastati o liter& urmata de ENTER. \\ indicator=scanf ("%lf", &nr); while (indicator==1) /*se poate scrie, echivalent: while(indicator) */ {sum += nr; nr_val_citite++; indicator=scanf ("%lf", &nr); printf("S-au citit %d valori. Suma lor este:%f\n", nr_val_citite, sum); 2) Exemplul ilustreaza o particularitate folositoare a functiei standard de biblioteca scanf(), Aceasta funcfie returneaza ca rezultat un intreg ce reprezinta numarul de valori pe care reuseste si le citeascd in mod corect de la tastatura. Corectitudinea se referd la faptul ca valorile introduse de la tastatura corespund sau nu tipului de date precizat prin specificatorul de format ce apare ca prim parametru la apelarea functiei scanf(). 54 De exemplu, daca se vor introduce de la tastatura valorile 3 2.7 fg ENTER pentru fragmentul de program: int m, test; float x, yi test=scanf("%d%F%F", &m, Bx, &y); variabila test va primi prin atribuire valoarea 2 deoarece au putut fi citite corect numai dou dintre valorile precizate (cele corespunzitoare variabilelor m si x). Desi pentru variabila y se astepta o valoare de tip float, de la tastaturd au fost introduse valori de tip char, care nu corespund formatului specificat in scanf(). Dacé niciuna dintre valorile introduse de la tastaturé nu ar fi corespuns tipului precizat prin specificatorul de format, valoarea returnata de functie ar fi fost 0 (zero). Observatie: in programul de insumare a valorilor numerice prezentat ca exemplu, grupul de instructiuni: indicator=scanf ("%If", &nr); while (indicator==1) {sum += nr; nr_val_citite++; indicator=scanf ("%lf", &nr); 3 se poate scrie mai compact, renuntand la declararea gi utilizarea variabilei indicator, astfel: while (scanf ("%lf", &nr) {sum += nr; nr_val_citite++; 3 1) De retinut ¢ while(k) instructiune; este echivalent cu while(k != 0) instructiune; © nu uitafi s& scrieti intre acolade instructiunile ce formeazi corpul buclei while daca doriti executarea in mod repetat a tuturor acestora; © atentie la greseli de tipul: in aceast& situatie, printf() nu este int k=1; instructiunea ce se execut in while. Se va ile (k++ <3) | 3 executa abia dupa terminarea instructiunii eke " ) “|* while, care repet& doar o instructiune printf("k=%d\n", k); vid’, exprimatd prin caracterul ; © instructiunea vida poate fi utila, atunci cand este folosita in cunostina de cauzi. De exemplu, daca intr-un program se doreste gasirea primului caracter ,spafiu” prin citirea unui text ,caracter cu caracter”, se poate serie: 35

You might also like