introducere in ansi c++ (v2)

Upload: nistor-roxana

Post on 15-Oct-2015

873 views

Category:

Documents


56 download

DESCRIPTION

C++

TRANSCRIPT

  • Introducere in ANSI C++

    IntroducereInitial, aceasta lucrare a fost conceputa avand ca instrument de lucru mediul de

    programare Borland C++ 3.1, varianta de DOS. Aparitia standardelor ANSI pentru C si C++ si in primul rand introducerea suportului pentru acest standard in majoritatea compilatoarelor (gcc, g++, bcc32 etc.), a dus la faptul ca unele dintre sursele existente sa nu mai fie viabile.

    Capitolele au fost modificate in asa fel incat un utilizator familiarizat cu mediul BC++ 3.1 sa poate face intr-un mod accesibil trecerea de la acest mediu spre variantele free oferite pe piata cu suport ANSI C++.

    Lucrarea a fost editata in intregime sub programul OpenOffice Writer, oferit in (probabil) toate distributiile gratuite de Linux. In acest caz, sistemul pe care s-a lucrat este SUSE 9.3.

    Am folosit pentru editarea programelor sursa utilitarul Kate, avand optiunile de editare specifice C++ activate, pentru compilare compilatorul g++, iar pentru depanare Kdbg, o interfata pentru gdb, depanatorul GNU.

    Urmatoarele volume vor contine:

    Prezentarea bilbiotecii standard ANSI C++

    Programare orientate obiect in ANSI C++

    STD (Standard Template Library)

    - 1 -

  • Introducere in ANSI C++

    Capitolul 1 Primul program

    1.1 Structura generala a unui program C++In general, structura surselor C++ ce apar in lucrare este urmatoarea:

    Sursele C++ reprezinta fisiere text care contin codul pe care dorim sa il rulam pe calculator. Scrierea acestora se poate face in orice editor de text care permite salvarea intr-un format text curat, fara detalii de formatare cum ar fi cele introduse de catre un procesor de text (MS Word, OpenOffice Write etc.). Textul sursa va fi salvat sub un nume sugestiv si cu extensia cpp.

    Pentru a putea fi rulat, textul sursa trebuie sa fie tradus intr-o forma executabila de catre calculator. Fara a intra in amanunte, sursa trebuie compilata, apoi link-editata, obtinand un program executabil. In Figura 1.1 dam o schema simplificata a acestui proces.

    - 2 -

    // Comentariu (enuntul problemei)

    # directive_preprocesor

    prototipuri_functii;declaratii_variabile globale;

    int main(){declaratii_variabile_locale;instructiuni;

    }

    definire_functii

  • Introducere in ANSI C++

    Figura 1.1 Trecerea de la textul sursa la fisierul executabil

    1.2 Hi man!Ca prim program vom implementa urmatoarea problema:

    P1. Realizati un program C++ care afiseaza mesajul Hi man! pe ecran.Vom rezolva problama in trei variante, una specifica C, a doua folosind mediul

    Borland C++ 3.1 si a treia varianta respectand standardul ANSI C++.

    Limbajele C si C++ nu dispun de catre instructiuni de intrare/iesire. Pentru a putea citi valori de la tastatura sau pentru afisa pe ecran vom folosi biblioteci care imbogatesc limbajul cu diferite functii utile. In acest caz, linia 1 include biblioteca standard stdio.h (standard input/output).

    Orice program C++ contine o functie numita main, functie cu care incepe executia programului. Linia 2 contine antetul acestei functii. Sfarsitul liniei 2 contine '{', care reprezinta inceputul unui bloc, terminat in linia 4.

    Intre acolade sunt scrise instructiunile programului, in acest caz linia 3, linie pe care apelam functia printf, functie care realizeaza afisarea mesajului dorit pe ecran.

    - 3 -

    Linkeditare

    nume.cpp nume.exe

    // P1_1. Realizati un program C++ care afiseaza mesajul Hi man! pe ecran.

    #include // linia 1

    int main(){ // linia 2printf("Hi man!"); // linia 3

    } // linia 4

    Compilare

  • Introducere in ANSI C++

    In varianta urmatoare vom folosi biblioteca iostream, introdusa in C++ si care implementeaza asa numitele fluxuri de intrare/iesire.

    Diferentele fata de primul exemplu le constatam in linia 1, unde am inclus o alta biblioteca ce ne ofera acees la operatiile de intrare iesire, respectiv in linia 3, unde, pentru afisare folosim o altfel de constructie.

    Cei obisnuiti cu compilatoarele mai vechi, cum ar fi bcc.exe, compilatoriul care vine cu mediul Borland C++ 3.1, vor ramane surprinsi ca sursa de mai sus nu functioneaza (iar daca main ar fi returnat void, am fi avut doua erori!).

    Varianta care respecta standardul ANSI C++ este urmatoarea:

    Observam lipsa extensiei .h din linia 1, respectiv specificarea spatiului de nume std in linia 3.

    1.3 Compilarea si rularea programului

    1.3.1 In mediul Borland C++ 3.1In cazul in care avem pornit mediul, putem rula programul prin apasarea

    combinatiei Ctrl+F9. Mediul va a apela automat compilatorul, apoi linkeditorul, va genera fisierul executabil, apoi il va rula. Pentru vizualizarea efectiva a rezultatului, apasam Alt+F5 pentru vizualizarea iesirii.

    - 4 -

    #include // linia 1

    int main(){ // linia 2 cout

  • Introducere in ANSI C++

    In cazul in care am editat sursa intr-un alt editor, de exemplu notepad, pentru a rula aplicatia dorita vom realiza manual trecerea spre fisierul executabil, in felul urmator:

    pas 1. Copiem sursa in directorul c:/borlandc/bin (pas facultativ, dar in acest mod simplificam explicatiile)

    pas 2. .. > bcc p01.cpp (in cazul in care sursa a fost corecta, obtinem la acest pas fisierul p01.obj)

    pas 3. .. > tlink p01.obj (obtinem p01.exe)pas 4. .. > p01.exe (este rulat programul)

    1.3.2 Folosind compilatorul g++Rulam comanda g++ p01.cpp, din directorul in care avem textul sursa, si

    obtinem fisierul executabil a.out, care poate fi lansat in executie prin comanda ./a.out .

    Daca dorim specificarea unui alt nume de fisier executibail, comanda de compilare va contine optiunea -o. De exemplu g++ -o Hi_Man p01.cpp va genera executabilul Hi_Man, iar rularea se va face prin ./Hi_Man .

    - 5 -

  • Introducere in ANSI C++

    Capitolul 2 Notiuni de baza

    2.1 Notiunea de algoritmNumim algoritm o succesiune de pasi care rezolva o clasa de probleme. Vorbim

    de clase de probleme in urmatorul sens: daca 2x+3=0, respectiv x-4=0 reprezinta probleme, ax+b=0 va reprezenta clasa de probleme ce formeaza ecuatia de gradul I.

    Un algoritm este caracterizat prin sintagma noi muncim, nu gandim!, in sensul ca executia pasilor algoritmului are loc fara nici un efort creator.

    In general, in cadrul unui algoritm avem trei sectiuni distincte: date e intrare, rezolvarea efectiva a problemei si date de iesire, conform Figurii 2.1.

    Figura 2.1 Forma generala a unui algoritm

    Pentru a evidentia pasii de urmat vom lua ca exemplu urmatoarea problema.

    P1. Realizati un algoritm care calculeaza suma a doua valori.

    Inainte de a incepe rezolvarea problemei trebuie sa ne fie clar care sunt datele initiale de la care se pleca, respectiv ce anume se cere. In acest caz, datele de intrare sunt reprezentate de catre a si b, iar data de iesire va fi S, care respecta datele problemei (adica S=a+b).

    - 6 -

    Date de intrare Date de iesireRezolvarea problemei

  • Introducere in ANSI C++

    Algortimul este:

    Datedeintrare(a,b)

    citesteasib

    Rezolvareaproblemei

    S=a+b

    Datedeiesire(S)

    afiseazaS

    Intelegerea clara a enuntului unei probleme este vitala in rezolvarea acesteia. Daca nu sunt clare care sunt datele de intrare, respectiv cele de iesire ale unui algoritm, cel mai probabil rezolvarea nu va fi corecta, sau vom rezolva o alta problema decat cea ceruta.

    2.2 Citirea si afisarea datelorIn subcapitolul anterior am citit datele de intrare ale algoritmului, respectiv am

    afisat rezultatul. In cazul descrierii algoritmului in cuvinte, acest lucru a fost realizat prin simpla enuntare a operatiei de executat (scrieS). In cazul in care dorim implementarea algoritmului intr-un limbaj de programare, in cazul nostru C++, trebuiesc respectate o serie de reguli clare, deoarece compilatorul trebuie sa inteleaga ceea ce dorim sa facem.

    Limbajul C++ nu ofera instructiuni de intrare/iesire. In schimb avem la dispozitie biblioteca de functii standard, prin care, putem realiza aceste operatii. Compilatoarele C++ actuale vin cu bilbioteca standard.

    Am ales, pentru simplitatea in utilizare, functii1 din cadrul bibliotecii iostream.

    Pentru afisare vom folosi constructii de forma:

    cout

  • Introducere in ANSI C++

    P2. Afisati textul "text de test!" pe ecran.

    Linia a doua din sursa va face ca folosirea specificarii spatiului de nume std(std::cout) sa nu fie obligatorie.

    In cazul in care folositi mediul Borland C++ 3.1 inlocuiti

    cu

    in rest programul ramand nechimbat.

    Pentru citire vom folosi constructii de forma:

    cin>>in_ce_citim; sau:

    cin>>v1>>v1>>...>>vn;

    Exemple de citire vom da mai tarziu, dupa introducerea notiunii de variabila.

    - 8 -

    #include using namespace std;

    #include

    // P2_1. Afisarea textului 'text de test!' pe ecran.

    #include using namespace std;

    int main(){ cout

  • Introducere in ANSI C++

    2.3 Tipuri de date. Variabile si constante.Algorimii lucreaza cu date. In exemplul cu suma, datele de lucru au fost a,b si S.

    Datele cu care lucreaza algoritmii au ca si corespondent in C++ constantele si variabilele. Fiecare constanta sau variabila din C++ are asociata un tip.

    Tipurile fundamentale ale C++ sunt prezentate in Tabelul 2.1:

    Tip Constante Observatii

    void - - indica absenta informatiei

    char

    'A''B''a'

    '+'

    '3'

    - defineste un caracter- in memoria calculatorului, stocarea unui caracter se face folosind codul lui ASCII- poate fi folosit si pentru a memora numere intregi mici

    int3

    123-1020

    - numar intreg cu semn- intervalul acoperit de acest tip poate diferi de la un calculator la altul

    float3.0

    123.456- 100.001

    - folosit pentru memorarea numerelor reale- este memorat in format cu virgula mobila (float) in simpla precizie

    double3.0

    123.456- 100.001

    - numere reale- il folosim pentru numere foarte mari sau pentru o precizie mai mare dupa virgula

    bool 1 0true false

    - tip care apare in ANSI C++- nu este recunoscut in Borland C++ 3.1

    Tabelul 2.1 Tipurile de baza in C++

    - 9 -

  • Introducere in ANSI C++

    Pe langa aceste tipuri de baza, C++ ofera asa numitii modificatori de tip, folositi pentru a scimba domeniul valorilor pe are le poate pastra o variabila, prezentati in Tabelul 2.2:

    Modificator Efectsigned - forteaza existenta semnului

    unsigned - daca dorim doar memorarea a valori pozitive intr-o variabila- prin disparitia semnului, este dublat numarul de valori pozitive de memorat

    short - reduce intervalul de reprezentare

    long - mareste intervalul de reprezentare

    Tabelul 2.2 Modificatorii de tip

    Tipurile de date sunt folosite pentru a defini variabilele cu care dorim sa lucram in program.

    Pe langa constantele prezentate in Tabelul 2.1, vom folosi si constante de tip sir de caractere, reprezentand succesiuni de caractere cuprinse intre ghilimele. Exemplu de siruri de caractere pot fi: ABC, Sunt un sir de caractere!, 1+2=3.

    Prin variabila intelegem o entitate capabila sa-si modifice valoarea. In C++, inainte de a folosi o variabila, aceasta trebuie declarata. Forma generala a unei declaratii este:

    tipnume; sau:

    tipv1,v2,...,vn;

    In momentul declaratiei, C++ permite initializarea variabilei, declaratia devenind:

    tipnume=valoare;

    Folosirea cuvantului cheie const inainte de declaratia unei variabile va spune compilatorului ca valoarea acesteia nu poate fi modificata in cadrul programului.

    - 10 -

  • Introducere in ANSI C++

    consttipnume=valoare;

    Pentru exemplificare fie urmatoarea problema:

    P3. Definiti cel putin 5 variabile de tipuri diferite, initializati-le si apoi afisati valoarile pe ecran.

    In urma executiei sa va afisa pe ecran:Suntcaracterul:A

    Suntintregul:123

    Suntintregulmare:12356789

    Suntintregulfarasemn:98

    Suntintregulmarefarasemn:12345678

    Suntnumarulreal:3.14

    Numarreal(da'maimare,dacavreau):21.344

    Pentru cosmetizarea afisarii am folosit cout

  • Introducere in ANSI C++

    in memoria calculatorului.

    P4. Verificati cat ocupa in memoria calculatorului dumneavoastra diverse tipuri de date.

    Programul va afisa:Uncaracterocupa1octet

    Unintregocupa4octeti

    Tipulfloatocupa4octeti

    Tipuldoubleocupa8octeti

    Rezultatele pot sa difere de la calculator la calculator.

    In acest moment avem toate datele pentru a implementa algoritmul cerut in problema 1 (cea de la inceputul capitolului). O posibila implementare este:

    - 12 -

    #include using namespace std;

    int main(){int i=123;

    cout

  • Introducere in ANSI C++

    La rularea aplicatiei avem impresia ca ea s-a blocat, avand in fata doar un cursor care clipeste. Motivul este cel ca, dupa declaratii, se executa instructiunea cin>>a;iar programul se opreste din executie in asteptarea unei valori introduse de la tastatura. Acest lucru se realizeaza prin scrierea unei valori urmata de apasarea tastei Enter. In acest moment variabila a preia valoarea introdusa, apoi se trece la urmatoarea instructiune. Tratand analog si cea de a doua citire, obtinem in final afisarea sumei valorilor introduse.

    O posibila rulare a aplicatiei va arata de forma:3

    5

    8

    Observam ca varianta prezentata nu arata deloc bine, o cosmetizare fiind bine venita:

    P5. Calculati valoare expresiei 2*(a-b)+c, realizand o interfata prietenoasa cu utilizatorul.

    In acest moment, executia va afisa ceva de forma:a=3

    b=5

    c=2

    E=2*(35)+2=2

    - 13 -

    #include using namespace std;

    int main(){int a,b,c,E; // declararea variabilelor

    cout a; // citim prima variabila

    cout >b; // analog pentru celelalte cout >c; // date de intrare

    E=2*(a-b)+c; // calcularea expresiei

    cout

  • Introducere in ANSI C++

    2.4 Secvente escapeSecventele escape sunt succesiuni de caractere care incep cu caracterul '\',

    fiecare secventa fiind interpretata ca un singur caracter special. Secventele escape sunt folosite pentru a introduce entitati imposibil de afisat in alt mod, cum ar fi trecerea la rand nou sau tab-ul.

    Tabelul 2.3 da o serie de secvente escape uzuale.

    Secventa escape Efect\n

    - trecere la rand nou- echivalent cu endl

    \t- tab orizontal

    \'- un caracter '(apostrof)

    \\- un caracter \(backslash)

    \- un caracter (ghilimea)

    \b- backspace

    \a- sunet de alerta

    \nnn- nnn reprezinta un cod ASCII in baza 8

    Tabelul 2.3 Secvente escape

    Secventele escape pot aparea sub forma de caractere de sine statatoare, de forma '\n' sau '\\', sau in cadrul unor siruri de caractere, cum ar fi abc\n\abc\.

    Urmatoarele doua surse rezolva aceeasi problema:

    - 14 -

  • Introducere in ANSI C++

    P6. Afisati un romb din caracterul '$' pe ecran.

    $

    $$$

    $$$$$

    $$$

    $

    $

    $$$

    $$$$$

    $$$

    $

    - 15 -

    #include using namespace std;

    int main(){ cout

  • Introducere in ANSI C++

    2.5 Referinte (alias-uri)C/C++ permite definirea unor alias-uri ale variabilelor. Forma generala este:tipa;

    tip&porecla=a;

    Din momentul definirii unei referinte, variabila initiala va putea fi accesata atat cu numele ei cat si cu alias-ul. Folosirea referintelor reluata in Capitolul 8, referitor la functii.

    P7. Exemplu de lucru cu referinte.

    Suntvariabilaa:123

    Sunttotvariabilaa:123

    Sunta,simisespune:123

    - 16 -

    #include using namespace std;

    int main(){ int a=123; // variabila intreaga a int &copie_a=a; // un alt nume pentru a int &porecla=a; // tot a

    cout

  • Introducere in ANSI C++

    2.6 Probleme propuse

    Pp1. Afisati pe ecran un bradulet folosind caracterul '*'.

    Pp2. Cititi de la tastatura trei numere intregi, apoi afisati-le in ordine inversa, cate unul pe un rand.

    Pp3. Calculati media aritmetica a doua valori intregi citite de la tastatura. Citirea si afisarea sa fie prietenoasa cu utilizatorul.

    Pp4. Calculati si afisati, in acelasi program si intr-o varianta prietenoasa cu utilizatorul, urmatoarele expresii:

    M(a,b,c)=(a+b+c)/3

    F(a,b)=(a+3)/2+b

    E(a,b,c,d)=(a+b)/2+(dc)/3

    Pp5. Folositi secvente escape pentru a afisa pe ecran:Manumescghilimeasinuaratasa'.

    Eu,adica\,suntunbackslash.

    Acumvoifacebeepde3ori,dupaceam'sarit'untab.

    - 17 -

  • Introducere in ANSI C++

    Capitolul 3 Expresii C++Numim expresie valida in C++ orice succesiune corecta de variabile, constante,

    operatori si apeluri de functii evaluabila la o valoare unica.

    3.1 Atribuirea Forma generala a operatiei de atribuire este:variabila=expresie;

    Modul in care limbajul realizeaza atribuirea este urmatorul:Pas 1. Este evaluata valoarea expresiei din dreapta (daca variabila din stanga

    apare in cadrul expresiei, va fi folosita valoarea curenta)Pas 2. Valoarea calculata este atribuita variabilei din stanga

    P1. Exemple de atribuiri simple

    La rulare vom avea:i=3

    c=C

    f=3.14

    Interesant este faptul ca in C/C++, spre deosebire de alte limbaje, atribuirea este o expresie, deci pe locul in care folosim atribuirea apare o valoare. Valoarea

    - 18 -

    #include using namespace std;

    int main(){ int i; char c; float f; i=3; // intregul i ia valoarea 3 c='A'+2; // caracterul c ia valoarea 'C' (65) f=2+1.14; // realul f ia valoarea 3.14 cout

  • Introducere in ANSI C++

    returnata de catre oparatia de atribuire este valoarea expresiei din dreapta. Deci, daca avem atribuirea a=3, pe locul atribuirii apare valoarea 3. Putem folosi acest fapt pentru a realiza atribuiri multiple, de forma urmatoare:

    variabila1=variabila2=...=variabilan=expresie;

    P2. Alte exemple de atribuiri

    Se va afisa:Rezultatulatribuiriii=3este:3

    i=8

    a=10

    b=10

    Pentru expresia a=b=i+2 avem urmatoarea ordine a operatiilor:

    Pas 1. Initial avem a=expresie, unde expresie este b=i+2.

    Pas 2. Se evalueaza expresie:

    - variabila b ia valoarea i+2 (10 in exemplul nostru)- expresie returneaza valoarea 10

    Pas 3. variabila a ia valoarea 10

    - 19 -

    #include using namespace std;

    int main(){ int i; int a,b; cout

  • Introducere in ANSI C++

    3.2 Conversii de tipEste posibil ca tipul expresiei sa nu fie identic cu tipul variabilei unde memoram

    rezultatul, caz in care este realizata o conversie implicita de tip si, in unele cazuri, vom avea un avertisment la compilare. In general, conversia de tip este realizata fara probleme daca variabila si expresia sunt ambele de tip intreg (int, char, long etc.) sau de tip real (float, double etc.), iar variabila este reprezentata pe un numar egal sau mai mare de octeti decat rezultatul expresiei.

    In urmatoare doua exemple vom evidentia cele doua cazuri de conversie implicita.

    P3. Conversie implicita de tip, fara pierdere de informatie

    i=65

    c=A

    f=12345

    - 20 -

    #include using namespace std;

    int main(){ int i=12345; char c='A'; float f=97.14; f=i; i=c; cout

  • Introducere in ANSI C++

    P4. Conversie implicita de tip, cu pierdere de informatie

    La compilare, avem:p04.cpp:Infunction`intmain()':

    p04.cpp:11:warning:convertingto`int'from`float'

    La rulare:i=97

    c=9

    f=97.14

    Observatie: c contine caracterul '9', nu valoarea intreaga 9.

    C si C++ permit conversii explicite de tip, de forma:

    (tip)expresie sau:

    tip(expresie)

    - 21 -

    #include using namespace std;

    int main(){ int i=12345; char c='A'; float f=97.14; c=i; i=f; cout

  • Introducere in ANSI C++

    P5. Conversia explicita de tip

    i=12348

    c=a

    f=97

    O aplicatie directa a conversiei explicite de tip este:

    P6. Se citeste un caracter. Afisati codul ASCII corespunzator caracterului citit

    Doua posibile rulari ale aplicatiei:Daticaracterul:a

    Caracterul'a'arecodulASCII97

    Daticaracterul:9

    Caracterul'9'arecodulASCII57

    - 22 -

    #include using namespace std;

    int main(){ int i=12345; float f=97.14; cout

  • Introducere in ANSI C++

    3.3 Expresii aritmeticeForma generala este, in functie de operator:

    operatoroperand sau

    operand1operatoroperand2

    Operatorii uzuali folositi in cadrul expresiilor aritmetice si care se comporta asa cum ne asteptam sunt '+','','*'.

    Operatorul '/' (impartirea) reactioneaza in mod diferit in functie de tipul operanzilor. Astfel, daca cel putin unul dintre operanzi este de tip real, rezultatul este real. Daca ambii operanzi sunt intregi, este realizata impartirea intreaga. In acest ultim caz are sens sa vorbim despre restul impartirii, dat de operandul '%'(modulo). Operatorul modulo nu poate fi aplicat tipurilor reale.

    Urmatoare problema da exemple de folosire a impartirii:

    P7. Expresii aritmetice. Impartirea reala si intreaga.

    123

    123/246=0

    123/246=0.5

    In cazul in care dorim ca raportul a doua expresii de tip intreg sa dea o valoare reala vom folosi conversia explicita de tip, de forma:

    float(operator_intreg1)/(operator_intreg2)

    In acest context, 7/2 are valoarea 3, dar 7./2 sau float(7)/2 au valoarea 3.5.

    - 23 -

    #include using namespace std;

    int main(){ int i=123,a; float f; cout

  • Introducere in ANSI C++

    Exista o serie de operatori de atribuire speciali (forma scurta a atribuirii), operatori ce vor avea forma generala:

    variabilaop=expresie

    unde op poate fi orice operator aritmetic prezentat anterior.

    Atribuirea este echivalenta cu:variabila=variabilaopexpresie

    P8. Forma scurta a atribuirii

    12510020020

    Alti operatori, specifici C si C++, sunt cei de incrementare si decrementare:variabila++

    ++variabila

    variabila

    variabila

    Operatorul ++ realizeaza incrementarea variabilei pe care este aplicat, adica este similar atribuirii variabila=variabila+1, in timp ce realizeaza decrementarea, adica variabila=variabila1.

    Diferenta intre cele doua forme (sufix sau prefix), consta in faptul ca, in cazul sufix, valoarea variabilei este folosita neschimbata in expresia din care face parte, apoi aceasta este incrementata, in timp ce in cazul prefix, valoarea variabilei este incrementata, apoi este folosita in expresia din care face parte.

    - 24 -

    #include using namespace std;

    int main(){ int i=123; i+=2; cout

  • Introducere in ANSI C++

    P9. Incrementarea si decrementarea

    126125125

    3.4 Expresii logiceSunt acele expresii in care rezultatul este interpretat ca adevarat sau fals.

    Daca in ANSI C++ avem definit un tip specific (bool), compilatoarele mai vechi (bcc) nu suporta acest tip. In orice caz, regula care se respecta este faptul ca valoarea 0 inseamna fals din punct de vedere logic, iar orice valoare diferita de 0 (de obicei valoarea 1) este interpretata ca adevarat, asa cum arata si exemplul urmator.

    P10. Valoarea expresiilor logice

    true=1

    false=0

    - 25 -

    #include using namespace std;

    int main(){ int i=123,a,b; i++; // daca nu apare intr-o expresie este similar cu ++i; a=++i;// incrementam i, apoi il atribuim lui a b=i++;// atribuim lui a valoarea lui i, apoi incrementam i cout

  • Introducere in ANSI C++

    Un caz particular de expresii logice il reprezinta expresiile relationale, expresii in care sunt comparate doua valori. Operatorii relationali sunt dati in tabelul urmator:

    Operator Semnificatie Exemplu< mai mic 3 mai mare (4+1)>(2*2)

    =3

    != diferit 2!=3

    == egal 3==3

    Tabelul 3.1 Operatorii relationali

    Observam ca testarea egalitatii a doua expresii nu se face folosind '=', operator reprezentand atribuirea.

    Diferite expresii logice pot fi reunite folosind operatorii logici din Tabelul 3.2.

    Operator Semnificatie Exemplu&& si logic (x>=2)&&(x=2), adica x

  • Introducere in ANSI C++

    P11. Se citesc trei valori intregi de la tastatura. Verificati unde se gaseste prima valoare citita in raport cu intervalul determinat de ultimele doua valori.

    Datiintervalul[a,b]

    a=2

    b=5

    apartineintervalului:1

    nuapartineintervalului:0

    Observam ca valoarea de adevar a afirmatiilor este data sub forma 0-fals si 1-adevarat.

    3.5 Operatorul conditionalAre forma generala:expresie1?expresie2:expresie3

    Daca expresie1 este evaluata la adevarat, expresia returneaza expresie2, altfel returneaza expresie3.

    In unele cazuri particulare poate fi un inlocuitor pentru instructiunea if.

    - 27 -

    #include using namespace std;

    int main(){ int i,a,b; cout >i; cout > a; cout > b; cout

  • Introducere in ANSI C++

    P12. Calculati expresia E(x)=1/x daca e posibil, afisand valoarea 0 in caz contrar.

    x=2

    1/2=0.5

    P13. Calculati expresia max(a,b), unde a si b sunt valori reale citite de la tastatura.

    a=5

    b=2

    max(5,2)=5

    P14. Se citesc doua valori intregi de la tastatura. Interschimbati cele doua valori, apoi afisati rezultatul pe ecran.

    - 28 -

    #include using namespace std;

    int main(){ int x; float E; cout >x; E = (x!=0) ? 1./x : 0; cout

  • Introducere in ANSI C++

    a=2

    b=5

    dupainterschimbare

    a=5b=2

    Ordinea de efectuare a operatiilor in cazul unei expresii complexe este data de prioritatea operatorilor, respectiv de folosirea parantezelor. Tabele cu prioritatea operatorilor gasiti in [1],[5] etc. De cate ori nu stiti exact ordinea in care se vor executa diferite operatii intr-o expresie, folositi parantezele.

    P15. Necesitatea folosirii parantezelor. Acest program NU va verifica apartenenta valorii a intervalului [1,5], desi in unele cazuri pare sa functioneze !!!

    a=8

    8apartineintervalului[2,5]:1

    - 29 -

    #include using namespace std;

    int main(){ int a,rez; cout > a; rez=(2

  • Introducere in ANSI C++

    Observam ca la conditia care pare "8 apartine lui [2,5]" rezultatul este adevarat (1). Motivul este urmatorul:

    Expresia 2

  • Introducere in ANSI C++

    3.7 Operatori care actioneaza la nivel de bitTabelul 3.3 da operatorii pe biti acceptati in C/C++:

    Operator Semnificatie Exemplu

    & si pe biti x&1 reseteaza toti bitii, in afara celui mai putin semnificativ

    | sau pe biti x|1 seteaza bitul cel mai putin semnificativ

    ^ sau exclusivx^0 complementeaza toti bitiix^xvaloare nula pentru orice x

    ~ negatie pe biti ~xcomplementeaza toti bitii

    >> deplasare la dreapta x

  • Introducere in ANSI C++

    3.8 Probleme propusePp1. Se citeste un numar real x, strict pozitiv, de la tastatura. Calculati si afisati

    rezultatul expresiei (x-1)/x2 .Pp2. Se citeste un numar real de la tastatura. Folosind conversii de tip, afisati

    partea fractionara a numarului.

    Pp3. Se citesc doua numere a si b de la tastatura, valori intregi strict pozitive. Afisati rezultatul expresiei E(a,b)=(a-b)/(a+b).

    Pp4. Folosind operatorul conditional, determinati minimul a doua valori intregi citite de la tastatura.

    Pp5. Se citeste un numar real x de la tastatura. Folosind operatorul conditional, calculati si afisati rezultatul expresiei E(a)=max(min(a,7),|a-7|).

    Pp6. Se citesc trei numere intregi de la tastatura. Afisati valoarea "din mijloc", adica valoarea care nu este nici minimul, nici maximul celor trei valori date.

    Pp7. Se citesc trei numere intregi de la tastatura. Afisati pe ecran suma celor mai mici doua valori.

    - 32 -

  • Introducere in ANSI C++

    Capitolul 4 Instructiuni conditionaleDaca dorim executia unor instructiuni doar daca o conditie este adevarata sau

    daca dorim ramificarea executiei programului, folosim instructiuni conditionale.

    4.1 Instructiunea ifExista doua forme ale instructiunii if:

    if(expresie)instructiune

    In acest caz, daca expresie este evaluata la adevarat (o valoare nenula), atunci se executa instructiunea care urmeaza.

    if(expresie)instructiune1

    elseinstructiune2

    Daca expresie este evaluata la adevarat se executa instructiune1, altfel se executa instructiune2.

    De obicei expresia dintre paranteze este o expresie logica, dar, datorita conventiilor C referitoare la notiunile de adevarat si fals, expresia poate fi de orice tip, inclusiv expresii aritmetice sau atribuiri. In urmatoarele exemple vom arata diverse moduri de a realiza comparatii in C.

    P1. Se citeste un numar intreg de la tastaura. Verificati daca acesta este nul, pozitiv sau negativ.

    a=123

    123estepozitiv.

    - 33 -

    #include using namespace std;

    int main(){ int a; cout > a; if (a==0) cout

  • Introducere in ANSI C++

    sau:

    a=0

    0estenul.

    P2. Se citeste un numar intreg de la tastaura. Verificati daca acesta este nul sau nu.

    a=123

    123estenenul.

    Sa vedem putin ce se intampla in acest caz. Conditia "ciudata" dinif, va fi evaluata in felul urmator:

    - daca a este diferit de zero, atunci, conform conventiilor C, reprezinta true, deci se va executa prima ramura a if-ului

    - daca a este nul, adica corespunde valorii false, se executa cea de a doua ramura.

    In general, verificarea unei expresii daca este adevarata sau falsa, se realizeaza prin simpla scriere a expresiei intre parantezele if-ului, de forma:

    if(expresie)

    Nu este nevoie sa scriem varianta echivalenta:

    if(expresie!=0) sau

    if(expresie!=false)

    - 34 -

    #include using namespace std;

    int main(){ int a; cout > a; if (a) cout

  • Introducere in ANSI C++

    P3. Se citesc de la tastaura doua numere intregi si un caracter reprezentand operatiile matematice '+', '-'. Afisati valoarea corespunzatoare aplicarii operatiei date asupra intregilor cititi.

    a=2

    b=3

    operatia:+

    2+3=5

    In problema 3, observam ca instructiunea de pe ramura fals a primului if este o alta instructiune if. Vom denumi acest caz ca imbricarea instructiunii if si vom folosi alinierea else cu if-ul corespunzator pentru a imbunatatii lizibilitatea programului.

    Daca dorim executia a mai multe instructiuni pe o ramura a instructiunii if, vom grupa aceste instructiuni intr-un bloc (instructiune compusa). Vom numi bloc zona cuprinsa intre acolade ({...}). In cazul scrierii instructiunilor intr-un bloc, acestea vor fi tratate in mod unitar, ca o singura instructiune. In legatura cu sugestii privind indentarea codului studiati Anexa 3.

    - 35 -

    #include using namespace std;

    int main(){ int a,b; char op; cout > a; cout > b; cout > op; if (op=='+') cout

  • Introducere in ANSI C++

    P4. Se citesc de la tastaura trei numere intregi. Calculati maximul si minimul valorilor.

    a=2

    b=3

    c=1

    min(2,3,1)=1

    max(2,3,1)=3

    Datorita faptului ca putem avea mai multe nivele de imbricare a instructiunilor if, unele avand else si altele nu, trebuie acordata o atentie deosebita corespondentei ifelse dorite. Fiecare else va fi in corespondenta cu primul ifcare se gaseste inaintea lui in textul sursa cu proprietatea ca nu ii corespunde nici un else si nu este inclus in instructiunea ifcare il precede.

    Mai mult, o aliniere corecta nu va tine locul de bloc.

    - 36 -

    #include using namespace std;

    int main(){ int a,b,c; int max,min; cout > a; cout > b; cout > c;// calculam minimul si maximul primelor doua valori if (a>b){ min=b; max=a; } else{ min=a; max=b; }// "ajustam" minimul si maximul in functie de a treia valoare if (c>max) max=c; if (c

  • Introducere in ANSI C++

    P5. Exemple de erori de compilare la surse care par corecte.

    p05.cpp:Infunction`intmain()':

    p05.cpp:12:error:syntaxerrorbefore`else'

    Desi, datorita imbricarii, pare ca pe ramura true vor fi executate cele doua instructiuni, compilatorul va interpreta if-ul ca fiind fara else (pe ramura true se executa o singura instructiune), deci nu va gasi corespondet pentru else. Linia [2] din cod ar trebui aliniata cu instruciunea if, afisarea fiind executata in afara acestuia.

    P6. Varianta corecta a problemei 5.

    a=2

    Emaimiccatrei

    Numaidaeroare;)

    Acum liniile [1] si [2] sunt grupate intr-un bloc, deci pe ramura true se executa o singura instructiune, iar else isi gaseste corespondent.

    - 37 -

    #include using namespace std;

    int main(){ int a; cout > a; if (a

  • Introducere in ANSI C++

    In multe probleme, folosirea expresiilor logice compuse reprezinta o alegere evidenta.

    P7. Determinati daca patru numere intregi citite de la tastatura sunt in ordine crescatoare sau nu.

    Introducetipatrunumereintregi:

    2458

    Numerelecititesuntinordinecrescatoare

    Putem folosi o variabila booleana pentru a memora rezultatul unor exepresii logice complexe, apoi sa folosim acea variabila ca o conditie in cadrul instructiunii if. Acelasi efect il putem obtine folosind o variabila de tip intreg in locul celei booleene.

    P8. Determinati daca patru numere intregi formeaza o progresie aritmetica. Daca da, afisati ratia.

    - 38 -

    #include using namespace std;

    int main(){ int a,b,c,d; cout > a >> b >> c >> d; if ((a

  • Introducere in ANSI C++

    Introducetipatrunumereintregi:

    2468

    Numerelecititesuntinprogresie

    aritmetica,curatia:2

    Un caz uzual in care apare folosirea conditiei multiple este verificarea apartenentei unui numar unui interval dat.

    P9. Calculati urmatoarea functie:

    f x =x pentru x[10,20 ]

    x pentru x20,00 inrest

    - 39 -

    #include using namespace std;

    int main(){int a,b,c,d;bool progresie;cout > a >> b >> c >> d;

    progresie = (2*b==a+c); // verificam daca primele trei formeaza o progresie

    progresie = progresie && (2*c==b+d); // acum urmatoarele...

    if (progresie){cout

  • Introducere in ANSI C++

    x=3

    f(3)=0

    Nu este recomandata verificarea egalitatii intre doua numere reale. Datorita erorilor de calcul, este posibil ca rezultatele calculelor sa nu fie exacte. In acest caz se recomanda folosirea unor conditii de forma abs(ab) x;

    if ((x>=10)&&(x-20)&&(x

  • Introducere in ANSI C++

    - se evalueaza expresie, apoi se compara, pe rand cu fiecare constanta

    - daca este realizata egalitatea, se executa setul de instructiuni ce urmeaza

    - daca dupa executarea unei secvente dorim iesirea din switch, se foloseste instructiunea break

    Cum de obicei se intampla acest lucru, forma generala devine:

    switch(expresie){

    caseconstanta1: instructiuni;break;

    caseconstanta2: instructiuni;break;

    ...

    caseconstantan: instructiuni;

    default:instructiune;

    }

    P10. Se citesc de la tastatura doua numere intregi si un caracter. Daca acest caracter este +, -, * sau /, realizati operatia respectiva intre intregiii de intrare, apoi afisati rezultatul pe ecran.

    - 41 -

    #include #include using namespace std;

    int main(){int a,b;

    float R; char op; cout >a; cout >b; cout >op;

    switch (op){ case '+': R=a+b; break; case '-': R=a-b; break; case '*': R=a*b; break; case '/': if (b!=0) { R=float(a)/b; break;} else {cout

  • Introducere in ANSI C++

    a=2

    b=4

    operator:/

    2/4=0.5

    P11. Se citeste de la tastatura ziua din saptamana corespunzatoare date de 1 ale unei luni (1 pentru luni, 2 pentru marti, etc). Afisati ce zi din saptamana va avea o alta data a lunii respective.

    Ziuacorespunzatoaredateide1alunii:0

    Datadeverificat:14

    DatacorespundeuneizideDUMINICA

    - 42 -

    #include using namespace std;

    int main(){ int prima_zi, zi;

    cout >prima_zi; cout > zi;

    zi=(zi+prima_zi-1)%7;

    cout

  • Introducere in ANSI C++

    4.3 Probleme propusePp1. Dati un exemplu de problema in care expresia conditionala nu poate tine

    locul instructiunii if.

    Pp2. Calculati:

    f x , y =xy pentru x0xy pentru x0

    Pp3. Se citesc patru numere intregi de la tastatura. Afisati valorile distincte citite.

    Pp4. Sa se determine ultimele doua cifre ale produsului a*b, a si b citite de la tastatura.

    Pp5. Se citeste x intreg. Sa se calculeze ultima cifra a lui 2x.

    Pp6. Rezolvati ecuatia de gradul 1.

    Pp7. Se citesc 3 numere intregi de la tastatura. Daca toate nuemerele citite sunt pozitive, afisati-le in ordine crescatoare. Daca nu, afisati mesajul "We have a problem!".

    Pp8. Folosind instructiunea switch, afisati numele unei luni cu numarul de ordine citit de la tastatura.

    - 43 -

  • Introducere in ANSI C++

    Capitolul 5 Instructiuni repetitiveDaca dorim executia unor instructiuni de mai multe ori, in functie de o conditie,

    folosim instructiunile repetitive. Acestea sunt while, dowhilesi for.

    5.1 Instructiunea whileForma generala a instruciunii while:

    while(expresie)instructiune;

    Expresia poate fi de orice tip, inclusiv expresii aritmetice sau atribuiri, dar, ca si la instruciunea if, sunt de preferat expresii logice. Daca se doreste executarea unui grup de instructiuni se va folosi un bloc care sa formeze corpul instructiunii while.

    Executia instructiunii:

    - se evalueaza expresie

    - daca rezultatul este true (diferit de 0), se executa instructiune, apoi se revine la primul pas

    - daca rezultatul este false (0), se continua executia cu instructiunea urmatoare

    Poate cea mai simpla problema care se poate rezolva folosind structuri repetitive este afisarea valorilor intregi din [1,10]. In acest caz, o rezolvare de forma:...cout

  • Introducere in ANSI C++

    P1. Afisati numerele de la 1 la 10 pe ecran.

    citesc12345678910

    P2. Afisati urmatoarele serii de numere pe ecran (a,b,n sunt intregi citite de la tastatura, a

  • Introducere in ANSI C++

    n=10

    a=2

    b=7

    1248

    234567

    22.533.544.555.566.57

    1010101010

    - 46 -

    #include using namespace std;

    int main(){ int i,a,b,n; float pas,k;

    cout >n; cout >a; cout >b;

    i=1; while (i

  • Introducere in ANSI C++

    In unele cazuri corpul instructiunii while poate sa fie vid. In acest caz vomverondela folosi intructiunea vida ; .

    P3. Se citeste un numar intreg de la tastatura. Afisati cel mai mare numar multiplu de 10 mai mic ca numarul citit. (while fara corp)

    n=123

    120

    5.2 Instructiunea do-whileForma generala a instruciunii dowhile:do

    instructiune;

    while(expresie);

    Observatiile de la instructiunea while raman valabile si pentru aceasta instructiune. Diferenta dintre while si do-while este aceea ca, in cazul instructiunii do- while instructiunea se executa cel putin o data, chiar si in cazul in care expresie este falsa la prima iteratie.

    Modul de executie al instructiunii:

    - se executa instructiune

    - se evalueaza expresie

    - daca rezultatul este true (diferit de 0) se revine la primul pas- daca rezultatul este false (0) se incheie instructiunea si se continua programul

    - 47 -

    #include using namespace std;

    int main(){ int n; cout >n; while ((n--)%10!=0); // while cu corp vid cout

  • Introducere in ANSI C++

    Urmatoarele secvente de instructiuni sunt echivalente:

    if(expresie)do

    instructiune;while(expresie);

    while(expresie)instructiune;

    Figura 5.1

    P4. Se citesc de la tastatura doua caractere. Afisati pe ecran caracterele si codurilor lor ASCII din intervalul dat de catre caracterele citite.

    AC

    A65

    B66

    C67

    P5. Se citeste de la tastatura un numar real cu 3 zecimale. "Mutati" virgula pe toate pozitiile interioare posibile in cadrul numarului initial. Afisati pe ecran rezultatul, cate un numar pe un rand.

    - 48 -

    #include using namespace std;

    int main(){ char c1,c2,t,c; cin >> c1 >> c2; if (c1>c2){t=c1; c1=c2; c2=t;}

    c=c1; do{ cout

  • Introducere in ANSI C++

    n=12.789

    1278.9

    127.89

    12.789

    1.2789

    5.3 Instructiunea forIn general instructiunile while si do-while poarta numele de cicluri cu numar

    necunoscut de pasi. Instructiunea for este instructiunea ce implementeaza in C ciclul cu numar cunoscut de pasi (desi vom vedea ca nu este limitata la acest tip de cicluri).

    Forma generala a instruciunii for:for(expr1;expr2;expr3)instructiune;

    sau, de obicei:for(init;cond_de_oprire;reinit) instructiune;

    Modul de executie al instructiunii:

    - se executa init

    - cat timp expresie este adevarata

    - 49 -

    #include using namespace std;

    int main(){ float n; cout > n;

    n=n*100; do{ cout

  • Introducere in ANSI C++

    - se executa instructiune

    - se executa reinit

    Instructiunea for este folosita, in principal, pentru parcurgerea seriilor de numere.

    P6. Afisati urmatoarele serii de numere pe ecran (a,b,n sunt intregi citite de la tastatura, a> n >> a >> b;

    for(i=1;i

  • Introducere in ANSI C++

    54321012345

    345678

    124

    124816

    P7. Afisati, folosind trei metode diferite urmatoarea serie de numere pe ecran:1 0 1 0 1 0 ..., in total n valori

    n=7

    1010101

    1010101

    1010101

    Cum partea de reinitializare din cadrul buclei for contine orice expresie, nu numai incrementare/decrementare, instructiunea for devine echivalenta ca functionalitate cu bucla while.

    In figura 5.2 este data echivalenta dintre instructiunile for si while:

    - 51 -

    #include using namespace std;

    int main(){ int n,i,b; cout > n;

    for(i=1;i

  • Introducere in ANSI C++

    expr1;while(expr2){

    instructiune;expr3;}

    for(expr1;expr2;expr3)

    instructiune;

    Figura 5.2

    Folosirea expresiei virgula reprezinta o varianta prin care putem controla mai multe variabile in cadrul aceleiasi bucle for.

    P8. Afisati urmatoarele serii de numere pe ecran: 1 9 2 8 3 7 ... 9 1

    1 2 4 8 ... , in total n valori

    n=5

    192837465564738291

    124816

    Putem folosi, in cadrul instructiunii for, mai multi contori, eventual de tipuri diferite. In plus, toate partile din for sunt optionale, urmatoarea bucla fiind bucla infinita:

    for(;;);

    P10. Afisati tabela cu codurile ASCII, cate 10 pe un rand.

    - 52 -

    #include using namespace std;

    int main(){ int n,i,j,p; cout > n;

    for(i=1,j=9; i

  • Introducere in ANSI C++

    .............

    62?63@64A65B66C67D68E69

    F70G71H72I73J74K75L76M77N78O79

    ................

    5.4 break si continueIn cazul care se doreste iesirea din bucla curenta imediat, eventual in functie de

    o alta conditie decat cea din bucla, folosim instructiunea break. De obicei vom folosi instructiunea break pentru a nu complica conditia din bucla.

    Sintaxa:break;

    Instructiunea break va cauza iesirea doar din cadrul buclei curente, in cazul in care avem mai multe bucle imbricate, iesirea facandu-se in bucla imediat superioara.

    Tot pentru controlul fluxului de executie putem folosi instructiunea continue.

    Sintaxa:continue;

    Analog instructiunii break, fluxul executiei din cadrul buclei curente este intrerupt, dar executie revine la conditia de oprire din bucla.

    - 53 -

    #include using namespace std;

    int main(){ unsigned char c;

    for(c=0;c

  • Introducere in ANSI C++

    P11. Afisati pe ecran numerele prime mai mici decat n.

    n=20

    1235711131719

    P12. Afisati pe ecran urmatoarele numere, cu doua zecimale exacte: 1/10, 1/9, 1/8, ... 1/1, 1/-1, 1/-2, ... 1/-10

    0.10.110.120.140.170.20.250.330.5110.50.330.250.20.170.140.120.110.1

    - 54 -

    #include using namespace std;

    int main(){ int i;

    for(i=10;i>=-10;i--){ if (i==0) continue; cout.precision(2); cout

  • Introducere in ANSI C++

    5.5 instructiunea gotoTrecerea fluxului de executie la o pozitie oarecare, identificata printr-o eticheta

    se poate realiza prin instructiunea goto.

    Definirea etichetei se face in felul urmator:eticheta:

    iar utilizarea instructiunii goto:gotoeticheta;

    Chiar daca este o instructiune pusa la dispozitie in cadrul limbajului C, folosirea acesteia nu este recomandata, folosirea instructiunilor if,ifelsesiwhileputand realiza acelasi lucru, iar depanarea este mai facila.

    P13. Folosind instructiunea goto, afisati pe ecran numerele intregi din intervalul [a,b].36

    3456

    - 55 -

    #include using namespace std;

    int main(){ int i,a,b; cin >> a >> b;

    i=a;salt: cout

  • Introducere in ANSI C++

    5.6 Probleme tipIn acest subcapitol vom prezenta o serie de algoritmi ce vor fi rezolvati folosind

    instruciuni repetitive. Vom prezenta o serie de "scheme generale" de rezolvari de algoritmi. Aceste scheme sunt reguli de forma: "daca o problema suna asa, rezolvarea este, de obicei, cam asa".

    5.6.1 Probleme pe cifrele unui numarAcest gen de probleme prelucreaza numerele intregi la nivel ce cifre

    componente. Accesul la cifrele unui numar este dat de Figura 5.3

    Figura 5.3

    De aici obtinem urmatoarele:

    Si mai departe, parcurgerea unui numar intreg pozitiv, cifra cu cifra:

    unde foloseste(c)este o secventa de instructiuni dependenta de enuntul problemei.

    - 56 -

    1234 101230 123

    4

    n

    n%10 n/10

    c=n%10calcululultimeicifre

    n=n/10eliminareaultimeicifre

    while(n>0){ //cattimpmaiavemcifrec=n%10;foloseste(c);n=n/10;

    }

  • Introducere in ANSI C++

    O alta varianta este cea folosind instructiunea for:

    P14. Afisati cifrele unui numar, cate o cifra pe un rand.

    n=1942

    2

    4

    9

    1

    Ultima instructiune for(cea comentata) rezolva acceasi problema intr-o varianta compacta.

    - 57 -

    for(;n>0;n=n/10)foloseste(n%10);

    #include using namespace std;

    int main(){ int n,c; cout > n;

    while(n>0){ c=n%10; cout

  • Introducere in ANSI C++

    5.6.2 Probleme de divizibilitate

    Un numar n este divizibil cu numar d daca restul impartirii lui n la d este zero, deci:

    Plecand de la aceasta conditie, parcurgerea divizorilor unui numar intreg pozitiv n:

    P15. Afisati divizorii unui numar intreg pozitiv citit de la tastatura.

    n=120

    12345681012152024304060120

    P16. Se citeste de la tastatura un numar intreg pozitiv.

    Verificati daca este prim descompuneti-l in factori primi

    - 58 -

    n%d==0verificareadacad|n

    for(d=1;d n;

    for(d=1;d

  • Introducere in ANSI C++

    n=120

    120nuesteprim

    22235

    P17. Se citesc doua numere intregi pozitive de la tastatura. Calculati cmmdc(a,b) si cmmmc(a,b).

    - 59 -

    #include using namespace std;

    int main(){ int n,d; bool prim; cout > n;

    prim=true; for(d=2;d

  • Introducere in ANSI C++

    2436

    cmmdc(24,36)=12

    cmmmc(24,36)=72

    5.6.3 Sume, produse, numarariAvem urmatoarele scheme generale:

    Suma:

    Produsul:

    - 60 -

    S=0PentrutoatevalorileXdeinsumat

    S=S+X

    P=1PentrutoatevalorileXdeinmultit

    P=P*X

    #include using namespace std;

    int main(){ int a,b,cmmdc,cmmmc,r,aa,bb; cin >> a >> b;

    aa=a; bb=b; while(bb!=0){ r=aa%bb; aa=bb; bb=r; }

    cmmdc=aa; cmmmc=(a*b)/cmmdc;

    cout

  • Introducere in ANSI C++

    Numarari (contorizari):

    P18. Se citesc doua numere intregi a si b (a> a >> b;

    for(Sm=0,i=a; i

  • Introducere in ANSI C++

    De cate ori apare prima cifra in numar

    12141

    9813

    P20. Se citeste un numar intreg pozitiv n de la tastatura. Calculati:

    Suma divizorilor numarului

    Cate numere prime mai mici ca n exista

    - 62 -

    #include using namespace std;

    int main(){ int n,nn,S,P,pc,ct,c; cin >> n; nn=n;

    for(S=0,P=1; n ;n/=10){ c=n%10; S+=c; if (c%2==0) P*=c; }

    for(n=nn;n>=10;n/=10); pc=n;

    for(n=nn,ct=0; n ;n/=10) if (n%10 == pc) ct++;

    cout

  • Introducere in ANSI C++

    n=10

    184

    5.6.4 Maxime si minime

    Calcularea valorile minime sau maxime dintr-o serie de valori reprezinta o problema des intalnita in practica.Avem:

    Maxime:

    Minime:

    - 63 -

    max=infinitPentrutoatevalorileXdeparcurs

    if(X>max)max=X

    min=infinitPentrutoatevalorileXdeparcurs

    if(X n;

    S=0; for(d=1;d

  • Introducere in ANSI C++

    In aceste scheme, infinit reprezinta valoarea minima pe care o poate lua X si depinde de tipul de date cu care lucram.

    Biblioteca values.h ofera in acest sens o serie de constante predefinite utile, cum ar fi MAXINT, -MAXINT, MAXFLOAT etc.

    P21. Se citeste un numar intreg pozitiv de la tastatura. Calculati:

    Cifra maxima a numarului De cate ori apara cifra minima

    25221

    12823

    5.6.5 Citirea mai multor numere de la tastaturaIn cazul in care dorim prelucrarea a mai multe numere citite, avem urmatoarele

    rezolvari:

    a. Utilizatorul, ca prima faza, introduce numarul de valori ce vor fi citite ulterior:

    - 64 -

    #include using namespace std;

    int main(){ int n,nn,S,P,pc,ct,c; cin >> n; nn=n;

    for(S=0,P=1; n ;n/=10){ c=n%10; S+=c; if (c%2==0) P*=c; }

    for(n=nn;n>=10;n/=10); pc=n;

    for(n=nn,ct=0; n ;n/=10) if (n%10 == pc) ct++;

    cout

  • Introducere in ANSI C++

    b. Se cunoaste o conditie cat timp se vor citi valori:

    P22. Se citeste un numar n, apoi n valori reale de la tastatura. Calculati:

    maximul

    produsul

    5

    11521

    510

    - 65 -

    cin>>n; //numaruldevaloridecititfor(i=1;i>X; //citimnumarulfoloseste(X); //ilutilizamconformenuntului

    }

    cin>>X; //citimvaloarewhile(cond(X)){ //cattimpconditiaerespectata

    foloseste(X); //ilutilizamconformenuntuluicin>>X; //citimnumarul

    }

    #include #include using namespace std;

    int main(){ int n,x,i,max,P;

    max=-MAXINT; P=1; cin >> n; for(i=1;i> x; P=P*x; if (x>max) max=x; }

    cout

  • Introducere in ANSI C++

    P23. Se citesc numere intregi pana la intalnirea valorii 0. Calculati:

    Suma valorilor pare

    Minimul si de cate ori apare acesta

    2314611161120

    30

    1aparede5ori

    5.6.6 Generarea unor serii complexe de numere P24. Se citeste n (intreg pozitiv). Afisati pe ecran:a: 1 1 2 1 2 3 ... 1 2...n

    b: 1 2 2 3 3 3 ... n n ...n

    - 66 -

    #include #include using namespace std;

    int main(){ int x,i,min,ct_min,S;

    min=MAXINT; ct_min=0; S=0; cin >> x; while (x!=0){ if (x%2==0) S=S+x;

    if (x==min) ct_min++; else if (x> x; }

    cout

  • Introducere in ANSI C++

    5

    112123123412345

    122333444455555

    P25. Se citeste n (intreg pozitiv). Afisati pe ecran, sub forma data:

    1 1 2 1 1 2 3 2 1....................

    1 ................ 1

    1:1 2:1,2 ....

    6: 1,2,3,6 numarul urmat de divizori......

    1 2 3 4 52 3 4 5 63 4 5 6 74 5 6 7 85 6 7 8 9 (n=5)

    - 67 -

    #include using namespace std;

    int main(){ int n,i,k; cin >>n;

    for(k=1;k

  • Introducere in ANSI C++

    4

    1

    121

    12321

    1234321

    1:1

    2:1,2

    3:1,3

    4:1,2,4

    2345

    3456

    4567

    5678

    - 68 -

    #include using namespace std;

    int main(){ int n,i,k,d; cin >>n;

    for(k=1;k

  • Introducere in ANSI C++

    5.7 Probleme propusePp1. Refaceti solutiile propuse ale problemelor rezolvate in acest capitol, astfel

    incat sa folositi alt tip de instructiune repetitiva fata de cea utilizata in rezolvarea initiala (de exemplu in loc de forfolositi while).

    Pp2. Se citeste numarul intreg pozitiv n de la tastatura. Calculati valoarea urmatoarele expresii, folosind pentru fiecare expresie un alt tip de instructiune repetitiva:

    E = n + n/2 + n/3 + ... + 1

    P = 1! + 2! + ... +n!

    S = 12 + 42 + 72 + ... + (3n-2)2 Pp3. Se citesc doua numere intregi de la tastatura. Determinati daca cele doua

    numere sunt formate din aceleasi cifre, indiferent de cate ori apar. De exemplu 123 si 11321 sunt formate din aceleasi cifre.

    Pp4. Calculati ultima cifra a expresiei E= ab, a si b valori intregi pozitive citite de la tastatura.

    Pp5. Se citesc numere intregi de la tastatura pana la intalnirea unui numar negativ. Afisati numarul citit care are cei mai multi divizori.

    Pp6. Se citeste de la tastatura un numar intreg n. Afisati pe ecran urmatoarele serii de numere, pastrand formatul:

    1 2 1 2 3 2 1 2 3....................

    n ......1....... n

    1:1 2:2,2 3:3,3,3......

    n:n,n,n,...,n

    1 0 1 0 10 1 0 1 01 0 1 0 10 1 0 1 01 0 1 0 1 (n=5)

    Pp7. Afisati pe ecran tabla inmultirii pana la 10.

    Pp8. Se citeste n intreg, apoi n numere intregi de la tastatura. Afisati:

    cel mai mare si cel mai mic numar prim

    suma numerelor care au cifrele in ordine crescatoare

    - 69 -

  • Introducere in ANSI C++

    Capitolul 6 Vectori (matrici)In momentul in care complexitatea programelor creste, devine evidenta

    necesitatea folosirii unor tipuri de date complexe. Folosirea variabilelor simple permite stocarea unei singure valori, iar acest lucru devine un impediment major in momentul in care, sa zicem, avem nevoie de stocarea si realizarea de diferite operatii pe 100 de numere intregi.

    Un vector (tablou unidimensiunal) este o structura de date care poate stoca mai multe valori de acelasi tip.

    6.1 Declararea si initializareaExact ca si in cazul variabilelor simple, daca dorim utilizarea unui vector acesta

    trebuie sa fie declarat. C++ ofera mai multe moduri de a declara/initializa un vector, sub forma urmatoare:

    tipnume[dimensiune] sau

    tipnume[dimensiune]={v1,...,vn}, unde vi au un tip convertibil la tip sau

    tipnume[]={v1,v2,...,vn}, unde viau un tip convertibil la tip

    P1. Exemple de declarari/initializari de vectori si cat ocupa acestia in memorie.

    VectorulAocupa400octeti

    VectorulBocupa40octeti

    - 70 -

    #include using namespace std;

    int main(){ int A[100]; // vector de intregi neinitilalizat int B[10]={1,2,3,4};// vector de intregi partial initializat float X[]={3.14, 5, 2.5};// vector de reali complet initializat

    cout

  • Introducere in ANSI C++

    VectorulXocupa12octeti

    VectorulXare3valori

    Observam ca specificarea dimensiunii va duce la alocarea unui spatiu de memorie suficient pentru a pastra toate valorile din vector, iar in cazul in care nu avem specificata dimensiunea aceasta este data de numarul de valori cu care initializam vectorul.

    Accesul la elementele unui vector se face folosind indici. Fie urmatorea declaratie de vector:

    intA[10]={1,2,3,4};

    In acest caz se aloca in memorie un numar de 10 intregi, primele patru valori fiind initializate. In memorie situatia va asemanatoare cu cea descrisa in figura 6.1:

    Figura 6.1

    Observam ca primul element este A[0], al doilea A[1], si, in final, ultimul element valid va fi A[9]. Primele patru elemente, cele initializate, au valori cunoscute, in rest nu stim ce valori exista in vector. In functie de compilator, s-ar putea ca ele sa fie initializate cu valoare 0, dar este mai bine sa nu contam pe acest fapt.

    Daca, in continuare, avem urmatoarele atribuiri:A[0]=5;

    A[9]=A[1]+A[2]+A[3];

    vom avea urmatoarea situatie (Figura 6.2):

    Figura 6.2

    - 71 -

    1 2 3 4 ? ?...

    A[0] A[1] A[9]

    5 2 3 4 ? 9...

    A[0] A[1] A[9]

  • Introducere in ANSI C++

    6.2 Citirea si scrierea vectorilorVom prezenta in continuare primele operatii pe vectori.

    In cazul in care dorim sa realizam citirea si afisarea unui vector, exista posibilitatea de a accesa vectorul elemente cu element prin intermediul unor indici constanti, asa cum se observa in problema urmatoare:

    P2. Se citesc cinci valori ale unui vectori de intregi. Afisati vectorul in ordine inversa.

    DatielementelevectoruluiA:24135

    A:53142

    Aceasta abordare nu acopera urmatoarele cazuri:

    - daca avem un numar mare de elemente in vector

    - daca numarul de elemente din vector difera de la rulare la rulare

    Pentru a rezolva aceste situatii, in loc sa accesam valorile din vector folosind indici constanti, vom folosi o variabila ca indice. Accesul la elementele vectorului se va face folosind o notatie de forma A[i], unde i va fi o valoare intrega ce reprezinta un indice valid in vector, adica o valoare din multimea {0,1,...,n-1}.

    Citirea unui element va fi de forma: cin>>A[i];

    unde i va parcurge indicii vectorului.

    - 72 -

    #include using namespace std;

    int main(){ int A[5];

    cout > A[0] >> A[1] >> A[2] >> A[3] >> A[4];

    cout

  • Introducere in ANSI C++

    P3. Se citesc cinci valori ale unui vectori de intregi. Afisati vectorul in ordine inversa. (varianta 2)

    DatielementelevectoruluiA:34567

    A:76543

    In general, pentru a creste flexibilitatea programului, vom da posibilitatea utilizatorului sa foloseasca vectori de lungime variabila, lungime limitata doar de modul in care am declarat vectorul. De acum inainte, atunci cand ne referim la un vector, ne vom referi la o pereche de forma (A,n), unde A este vectorul, iar n este lungimea actuala a acestuia.

    P4. Se citeste un vector de la tastatura. Afisati vectorul pe ecran.

    4

    3412

    3412

    - 73 -

    #include using namespace std;

    int main(){ int A[5]; int i;

    cout A[i];

    cout =0;i--) cout

  • Introducere in ANSI C++

    Aspectul sec al aplicatiei este remediat in exemplul urmator:

    P5. Se citeste un vector de la tastatura. Afisati vectorul pe ecran. (varianta cosmetizata)

    n=3

    A[0]=7

    A[1]=15

    A[2]=9

    A=(7,15,9)

    In general recomand folosirea variantei simple daca lucram programul pe foaie, orice varianta practica, pe calculator, folosind o varianta de citire/scriere user-friendly.

    Dupa cum observam in ultimele exemple, accesul la elementele vectorului (A,n) respecta, in general, urmatoarea schema generala:

    Modul in care folosim elementele vectorului depinde de la problema la problema.

    - 74 -

    #include using namespace std;

    int main(){ int A[100],n; int i;

    cout >n; for(i=0;i

  • Introducere in ANSI C++

    6.3 Generari de vectoriUneori elementele vectorilor nu vor fi valori citite de la tastatura ci valori

    construite in functie de enunt. Urmatoarele exemple ilustreaza cateva cazuri mai des intalnite in practica.

    In problema urmatoare exploatam relatia dintre indicele si valoarea memorata pe pozitia respectiva:

    P6. Se citeste de la tastatura un numar intreg 1

  • Introducere in ANSI C++

    Generarea recursiva a vectorilor este o varianta intuitiva de rezolvare, daca enuntul problemei permite folosirea unei relatii prin care construim un element in functie de cele deja generate.

    P7. Se citeste de la tastatura un numar intreg 1

  • Introducere in ANSI C++

    Generarea de valori aleatoare in vectori poate fi utila daca dorim testarea unor algoritmi pe vectori si dorim sa evitam introducerea de valori de la tastatura.

    P8. Generati un vector de lungime citita de la tastatura, continand valori aleatoare in intervalul [a,b], an; cout >a; cout >b;

    for(i=0;i

  • Introducere in ANSI C++

    d. minimul valorilor pozitive

    n=6

    112233

    Suma:0

    Produsulvalorilorpare:4

    Maximul:3

    minimulvalorilorpozitive:1

    P10. Generati un vector aleator de 2n elemente din [1,10], n citit de la tastatura, nn; for(i=0;i> A[i];

    S=0;P=1; for(i=0;i

  • Introducere in ANSI C++

    n=2

    Vectorul:4786

    E:1.90476

    F:27

    P11. Verificati daca un vector citit de la tastatura este sau nu:a. sortat crescator

    b. este sir Fibonacci (primele doua vaori sunt 1, in rest fiecare element de obtine insumand cele doua valori anterioare)

    c. simetric

    - 79 -

    #include #include using namespace std;

    int main(){ int A[20],n,i; float E; int F,max;

    cout >n; for(i=0;i

  • Introducere in ANSI C++

    n=5

    11235

    Vectoruldatestecrescator,esteFibonacci,nuestesimetric.

    sau:

    n=6

    162261

    Vectoruldatnuestecrescator,nuesteFibonacci,estesimetric.

    - 80 -

    #include using namespace std;

    int main(){ int A[100],n,i,j; bool cresc, fibo, sim;

    cout >n; for(i=0;i> A[i];

    cresc=true; for(i=0;iA[i+1]) cresc=false;

    if ((A[0]==1)&&(A[1]==1)) fibo=true; for(i=2;fibo && i

  • Introducere in ANSI C++

    6.5 Sortarea si interclasareaProblema sortarii unui vector, este problema reasezarii elementelor in asa fel

    incat ele sa respecte o relatie de ordine (crescatoare). Problema este bine reprezentata in literatura de specialitate (vezi [1], [4], [6], [8]). Prezentam in continuare trei metode de sortare consacrate.

    P12. Sortarea prin selectie

    n=5

    24513

    Vectorulsortat:12345

    Ideea din spatelealgoritmului este urmatoarea:

    - aducem pe prima pozitie elementul minim din vector, prin interschimbarea lui A[0] cu acele elemente dintre A[1],A[2],...A[n-1] care sunt mai mici ca A[0].

    - repetam algoritmul descris la pasul anterior pe cazul general, aducand pe pozitia A[i] minimul dintre A[i],A[i+1],...,A[n-1]

    - la sfarsit toate valorile sunt pe pozitiile corecte

    - 81 -

    #include using namespace std;

    int main(){ int A[100],n,i,j,t;

    cout >n; for(i=0;i> A[i];

    for(i=0;i

  • Introducere in ANSI C++

    P13. Bubble Sort

    n=5

    24513

    Vectorulsortat:12345

    Ideea este urmatoarea:

    - comparam, rand pe rand, toate valorile succesive din vector

    - daca elementul din stanga este mai mare ca cel din dreapta, atunci interschimbam elementele

    - in urma primei treceri prin vector, elementul maxim a ajuns sigur pe ultima pozitie

    - repetari succesive ale algoritmului vor duce la deplasari ale elementelor mari spre sfarsit, pana la ocuparea pozitiei corecte

    - cum la fiecare trecere cel putin un element ajunge la locul corect, din maxim n-1 treceri vor avea vectorul sortat crescator

    - 82 -

    #include using namespace std;

    int main(){ int A[100],n,i,k,t;

    cout >n; for(i=0;i> A[i];

    for(k=1;k

  • Introducere in ANSI C++

    P14. Sortarea prin numarare

    Pentru a putea aplica sortarea prin numarare, se stie ca intervalul in care A[i] poare lua valori este de forma [0,m], cu m cunoscut si nu foarte mare. Pentru problema noastra am considerat m=10.

    n=10

    Vectorulinitial:3675356291

    Vectorulsortat:1233556679

    Functionarea algoritmului:

    - numaram fiecare valoare de cate ori apare in vector

    - odata avut vectorul de contori, nu avem decat sa completam valorile, de la cea mai mica la cea mai mare, de cate ori trebuie in vectorul rezultat

    - 83 -

    #include using namespace std;

    int main(){ int A[100],n,i,k,j; int ct[100];

    cout >n; for(i=0;i

  • Introducere in ANSI C++

    Interclasarea se definiste ca fiind algoritmul care, primind doi vectori sortati, obtine un al treilea vector sortat continand elementele vectorilor initiali.

    P15. Interclasarea vectorilor

    A:245710

    B:145791216

    C:124455779121610

    Vectorii au fost generati aleator, dar in ordine crescatoare.

    - 84 -

    #include using namespace std;

    int main(){ int A[100],B[100],n,m,i,j; int C[100],k;

    n=2+rand()%10; A[0]=2; for(i=1;i

  • Introducere in ANSI C++

    6.6 Declararea matricilorLimbajul C++ permite, pe langa matricile unidimensionale (vectorii), matrici

    bidimensionale si multidimensionale.

    Declararea unei matrici:

    tipnume[dimensiune1][dimensiune2] sau, mai general,tipnume[dimensiune1][dimensiune2]...[dimensiunen]

    Cele mai folosite, pe langa vectori, sunt matricile bidimensionale, numite de acum, din comoditate, matrici.

    Exista posibilitatea initializarii elementelor unei matrici, dand un vector de vectori de valori, valori ce vor fi completate in matrice pe linii.

    P16. Declarari de matrici. Cantitatea de memorie ocupata de matrici.

    A[10][10]ocupa400octeti

    B[4][3]ocupa48octeti

    6.7 Citirea si afisarea matricilorAccesul la elementele unei matrici se face tot prin intermediul indicilor. Astfel,

    pentru o declaratie de forma intA[10][10]indicii corespunzatori sunt dati in Figura 6.3.

    - 85 -

    #include using namespace std;

    int main(){ int A[10][10]; float B[4][3]={{1,2}, {3,4}, {5,6}};

    cout

  • Introducere in ANSI C++

    Figura 6.3

    P17. Se citeste o matrice de la tastatura. Afisati matricea.

    n=2

    m=2

    A[0][0]=1

    A[0][1]=2

    - 86 -

    A[0][0] A[0][1] A[0][2]

    A[1][0] A[1][1] A[1][2]

    . . .

    . . .

    A[0][9]

    A[1][9]

    A[9][0] A[9][1] A[9][2] . . . A[9][9]

    . . .

    . . .

    . . .

    . . .

    Linia 0

    Linia 1

    Linia 9C

    oloana 1

    Coloana 0

    Coloana 9

    #include using namespace std;

    int main(){ int A[10][10],n,m,i,j;

    cout >n; cout >m; for(i=0;i

  • Introducere in ANSI C++

    A[1][0]=3

    A[1][1]=4

    12

    34

    Analog citirii vectorilor, citirea efectiva a elementelor din matrice este precedata de specificarea numarului de linii si de coloane. Primul indice reprezinta linia, iar al doilea coloana.

    In general, parcurgerea pe linii a unei matrici are loc astfel:

    6.8 Probleme cu matriciP18. Afisati pe coloane o matrice initializata din cod

    147

    258

    369

    - 87 -

    for(i=0;i

  • Introducere in ANSI C++

    P19. Generati si afisati urmatoarele matrici:1111 1010 1234

    2222 0101 5678

    3333 1010 9101112

    4444 0101 13141516

    - 88 -

    #include using namespace std;

    int main(){ int A[10][10], B[10][10], C[10][10]; int n,m,i,j,v;

    cout > n; cout > m;

    v=1; for(i=0;i

  • Introducere in ANSI C++

    In cazul in care numarul de linii si cel de coloane este identic spunem despre matrice ca este patratica. In acest caz, vorbim despre diagonala principala si cea secundara. Relatia dintre indici raportata la diagonale este data in Figura 6.4:

    Figura 6.4

    P20. Completati o matrice sub forma:

    - 89 -

    1 2 2 2 2 15 1 2 2 1 35 5 1 1 3 35 5 1 1 3 35 1 4 4 1 31 4 4 4 4 1

    i==jij

    i+j==

    n-1

    i+jn-1

    #include using namespace std;

    int main(){ int A[10][10], n,i,j; cout > n;

    for(i=0;i

  • Introducere in ANSI C++

    P21. O matrice contine cifre pe primele n-1 linii. Considerand fiecare rand al matricii ca fiind numarul in baza 10 corespunzator, completati pe ultima linie suma numerelor zecimale de pe liniile date.

    0245

    0091

    1234

    1570

    - 90 -

    #include using namespace std;

    int main(){ int A[10][10], n,i,j,t;

    cout > n; for(i=0;i A[i][j];

    t=0; for(j=n-1;j>=0;j--){ for(i=0;i

  • Introducere in ANSI C++

    6.9 Probleme propusePp1. Generati si afisati vectorii (n intreg citit de la tastatura):a: 1 0 2 0 3 0 ...

    b: 1 2 3 5 7 11 ... (primele n numere prime)c: 1 1 1 3 5 9 17 ... (tribonacci :))Pp2. Se citeste un vector de la tastatura. Calculati:

    S=a[0]*a[1]+a[1]*a[2] + ... + a[n-2]*a[n-1]E = suma valorilor cu indice prim

    F = produsul ultimelor cifre

    Pp3. Se citesc doi vectori de intregi de la tastatura. Determinati daca cei doi vectori sunt formate din aceleasi valori, indiferent de ordine si cate ori apar. De exemplu a: 1,2,3 si b:1,1,3,2,1 satisfac proprietatea ceruta.

    Pp4. Un vector contine cifre. Care este cel mai mare numar de trei cifre care poate fi format din cifrele vectorului?

    Pp5. Generati un vector continand n valori intregi in intervalul [-100,100]. Mutati valorile pozitive la incepu si cele negative la sfarsitul vectorului (dintr-o singura parcurgere).

    Pp6. Se citeste o matrice de la tastaura. Verificati daca elementele de pe diagonale sunt in ordine crescatoare sau descrescatoare, afisand mesaje sugestive pe ecran.

    Pp7. Se citesc o matrice patratica de nxn si un vector de lungime n. Verificati de cate ori regasim vectorul in matrice, ca linie sau coloana.

    Pp8. O matrice contine valori in intervalul [1,100]. Generati un vector continand valori din [1,100] care NU se regasesc in matrice, in ordine descrescatoare.

    - 91 -

  • Introducere in ANSI C++

    Capitolul 7 Siruri de caractereDatorita gradului de utilizare, acestui tip structurat de date i s-a acordat o atentie

    deosebita; exista functii de citire/scriere specifice, plus o serie functii de uz general pe siruri de caractere definite in biblioteca standard.

    7.1 Declaratie si initializareForma generala a declaratiei unui sir de caractere este:

    charnume[dimensiune] sau

    charnume[dimensiune]=c1c2...cn, sau

    charnume[]=c1c2...cn

    Urmatorul stil de initializare nu este recomandat, desi este suportat de catre compilator:

    charnume[dimensiune]={c1,c2,...,cn}

    P1. Exemple de declarari/initializari de siruri.

    VectorulSocupa100octeti

    Vectorulsocupa20octeti

    VectorulXocupa4octeti

    VectorulYocupa4octeti

    - 92 -

    #include using namespace std;

    int main(){ char S[100]; // sir neinitilalizat char s[20]="Ana are laptop";// sir initializat char X[]="abc"; // initializare corecta char Y[]={'x','y','z'}; // initializare nerecomandata

    cout

  • Introducere in ANSI C++

    Vom exemplifica in constinuare modul de memorare a sirurilor de caractere in C. In exemplul anterior observam ca, in urma declaratiei

    charX[]=abc;

    in memorie X ocupa 4 octeti. Cum unui caracter ii este necesar un octet pentru a fi memorat, observam ca s-a alocat un octet in plus. Motivul este cel ca in limbajul C este folosit terminatorul NULL pentru a marca sfarsitul unui sir de caractere. Pentru exemplul de mai sus avem urmatoarea situatia dinfigura 7.1:

    Figura 7.1

    Acelasi lucru se intampla atunci cand folosi constante de tip sir de caractere, compilatorul adaugand automat terminatia NULL. Caracterul \0 este caracterul cu codul ASCII egal cu zero si este diferit de caracterul 0.

    In general, in cazul in care declaram o variabila de tip sir de caractere, trebuie tinut cont de terminatorul NULL, deci practic trebuie sa declaram cu dimensiune cu 1 mai mare decat a sirului efectiv.

    Diferenta de reprezentare dintre un caracter si sirul de caractere identic este evidentiat de exemplul urmator.

    P2. Diferenta dintre un caracter si sirul de caractere corespunzator.

    Caracterul'A'ocupa1octeti

    Sirul"A"ocupa2octeti

    Este necesara folosirea secventelor escape pentru afisarea si .

    - 93 -

    a b c \0 ? ...

    X[0] X[1]

    #include using namespace std;

    int main(){

    cout

  • Introducere in ANSI C++

    Diferenta de reprezentare este evidentiata de Figura 7.2:

    Figura 7.2

    7.2 Operatii de citire/scriere pe siruri de caractereCitirea si scrierea sirurilor de caractere este mult simplificata fata de citirea

    vectorilor, nu mai este necesara memorarea lungimii actuale (datorita terminatorului NULL) si nu trebuie sa citim caracter cu caracter. Urmatorul exemplu da diferite moduri de citire/scriere:

    P3. Citirea/scierea sirurilor de caractere.

    Introducetiunsir:Anaarelaptop

    Introducetiincaunsir:Anaarelaptop

    Primulsirintrodus:Anaarelaptop

    Aldoileasirintrodus:Ana

    - 94 -

    A A \0

    Caracterul A Sirul de caractere A

    #include using namespace std;

    int main(){

    char S1[100],S2[100];

    cout S2; // citeste pana la primul caracter "alb"

    cout

  • Introducere in ANSI C++

    Observam ca citirea nu trebuie facuta caracter cu caracter. Daca S este un sir de caractere, folosind o constructie de forma

    cin>>S;

    citirea se opreste la primul caracter alb (spatiu, tab, enter). Citirea intregului rand, adica pana la apasarea tastei Enter se face folosind:cin.getline(S,dimensiune);

    unde dimensiune este numarul maxim de caractere care va fi citit.

    La citire, adaugarea terminatorului NULL este realizata in mod automat. Daca dorim citirea caracter cu caracter, acest lucru este posibil (in stilul citirii vectorilor), dar trebuie sa avem grija de terminatorul NULL, functiile pe siruri de caractere tinand cont de acesta.

    7.3 Accesul la caracterele unui sirDaca dorim parcurgerea unui sir de caractere, flosim urmatoare schema

    generala:

    Observam conditia de oprire S[i], echivalenta cu S[i]!=NULL. In cuvinte, schema de mai sus ar fi: de la primul caracter si pana la caracterul NULL, foloseste caracterul curent. Alte scheme utile:

    Verificarea daca un caracter este sau nu cifra:

    Verificarea daca un caracter este sau nu litera mare:

    - 95 -

    for(i=0;S[i];i++)foloseste(S[i]);

    If((c>=0)&&(c=A)&&(c

  • Introducere in ANSI C++

    P4. Se citeste un sir de caractere fara spatii. Inlocuiti literele mici cu litere mari si invers.

    Introducetiunsir:abcDEF123

    ABCdef123

    P5. Se citeste un sir de caractere cantinand cuvinte separate de unul sau mai multe spatii. Afisati numarul de cuvinte.

    Introducetiunsir:Anaarelaptop

    Numaruldecuvinte:3

    - 96 -

    #include using namespace std;

    int main(){ char S[100]; int i;

    cout > S;

    for(i=0;S[i];i++){ if ( (S[i]>='a')&&(S[i]='A')&&(S[i]

  • Introducere in ANSI C++

    In problema P5, numarul de cuvinte este determinat numarand cate succesiuni de forma spatiu-caracter avem in sir, primul cuvant fiind numarat separat daca sirul nu incepe cu spatiu.

    7.4 Functii specifice sirurilor de caractereIn biblioteca standard string.hsunt definite o serie de functii utile pe siruri de

    caractere . Cele mai utilizate sunt date in Tabelul 7.1:

    Functie Efect Exemple

    strlen(S)Returneaza lungimea sirului dat ca paramentru

    strlen("trei")>4

    strcpy(S1,S2) Copiaza S2 peste S1 strcpy(S,"abcd")

    strcat(S1,S2) Concaterneaza S2 la S2 strcpy(S,"Imiplace");strcat(S,"C++");

    strcmp(S1,S2)

    Compara lexicografic sirurile date ca parametri. Returneaza0 daca S1==S2< 0 daca S1 0 daca S1>S2

    if(strcmp(S1,S2)==0)cout

  • Introducere in ANSI C++

    Observatii:

    itoanu este implementata in standardul ANSI C++, dar este suportata de multe compilatoare.

    Mai departe dam implementari posibile ale acestor functii, rezolvand problemele date atat folosind functiile de bilbioteca cat si implementand din cod.

    P6. Se citeste un sir de caractere. Afisati lungimea acestuia.

    Introducetiunsir:Anaarelaptop

    Lungimea:14

    Lungimea(strlen):14

    Observam ca functia strlennu contorizeaza si terminatorul NULL. Nu este recomandata parcurgerea unui sir de caractere sub forma

    for(i=0;i

  • Introducere in ANSI C++

    P7. Se citeste un sir de caractere. Copiati-l in alt sir.

    Introducetiunsir:Anaarelaptop

    X::Anaarelaptop

    Y(strcpy):Anaarelaptop

    In cazul in care facem copierea din cod, trebuie sa avem grija de terminator, in caz contrar alte operatii pe sir, cum ar fi afisarea, nu vor actiona dupa asteptari.

    Atribuire directa intre doua siruri de caractere (posibila in alte limbaje), de forma: S1=S2;

    va da un mesajul de eroaren1=atoi(S1);p07.cpp:21:error:ISOC++forbidsassignmentofarrays

    P8. Concaternati doua siruri de caractere.

    In implementarea urmatoare am comentat apelul functiei strcat. Analog exemplelor anterioare, observam ca folosirea functiei de biblioteca simplifica mult programul. O atribuire de forma:X=S1+S2;va da mesajul de eroare:

    p09.cpp:23:error:invalidoperandsoftypeschar[100]andchar[100]tobinaryoperator+

    - 99 -

    #include #include using namespace std;

    int main(){ char S[100],X[100],Y[100]; int i;

    cout

  • Introducere in ANSI C++

    Introducetinumele:Ana

    SalutAna

    Exista posibilitatea de a compara doua siruri de caractere. In acest caz se va tine cont de ordinea lor lexicografica (cea din dictionar), iar litera mare va fi considerata mai mica fata de litera mica corespunzatoare (conform codurilor ASCII). Urmatoare exemple sunt sugestive:

    "A"

  • Introducere in ANSI C++

    Introducetisirul1:trei

    Introducetisirul2:patru

    "trei"estemaimareca"patru"

    P10. Se citesc doua siruri de caractere reprezentand numere intregi. Faceti suma lor, apoi afisati pe ecran rezultatul.

    Introducetinumarul1:123

    Introducetinumarul2:234

    123+234=357

    - 101 -

    #include #include using namespace std;

    int main(){ char S1[100],S2[100]; int i,j; cout

  • Introducere in ANSI C++

    P11. Verificati daca un nume apare intr-un sir.

    Introducetinumele:Radu

    Introducetisirul:ToniAlinaRaduCristi

    "Radu"apareinsirul"ToniAlinaRaduCristi"

    7.5 Matrici de caractereUtilizarea unui numar mare de siruri de caractere intr-o aplicatie implica

    folosirea unui sir de siruri de caractere. Urmatoarele exemple arata definirea si initalizarea unei matrici de caractere:

    charS[10][10]={"Ana","are","laptop"};

    Pentru exemplul de mai sus, S[0] este "Ana", S[1] este "are", S[2] este "laptop", iar S[3],...,S[9] sunt siruri vide.

    In general, fiecare rand al unei matrici de caractere reprezinta un sir de caractere.

    - 102 -

    #include #include using namespace std;

    int main(){ char nume[10],S[100]; int rez,n1,n2;

    cout

  • Introducere in ANSI C++

    P12. Se citesc doua siruri reprezentand zile ale saptamanii. Folosind o matrice de caractere initializata cu zilele saptamanii, afisati zilele curinse intre cele citite de la tastatura.

    Introducetiziua1:marti

    Introducetiziua2:joi

    marti

    miercuri

    joi

    - 103 -

    #include #include using namespace std;

    int main(){ char zile[7][10]={ "luni", "marti", "miercuri", "joi", "vineri", "sambata", "duminica" };

    char z1[10],z2[10]; int poz1,poz2,i;

    cout

  • Introducere in ANSI C++

    7.6 Alte aplicatiiP13. Se citeste un sir de caractere de la tastatura. Afisati toate prefixele si

    sufixele acestuia.

    abcdef

    Prefixe:

    abcdefabcdeabcdabcaba

    Sufixe:

    abcdefbcdefcdefdefeff

    - 104 -

    #include #include using namespace std;

    int main(){ char cuvant[100]; char copie[100]; int i,j;

    cin >> cuvant;

    cout 0;i--){ copie[i]='\0'; // "mutam" sfarsitul cuvantului la stanga cout

  • Introducere in ANSI C++

    P14. Se citesc de la tastatura siruri de caractere pana la intalnirea sirului "stop". Afisati cuvantul de lungime maxima.

    micmarescurtlungstop

    Cuvantulcellung:scurt

    - 105 -

    #include #include using namespace std;

    int main(){ char S[100],Smax[100];

    cin >> S; strcpy(Smax,S);

    while (strcmp("stop",S)){ if (strlen(S)>strlen(Smax)) strcpy(Smax,S); cin >>S; }

    cout

  • Introducere in ANSI C++

    7.7 Probleme propusePp1. Se citesc de la tastatura doua siruri de caractere continand doar cifre.

    Considerand sirurile ca fiind numere in baza 10, calculati suma lor in alt sir.

    Pp2. Se citeste de la tastatura un sir de caractere continand litere mici si spatii. Afisati cuvintele conponente, cate unul pe un rand.

    Pp3. Un sir de caractere contine doar litere mici si litere mari. Prin operatie elementara intelegem transformarea din litera mica in litera mare sau invers. Care este numarul minim de operatii elementare astfel incat sa obtinem din sirul initial unul avand toate literele mici sau toate literele mari.

    Pp4. Se citesc de la tastatura cuvinte (fara spatii), pana la citirea cuvantului "gata". Afisati cel mai lung cuvant care contine doar vocale.

    Pp5. Se citeste un sir S, continand cuvinte separate de exact un spatiu si doua cuvinte, C1 si C2. In locuiti toate aparitiile cuvantului C1 din testul S cu cuvantul C2.

    Pp6. O matrice de caractere contine cate un cuvant pe un rand. Sortati cuvintele lexicografic, apoi afisati-le pe ecran.

    - 106 -

  • Introducere in ANSI C++

    Capitolul 8 Structuri si alte tipuri utilizatorDupa cum am vazut, un vector grupeaza sub un nume mai multe valori de

    acelasi tip. In acest capitol vom urmarii gruparea informatiilor corelate de tipuri diferite.

    8.1 StructuriGruparea informatiilor corelate de tipuri diferite se face prin utilizarea

    structurilor. Avem:structnume_structura{

    declaratii_de_variabile;

    }lista_variabile;

    Atat nume_structura cat si lista_variabile sunt optionale, dar pot lipsi ambele in acelasi timp.

    In C++, prin aceasta, nume_structura devine un nou tip de data, tip care poate fi folosit la declararea unor variabile.

    nume_structuralista_variabile;

    Sintaxa permite declararea directa, in momentul definirii unei structuri a unor variabile de acel tip.

    Daca lipseste nume_structura, avem o structura omonima:struct{

    declaratii_de_variabile;

    }lista_variabile;

    In acest caz vom folosi in program doar variabilele definite, neexistand posibilitatea definirii altor variabile de forma data.

    Variabilele definite in bloc repezinta datele ce dorim sa le grupam.

    Accesul la elementele unei structuri se face folosind operatorul .:variabila.nume_data

    - 107 -

  • Introducere in ANSI C++

    Exista posibilitatea de a face atribuiri intre doua variabile de tip structura, daca cele doua variabile sunt de acelasi tip. Deci daca avem:

    nume_structuraV1,V2;

    atunci atribuirea V1=V2; este valida.

    Initializarea unei structuri se face intr-o maniera analoaga initializarii vectorilor.

    P1. Definiti structura persoana, continand (nume, prenume, varsta). Definiti o variabila initializata de tipul persoana, mariti varsta cu 1, apoi afisati pe ecran.

    GatesGheorghe31

    In memorie o variabila de tip structura ocupa o zona continua de memorie. Figura 8.1 ilustreaza reprezentarea in memorie a unei structuri.

    Figura 8.1

    Tipurile de date definite prin cuvantul cheie struct pot fi transmise ca parametri sau pot fi returnate din functii.

    - 108 -

    #include using namespace std;

    // definirea structurii cerutestruct persoana{ char nume[20]; char prenume[20]; int varsta; };

    int main(){ persoana P={"Gates","Gheorghe",30}; P.varsta++; cout

  • Introducere in ANSI C++

    P2. Definiti structura complex (re,im). Implementati functiile suma, produs si modul.

    S=6+i*1

    P=7+i*9

    m=2.23607

    - 109 -

    #include #include using namespace std;

    struct complex{ float re; float im;};

    complex suma(complex,complex);complex produs(complex,complex);float modul(complex);

    int main(){ complex z1={1,2},z2={5,-1},S,P; // z1= 1+2i si z2=5-i float m;

    S=suma(z1,z2); P=produs(z1,z2); m=modul(z1);

    cout

  • Introducere in ANSI C++

    Putem defini vectori de structuri sau structuri care contin alte structuri.

    P3. Definiti structura persoana (nume, data_nasterii), unde data nasterii este o alta structura (zi,luna,an). Cititi de la tastatura 3 persoane, apoi afisati-le in ordine crescatoare dupa anul nasterii.

    Ana1282003

    Luci2151998

    Tom5122000

    Luci21/5/1998

    Tom5/12/2000

    Ana12/8/2003

    - 110 -

    #include using namespace std;

    struct data{ int zi,luna,an;};

    struct persoana{ char nume[20]; data datan;};

    int main(){ persoana P[10],t; int j,i,nr=3;

    for(i=0;i> P[i].nume; cin >> P[i].datan.zi >> P[i].datan.luna >> P[i].datan.an; }