Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15...

227
Note de laborator: C ++ Vers. 2.0 — Corectat: iunie 2013 Octavian G. Mustafa * e-mail address: [email protected] Cuprins Motivat ¸ie ............................................................... 1 Programe din “viat ¸a real˘ a” ............................................ 10 Alte programe ˆ ın C .................................................... 28 Programare ˆ ın C ++ ..................................................... 63 S ¸i acum? ............................................................ 208 Surse bibliografice .................................................... 219 1 Motivat ¸ie: plecˆ and de la zero. . . ˆ Incepem discut ¸ia cu cˆateva programescriseˆ ın limbajul C. Aceasta pentru c˘a,ˆ ın mediul Internet, exist˘ a mult cod C gratuit pe care ˆ ıl putem adapta nevoilor noastre. Limbajul C ++ este o extensie (un superset) a limbajului C, vezi [41, p. 8], astfel c˘a intruct ¸iunile dintr-un program C “portabil” (vezi POSIX, ANSI C etc., cf. [33], [20, p. 151]) vor funct ¸iona excelent ˆ ın cadrul unui program C ++ . Putem, fire¸ ste, studia limbajul C ++ ˆ ın mod direct, f˘ ar˘ a a apela la C, cf. [42, p. 9], ˆ ıns˘a nu vom face aceasta aici. Se obi¸ snuie¸ ste — ˆ ınc˘art ¸ile blˆ ande cu cititorul — s˘a seˆ ınceap˘ a studiul unui limbaj de programare descriind “cum * Acest eseu nu a fost raportat vreunui referent. ˆ In consecint ¸˘ a, cont ¸inutul s˘au trebuie considerat “ca atare.” ˆ In particular, utilizarea instruct ¸iunilor care urmeaz˘a se face pe r˘aspundereadumneavoastr˘ a. Autorul v˘a a¸ steapt˘ a comentariile la adresa de e-mail de mai sus ¸ siv˘amult ¸ume¸ ste anticipat pentru efortul depus. 1

Transcript of Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15...

Page 1: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Note de laborator:C++

Vers. 2.0 — Corectat: iunie 2013

Octavian G. Mustafa∗

e-mail address: [email protected]

Cuprins

Motivatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Programe din “viata reala” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Alte programe ın C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28Programare ın C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Si acum? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208Surse bibliografice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

1 Motivatie: plecand de la zero. . .

Incepem discutia cu cateva programe scrise ın limbajul C. Aceasta pentruca, ın mediul Internet, exista mult cod C gratuit pe care ıl putem adaptanevoilor noastre. Limbajul C++ este o extensie (un superset) a limbajului C,vezi [41, p. 8], astfel ca intructiunile dintr-un program C “portabil” (veziPOSIX, ANSI C etc., cf. [33], [20, p. 151]) vor functiona excelent ın cadrulunui program C++.

Putem, fireste, studia limbajul C++ ın mod direct, fara a apela la C, cf.[42, p. 9], ınsa nu vom face aceasta aici. Se obisnuieste — ın cartile blande cucititorul — sa se ınceapa studiul unui limbaj de programare descriind “cum

∗Acest eseu nu a fost raportat vreunui referent. In consecinta, continutul sau trebuieconsiderat “ca atare.” In particular, utilizarea instructiunilor care urmeaza se face peraspunderea dumneavoastra. Autorul va asteapta comentariile la adresa de e-mail de maisus si va multumeste anticipat pentru efortul depus.

1

Page 2: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

se vede” acesta din urma dinspre limbajul cu care cititorul este deja obisnuit,vezi, e.g., [45, pg. 4, 5]. Eu cred ın aceasta abordare . . .

Programele care urmeaza sunt scrise folosind mediul de dezvoltare Visual Stu-

dio sub sistemul de operare Windows XP Professional SP 3, accesibil ın multe sali

de clasa ori via MSDNAA. De asemeni, ele sunt testate sub Windows 7 Profes-

sional SP 1 (x86). Mentionez ca C-ul de la Microsoft este compatibil cu editia

1990 a ANSI C, cf. [7].

Construim un director (folder) destinat viitoarelor programe C si C++,C:\ProiecteleMele_Cpp, dupa care apelam Visual Studio-ul, vezi Figura1.

Figura 1

Alegem New Project, dupa care, vezi Figura 2, ın lista Installed Tem-

plates, optam pentru Visual C++. In tabelul central, selectam Empty Pro-

ject. Numele proiectului — ın primul din campurile albe din partea dejos a ferestrei (pop-up) New Project — va fi primul_program iar pen-tru a stabili locatia acestuia ın directorul construit anterior folosim bu-tonul Browse. Ultimul camp al ferestrei New Project, si anume Solution

name (solutia. . . ), va deveni, automat, primul_program. Evident, solutia —fisierul primul_program.sln din directorul C:\ProiecteleMele_Cpp\pri

mul_program — va permite ın urma unei duble apasari pe butonul stangal mouse-ului ıncarcarea proiectului nostru ın mediul Visual Studio, indifer-ent daca acesta este ın executie sau nu. Insa aceasta numai dupa ce vom ficonstruit primul nostru proiect!

2

Page 3: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 2

Daca totul este ın ordine, apasam butonul OK, vezi Figura 2. Mai departe,ın functie de setarile mediului Visual Studio, pe ecran vor aparea diferiteferestre ın care scriem cod, respectiv sunt afisate diverse informatii, veziFigura 3. Folosind butonul View din meniul principal, putem vizualiza —daca nu au fost setate deja — ferestrele Solution Explorer, Properties,Output, Document Outline, Error List s.a.m.d. Atentie, desi ın Figura 3fereastra centrala este de culoare alba, ceea ce noi vom vedea initial va fi unspatiu de culoare albastru metalizat, ca ın centrul Figurii 4.

In acest moment, putem introduce fisierele proiectului nostru, si anumecentru.c si headerulnostru.h. Pentru aceasta, urmarind Figura 4, nepozitionam cu cursorul pe elementul Source Files al listei din fereastraSolution Explorer. Apasand butonul drept al mouse-ului, remarcam apari-tia unei noi ferestre, din care vom selecta elementul Add. Acesta, odataselectat, va face vizibila o alta fereastra, ın cadrul careia vom opta pentruelementul New Item.

Avand cursorul pozitionat pe elementul New Item, apasam butonul stangal mouse-ului, ceea ce produce aparitia ferestrei Add New Item primul_prog

ram, vezi Figura 5. Aici, selectam din tabelul central elementul C++ File(

.cpp). Urmarind Figura 5, ne deplasam ın partea de jos a ferestrei activepana la campul Name. Acesta va fi completat cu numele ıntreg al fisierului

3

Page 4: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 3

nostru, adica program.c. Atentie, daca nu scriem si particula .c, fisierulva fi salvat ca program.cpp, adica un fisier cu cod C++. La urma urmei,compilatorul cl.exe care sta ascuns sub capota mediului de dezvoltare VisualStudio este un compilator C/C++! Apoi apasam butonul Add.

Finalizarea cu succes a operatiei ne conduce la aparitia elementului program.c ın lista Source Files din fereastra Solution Explorer, vezi din nouFigura 3. Reluam procedeul, vezi Figura 4, plecand de la elementul HeaderFiles din fereastra Solution Explorer, si alegem, urmarind Figura 5, el-ementul Header File(.h) din tabelul central. Odata ıncheiat acest pas,putem practic trece la scrierea codului. . . din primul nostru proiect VisualStudio.

Pozitionand cursorul pe elementul headerulnostru.h din fereastra Solu-tion Explorer, apasam butonul stang al mouse-ului, ceea ce va produceaparitia unei zone de culoare alba ın centrul ecranului, vezi Figura 3. Inaintede a scrie primul nostru program — desigur, daca acest detaliu nu a fostınca setat —, dorim sa numerotam liniile de cod. Ne va fi mai usor astfelsa depanam (debug) programele C/C++. Pentru a activa numerotarea ıncauza, apasam butonul Tools din meniul principal al Visual Studio-ului, caın Figura 6. Din fereastra nou aparuta, selectam elementul Options.

Apasand butonul Options, producem aparitia ferestrei Options, vezi

4

Page 5: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 4

Figura 7. Aici, din lista situata ın partea stanga, ın zona de culoare alba,alegem elementul Text Editor, ceea ce va permite vizualizarea unei noiliste de optiuni. Dintre acestea, alegem elementul C/C++. In acest moment,urmarind Figura 7, putem selecta ın zona Display din partea dreapta a fere-strei active optiunea Line numbers. Pentru a salva aceasta alegere, apasambutonul OK.

Acum, revenind la campul central de culoare alba cu titlul headerulnostru.h, introducem urmatoarele linii de cod.

Un header “utilitar” ın C: headerulnostru.h

1 #i f !defined( HEADERULNOSTRU )

2 #define HEADERULNOSTRU

3 /* ---------------------*/

4

5 /* diverse headere:*/

6 #include <stdio.h>

7 #include <conio.h>

8 #include <stdlib.h>

9 #include <malloc.h>

10 #include <Windows.h>

11

5

Page 6: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 5

12 /* rutina de incheiere */

13 #undef LA_REVEDERE

14 #define LA_REVEDERE \

15 MessageBox(NULL, \

16 TEXT("\u00CEncheiem minunatul program ?\t"), \

17 TEXT("Cutie de dialog"), \

18 MBOK);

19

20 /* ---------------------*/

21 #endif

In mod identic, adaugam ın campul program.c codul sursa al programu-lui.

Primul nostru program ın VS C: program.c

1 #include "headerulnostru.h"

2

3 main(){

4 pr int f ("\nIncepem ...\n");

5 LA_REVEDERE

6 }

6

Page 7: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 6

Trebuie facut urmatorul comentariu vizavi de “ciudata” mea preferinta pen-tru un element vizual, si anume MessageBox. Programele C sunt programe “deconsola” — acel ecran negru. . .—, cu executie ıntr-un singur fir1, cf. [20, p. 2],ınsa noi ne aflam ın Windows, deci consola este numai un proces, cf. [35, p. 88,Chap. 4], denumit cmd.exe, ın cadrul caruia ne manifestam. Acest proces poate fi“vazut” cu Windows Task Manager. Atunci cand rulam un program ın consola —o instanta a cmd.exe —, acesta poate fi observat ın lista de procese afisata de TaskManager. Tehnic vorbind, a opta la punctul de intrare ıntre _tmain si _tWinMaineste o chestiune de linkare (/SUBSYSTEM:CONSOLE), vezi [35, p. 91]. De aceea,mi-am permis sa introduc o modalitate grafica de control ın cadrul programuluimeu C.

Chestiunea mai multor fire de executie — multi-threading — este ıncredintata

sistemului de operare (via functia CreateThread) ınsa se recomanda utilizarea

functiei Windows C/C++ _beginthreadex— care “stie” cum sa apeleze CreateTh-

read. . .—, vezi [35, pg. 182–183, Chap. 6].

Pentru instructiunile de preprocesor , marcate cu # ın codul sursa, amurmat recomandarile din [20, pg. 89, 90, 229]. Astfel, pentru a defini unmacro pe mai multe linii se foloseste caracterul “\”. Pentru concatenareamacrourilor, vezi pagina 162, utilizam ##.

Odata salvate fisierele din proiect — vezi butonul “cu diskete” de sub me-niul principal al VS-ului —, dorim sa le compilam. Pentru aceasta, urmarindFigura 8, utilizam butonul Debug (compilare–cu–corectura) al meniului prin-cipal. In fereastra care va aparea, raspundem la ıntrebarea “This pro-

1La fel si programele C++, vezi [41, p. 357].

7

Page 8: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 7

ject is out of date: Would you like to built it?” apasand buto-nul Yes.

Putem folosi butonul F5 pentru a comanda compilarea–cu–corectura aunui program.

Daca introducerea codului sursa a decurs fara greseli, rezultatul actiuniinoastre este asemanator situatiei din Figura 9. Dupa ce apasam butonul OK,executia programului se va ıncheia cu codul 0, vezi Figura 10.

Pentru diversele optiuni privind “lansarea oficiala” a programului (vari-anta de productie), folosim butonul Build din meniul central: Clean Solu-

tion2, Batch Build — aici apare versiunea Release —, etc.In sfarsit, primul nostru program C dezvoltat ın mediul Visual Studio este

gata. El se gaseste — primul_program.exe — ın directorul C:\ProiecteleMele_Cpp\primul_program\Debug. Il lansam ın executie apasand de douaori butonul stang al mouse-ului atunci cand cursorul este pozitionat pestemica imagine (bitmap) intitulata primul_program.exe, vezi Figura 11.

Un alt comentariu trebuie facut ın ıncheierea acestei sectiuni. In multesituatii, atunci cand dezvoltam un proiect C sub mediul Visual Studio,dorim ca, la sfarsitul executiei sale, “consola” programului sa ramana de-schisa. . . Pentru aceasta avem mai multe optiuni, printre care si introducereaunor elemente vizuale gen MessageBox. Astfel, fie apelam programul din

2In Visual C++ 2010 Express, vezi pagina 40, utilizam butonul Tools si aici optampentru Settings/Expert Settings ca sa ajungem la Clean Solution.

8

Page 9: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 8

consola — via Start/Run/cmd —, fie ınlocuim codul sursa din program.c cuurmatorul set de instructiuni.

O alta vizualizare a aplicatiei: program.c

1 #include "headerulnostru.h"

2

3 main(){

4 pr int f ("\nIncepem ...\n");

5 /* LA_REVEDERE */

6 getch (); /* din <conio.h> */

7 }

Exista opinia ca apelarea uneia dintre variantele functiei getch — o im-plementare a sa folosind getchar poate fi citita ın [20, p. 79] — pentruvizualizarea rezultatelor executiei va avea drept efect introducerea unor date“aiurea” ın sistem. Trebuie ınsa observat ca, la ıncheierea corecta a pro-cesului primul_program.exe, sistemul de operare, printre altele, va eliberamemoria folosita de firul de executie principal, cf. [35, p. 124], deci nu vor

9

Page 10: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 9

ramane date ın sistem. . .

2 Programe din “viata reala”

Imi pare mai atractiv sa ne reamintim cateva elemente ale limbajului Cprin intermediul unor programe utilitare — pe care, la o adica, sa le punem latreaba rapid! —. Aceste programe pot fi, evident, ımbunatatite; de exemplu,ele nu stiu sa revina dintr-o ıntrerupere hardware, cf. [42, p. 133].

Program:> TEX este un sistem de procesare a textelor stiintifice, cu o larga raspandire,vezi [46, 27], una dintre implementarile sale fiind platforma TEX Live, cf. [47].Codul sursa al platformei contine libraria (colectia) kpathsea, folosita d.ex.la cautarea fisierelor cu fonturi. Programul care ne intereseaza citeste primalinie dintr-un fisier text, indiferent de lungimea acesteia. Singura restrictieimediata este ca textul din fisierul ın cauza sa se ıncheie cu ENTER — ceeace pare rezonabil daca ne referim la un fisier al carui continut este un sir decaractere introduse de la tastatura. . .—.

10

Page 11: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 10

Proiectul VS linie_arbitrara, prezentat ın continuare, modifica mini-mal continutul fisierelor line.h, line.c din libraria kpathsea. El este for-mat din fisierele headerulnostru.h, linie.h, centru.c si linie.c. Fisierultext din care citim este test.txt. El trebuie introdus ın directorul C:ProiecteleMele_Cpp\linie_arbitrara\linie_arbitrara ınaintea compilarii.

Am inserat ın codul sursa al proiectului mai multe citate din documentatia

on-line a VS-ului, vezi [26]. Desi numarul de linii de cod se mareste substantial,

dat fiind ca proiectul va fi pastrat ın calculator, adaosul este justificat.

Proiectul linie_arbitrara: linie.h

1 #i f !defined ( LINIE )

2 #define LINIE

3 /* ---------------------*/

4

5 #define BLOC_DE_DATE 75

6

7 #define MODUL_DEBUG 1

11

Page 12: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 11

8 /* ---

9 Daca dorim sa dezactivam modul "debug":

10 #undef MODUL_DEBUG

11 ---*/

12

13 char * read_line(FILE *);

14

15 /* ---------------------*/

16 #endif

Proiectul linie_arbitrara: centru.c

1 #include "headerulnostru.h"

2 #include "linie.h"

3 #include <errno.h>

4

5 int main(){

6

12

Page 13: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

7 FILE *studiu = NULL;

8 char *citire = NULL;

9 errno t eroare = 0;

10

11 pr int f s ("\n+++++++\n"

12 "Urmatorul program citeste\n"

13 "linia curenta , oricat de lunga ,\n"

14 "dintr -un fisier ASCII dat.\n"

15 "+++++++\ n");

16

17 i f ( fopen s (&studiu ,"test.txt","r") != 0){

18 pr int f s ("Probleme cu cititul fisierului...");

19 }

20 e l se {

21 citire = read_line(studiu);

22 pr int f s ("\nLinia citita este:\n\n%s",citire);

23

24 i f ( f c l o s e (studiu) != 0){

25 pr int f s ("Probleme cu inchiderea fisierului...");

26 }

27 }

28

29 f ree ((void *) citire);

30 get errno (&eroare);

31 pr int f s ("\n\nEroare: %d\n",eroare);

32 citire = NULL;

33

34 LA_REVEDERE

35 return 0;

36 }

Proiectul linie_arbitrara: linie.c

1 /* ----

2 Functia "read_line", descrisa in continuare ,

3 reprezinta o mica variatie a functiei cu acelasi nume

4 din fisierul "line.c" al programului "kpathsea ".

5 (" line.c: return the next line from a file , or NULL",

6 copyright: Karl Berry , Olaf Weber)

7 "kpathsea " face parte din distributia "TeX Live"

8 a sistemului publicistic TeX.

9 ----*/

10

11 #include "headerulnostru.h"

13

Page 14: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

12 #include "linie.h"

13

14 char * read_line(FILE *fisier){

15

16 int c;

17 unsigned int limit = BLOC_DE_DATE;

18 unsigned int loc = 0;

19 char *line = NULL;

20 char *intermediar = NULL;

21

22 i f (( line = (char *) malloc(limit)) == NULL){

23 #i f defined( MODUL_DEBUG )

24 pr int f s ("Probleme de alocare a memoriei ...");

25 #endif

26 /* ---------------

27 "malloc returns a void pointer to the allocated space

28 or NULL if there is insufficient memory available."

29 "malloc sets errno to ENOMEM if a memory allocation

30 fails or if the amount of memory requested exceeds

31 _HEAP_MAXREQ."

32

33 citate de pe:

34 http:// msdn.microsoft.com/en-us/library /6ewkz86d.aspx

35 constanta "_HEAP_MAXREQ" se gaseste in "<malloc.h>"

36 ----------------*/

37 }

38 e l se {

39 while (((c = getc (fisier)) != EOF)

40 && (c != ’\n’) && (c != ’\r’)) {

41 line[loc] = c;

42 /*----

43 optiune: afisam (imediat) caracterul pe ecran...

44 _putch(c);

45 ----*/

46 loc++;

47 /* ------

48 Testam daca mai avem spatiu liber.

49 In caz contrar , adaugam spatiu.

50 -----*/

51 i f (loc == limit) {

52 limit += BLOC_DE_DATE;

53 i f (

54 (intermediar = (char *) rea l l oc ((void *)line , limit))

14

Page 15: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

55 == NULL

56 ){

57 /*----

58 "If there is not enough available memory to expand

59 the block to the given size , the original block is

60 left unchanged , and NULL is returned ."

61 "realloc sets errno to ENOMEM if the memory alloca -

62 tion fails or if the amount of memory requested

63 exceeds _HEAP_MAXREQ."

64

65 citate de pe:

66 http:// msdn.microsoft.com/en-us/library/xbebcx7d .aspx

67 ----*/

68 /*----

69 Daca suntem aici , nu am terminat de citit linia ,

70 insa nu mai putem mari memoria alocata citirii.

71 Eliberam memoria folosita pana acum si iesim...

72 ----*/

73 f ree ((void *)line);

74 line = NULL;

75 /*----

76 "is safe (throws away the pointer ’s location )."

77 citat de pe:

78 http://en.wikipedia.org/wiki/Malloc

79 ----*/

80 #i f defined( MODUL_DEBUG )

81 pr int f s ("Probleme de (re)alocare "

82 "a memoriei ...");

83 #endif

84 return NULL;

85 }

86 e l se {

87 line = intermediar;

88 }

89 }

90 }

91 i f (c == EOF) {

92 i f ( f error (fisier)){

93 /* -----

94 "To indicate a read error or end -of-file condition ,

95 getc returns EOF , and getwc returns WEOF. For getc ,

96 use ferror or feof to check for an error or for end

97 of file."

15

Page 16: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

98

99 citat de pe:

100 http:// msdn.microsoft.com/en-us/library /5231d02a.aspx

101 -----*/

102 /*----

103 Daca suntem aici , nu am terminat de citit linia ,

104 insa au aparut erori de citire. Eliberam

105 memoria folosita pana acum si iesim...

106 ----*/

107 f ree ((void *)line);

108 line = NULL;

109 #i f defined( MODUL_DEBUG )

110 pr int f s ("Probleme cu stream -ul citit...");

111 #endif

112 return NULL;

113 }

114 e l se {

115 /* -----

116 Daca suntem aici , am ajuns la capatul fisierului...

117 Ultima linie nu se poate incheia cu NEWLINE ...

118 Atentie , daca avem un fisier a carui ULTIMA LINIE

119 nu se incheie cu ENTER , functia returneaza NULL...

120 -----*/

121 f ree ((void *)line);

122 line = NULL;

123 }

124 }

125 e l se {

126 /*----

127 Daca suntem aici , caracterul din stream -ul citit

128 este fie ’\r’, adica CARRIAGE RETURN (CR), fie ’\n’,

129 adica NEWLINE (LINE FEED sau LF).

130 Niciunul nu poate fi vizualizat , deci inlocuim

131 acest caracter cu "zero".

132 ------*/

133 line[loc] = 0;

134 i f (c == ’\r’) {

135 /*----

136 Citim caracterul urmator din stream; exista macar

137 unul , caci "c != EOF".

138 ----*/

139 i f ((c = getc (fisier)) != ’\n’){

140 i f ( f error (fisier)){

16

Page 17: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

141 f ree ((void *)line);

142 line = NULL;

143 #i f defined( MODUL_DEBUG )

144 pr int f s ("Probleme 2 cu stream -ul "

145 "citit...");

146 #endif

147 return NULL;

148 }

149 e l se i f (ungetc(c,fisier) == EOF){

150 /*----

151 "If c cannot be pushed back or if no character has

152 been read , the input stream is unchanged and ungetc

153 returns EOF; ungetwc returns WEOF."

154

155 citat de pe:

156 http:// msdn.microsoft.com/en-us/library /29hykw2y.aspx

157 ----*/

158 f ree ((void *)line);

159 line = NULL;

160 #i f defined( MODUL_DEBUG )

161 pr int f s ("Probleme la refacerea "

162 "stream -ului citit...");

163 #endif

164 return NULL;

165 }

166 }

167 }

168 }

169 }

170

171 #i f defined( MODUL_DEBUG )

172 /*----

173 Afiseaza nr. de caractere citite ...

174 ----*/

175 pr int f s ("\nNr. de caractere parcurse :"

176 "\t%d\n",loc);

177 #endif

178 return line;

179 }

In cadrul proiectului linie_arbitrara, am presupus ca pentru a com-pleta fisierul test.txt nu folosim o tastatura locala, ci ne bazam doar pecaracterele ASCII — aici, un caracter (char) ınseamna un octet (byte) —,

17

Page 18: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

cf. [20, p. 36], [3]. Aceasta prezumtie este corecta atunci cand ne referim laTEX, un sistem publicistic care functioneaza pe tastaturi “limitate”. . . creandcaracterele suplimentare ca metaforme. Insa nucleul Windows NT (versiu-nile 5.1, 5.2 pentru Windows XP, respectiv 6.1 pentru Windows 7, vezi [29])foloseste sistemul Unicode (UTF16) de notare a caracterelor pentru a facefata diverselor alfabete. Fireste, putem utiliza fara probleme “literele” de unoctet lungime, caci functiile Windows vor realiza conversiile necesare ıntreUnicode si ANSI (Windows-1252, etc), ori de cate ori este necesar, cf. [35,p. 35].

Am folosit si un macro “de depanare”, MODUL_DEBUG, complementar luiNDEBUG, vezi [20, p. 254], [41, p. 750].

Program:> Ilustrez, ın traditia K&R [20, p. 9], folosirea caracterelor multi-octet prin-tr-un convertor de temperatura primitiv ın cadrul proiectului Visual Studioconvertor_FC_1. Reamintesc formulele de conversie:

(C → F ) Fahrenheit =

(

Celsius ×9

5

)

+ 32,

respectiv

(F → C) Celsius = (Fahrenheit− 32)×5

9.

Vezi si [11].In codul sursa, am utilizat o varianta “securizata” a functiei sprintf

din biblioteca C standard, cf. [20, p. 245], respectiv [35, p. 42]. Aceastase numeste StringCchPrintf, se apeleaza via <strsafe.h> si se gasesteın Windows SDK, vezi [50], care trebuie, evident, instalat ınaintea rulariiproiectului VS — ın momentul testarii, versiunea SDK-ului este 7.1 —.

Proiectul convertor_FC_1: fc1.c

1 /* ---

2 Copyright: Octavian , 2011 - -2014

3 ---*/

4

5 #define UNICODE

6 #define _UNICODE

7

8 #include <malloc.h>

9 #include <Windows.h>

10

11 /* ---

12 Putem include efectiv "<WinNT.h>" in lista

18

Page 19: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

13 headerelor (continut in "<WinDef.h>")

14 cu conditia ca "<Windows.h>" sa fie

15 inaintea sa.

16 Macro -uri:

17 -- TEXT in "<WinNT.h>"

18 -- S_OK in "<WinError .h>", "<strsafe.h>"

19 ---*/

20

21 #include <tchar.h>/* --- pt. _tmain ---*/

22 #include <strsafe.h> /* --- pt. "StringCchPrintf";

23 ne trebuie Windows SDK...

24 ---*/

25

26 void tmain(){

27

28 TCHAR sir[] = TEXT("Temperatura este: 9999 \u00B0C");

29 s i z e t lungime = countof (sir);

30 /* ---

31 in cele patru spatii ocupate de "9999"

32 introducem valoarea temperaturii...

33 ---*/

34

35 int temperatura_F = 49,

36 temperatura_C = ( int )

37 (0.556 * temperatura_F - 32);

38

39 i f (

40 StringCchPrintf(

41 sir ,

42 lungime ,

43 TEXT("Temperatura este: %d \u00B0C"),

44 temperatura_C

45 ) != S OK

46 ){

47 MessageBox(NULL,

48 TEXT("StringCchPrintf"),

49 TEXT("Probleme cu func\u01ABia:"),

50 MBOK);

51 exit (EXIT FAILURE);

52 }

53

54 MessageBox(NULL,

55 sir ,

19

Page 20: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

56 TEXT("Rezultat :"),

57 MBOK);

58 exit (EXIT SUCCESS);

59 }

60 /*----

61 Alternatively , the main and wmain functions

62 can be declared as returning void (no return

63 value). If you declare main or wmain as

64 returning void , you cannot return an exit code

65 to the parent process or operating system by

66 using a return statement. To return an exit

67 code when main or wmain is declared as void ,

68 you must use the exit function .

69

70 citat de pe:

71 http:// msdn.microsoft.com/en-us/library /6wd819wh.aspx

72 ----*/

De multe ori, atunci cand doresc sa deschid un fisier header sau sa malamuresc asupra tipului unei anumite variabile, ma pozitionez cu cursorul pemarimea respectiva (d.ex., size_t) si apas butonul drept al mouse-ului, caın Figura 12. Alegand optiunea Go To Definition, aflu detaliile ın cauza,inclusiv numele fisierului — ori DLL-ul3 — ın care acestea sunt continute.

Program:> A doua varianta a convertorului, ın proiectul convertor_FC_2, testeazadaca avem suficienta memorie pentru manipularea sirului de caractere cetrebuie afisate.

Proiectul convertor_FC_2: fc2.c

1 /* ---

2 Copyright: Octavian , 2011 - -2014

3 ---*/

4

5 #define UNICODE

6 #define _UNICODE

7

8 /* ---

9 Despre utilizarea macro -urilor

10 "UNICODE", "_UNICODE "

11 vezi

12

13 Richter , Nassare , Windows via C/C++ 5th Ed., pag. 38

14 Petzold , Programming Windows 5th Ed., pag. 32

3Abrevierea de la dynamic link library, vezi, d.ex., [2, pg. 491, 492].

20

Page 21: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 12

15 ---*/

16

17 #include <malloc.h>

18 #include <Windows.h>

19 #include <tchar.h>

20 #include <strsafe.h>

21

22 /* ---

23 lungimi

24 ---*/

25 #undef MAX_LUNGIME

26 #define MAX_LUNGIME 25

27

28 /* ---

29 un macro pentru erori:

30 ---*/

31 #undef EROARE

32 #define EROARE(text ,cod) \

33 MessageBox(NULL, \

34 TEXT(text), \

35 TEXT("Probleme cu func\u01ABia:"), \

36 MBOK); \

37 exit (cod);

38

21

Page 22: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

39 void tmain(){

40 TCHAR *sir_larg = NULL;

41 int temperatura_F = 47,

42 temperatura_C = ( int )

43 (0.556 * temperatura_F - 32);

44

45 /* ---

46 Doresc sa manipulez sirul:

47 "Temperatura este: [maxim 4 cifre] 0C".

48 Avem 25 de caractere , pe care le rotunjesc

49 la 30, caci un sir TEXT(...) nu se termina

50 obligatoriu cu ’\0’...

51

52 Vezi si:

53 http:// msdn.microsoft.com/en-us/library/dd374116 .ց

(cont.) aspx

54

55 sau Petzold , pag. 23

56 ---*/

57 i f (

58 (sir_larg = (TCHAR *) malloc(

59 (MAX_LUNGIME+5) * s i z eo f (TCHAR)

60 )

61 ) == NULL

62 ){

63 EROARE("malloc",EXIT FAILURE)

64 }

65

66 /* ---

67 trunchiem sirul sir_larg si copiem ceva in el...

68 ---*/

69 i f (

70 StringCchPrintf(sir_larg ,

71 ( s i z e t )MAX_LUNGIME ,

72 TEXT("Temperatura este: %d \u00B0C"),

73 temperatura_C

74 ) != S OK

75 ){

76 f ree ((void *) sir_larg );

77 sir_larg = NULL;

78 EROARE("StringCchPrintf",EXIT FAILURE)

79 }

80

22

Page 23: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

81 MessageBox(NULL,

82 sir_larg ,

83 TEXT("Cutie de dialog:"),

84 MBOK);

85 f ree ((void *) sir_larg);

86 sir_larg = NULL;

87 exit (EXIT SUCCESS);

88 }

Program:> Revenind la “literele” de un octet lungime (char), formulez urmatoareaproblema a convertorului de temperatura: dorim sa citim gradele Fahren-heit (numar real) ıntr-un sir care cuprinde caracterele4

“ -”, “,”, “ ” (spatiu gol) si “ C”.

De exemplu, temperatura ın Bucuresti, la statia Baneasa, este:

32,5 C

Solutia data problemei, ın cadrul proiectului VS convertor_FC_3, pre-supune implementarea a doua functii: functia de conversie “(cifra) −→ (cara-cter)”, numita simbol, si functia de transformare “(numar real) −→ (sir decaractere)”, numita populare.

Se cuvine sa reamintim cateva chestiuni. In primul rand, o data de tipulchar este, practic, un numar ıntreg mic, cf. [20, pg. 42, 36], — deci aresens operatia 25 -’g’, cu rezultatul -78 — . De asemeni, literele ’a’, ’b’,’c’, etc. formeaza un bloc continuu (contiguu) ın setul de caractere ASCII.Acest lucru se poate schimba pentru alte seturi de caractere, deci dorim ofunctie simbol independenta de pozitia caracterelor ın set. D.ex., functiiledin <ctype.h> sunt independente de setul de caractere, vezi [20, p. 43]. Adoua chestiune se refera la precizia rezultatului afisat. Se stie ca, atunci candoperam cu numere reale, functiile de conversie realizeaza trunchieri/rotunjiriale datelor, pe care dorim sa le controlam, vezi [20, p. 45] pentru operatoriide conversie, respectiv [20, pg. 9, 15] pentru doua variante ale convertoruluide temperatura. De acest control va raspunde functia populare.

Proiectul convertor_FC_3: program.c

1 #include "headerulnostru.h"

2 #include "convertor.h"

3 #include <errno.h>

4Atentie, am folosit ghilimelele ın sens literar, si nu. . . informatic. Astfel, ın interiorulunui program, "C" desemneza un sir constant , adica un array terminat ın ’\0’, cf. [20,p. 104].

23

Page 24: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

4

5 main(){

6 double fahrenheit = 126.2,

7 celsius = (fahrenheit - 32)*5/9;

8 char *citire = NULL;

9 errno t eroare = 0;

10 pr int f s ("\n%7.3f\n",celsius);

11 /*---

12 7: numar minim de caractere afisate;

13 3: numar de zecimale afisate ,

14 vezi Jamsa & Klander , pag. 72, Sect. 68

15 ---*/

16 citire = populare(celsius);

17 pr int f s ("\n%s\n",citire);

18 /*---

19 curat memoria ...

20 testez daca am reusit ...

21 ---*/

22 f ree ((void *) citire);

23 get errno (&eroare);

24 pr int f s ("\n\nEroare: %d\n",eroare);

25 citire = NULL;

26 LA_REVEDERE

27 }

Proiectul convertor_FC_3: convertor.h

1 #i f !defined ( CONVERTOR )

2 #define CONVERTOR

3

4 #undef MODUL_DEBUG

5 #define MODUL_DEBUG 1

6

7 #undef LUNGIME

8 #define LUNGIME 8

9 /* ---

10 numar maxim de caractere:

11 [minus][ zeci][unitati ][ virgula ][zecimala ][ spatiu][C][ց

(cont.) incheiere]

12 ---*/

13 #undef CELSIUS_MIN

14 #define CELSIUS_MIN -99

15 #undef CELSIUS_MAX

16 #define CELSIUS_MAX 99

24

Page 25: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

17

18 char simbol( int );

19 char * populare(double);

20

21 #endif

Proiectul convertor_FC_3: simbol.c

1 #include "headerulnostru.h"

2 #include "convertor.h"

3

4 char simbol( int cifra){

5 char rezultat ;

6 switch(cifra){

7 case 0: return (rezultat = ’0’);

8 case 1: return (rezultat = ’1’);

9 case 2: return (rezultat = ’2’);

10 case 3: return (rezultat = ’3’);

11 case 4: return (rezultat = ’4’);

12 case 5: return (rezultat = ’5’);

13 case 6: return (rezultat = ’6’);

14 case 7: return (rezultat = ’7’);

15 case 8: return (rezultat = ’8’);

16 case 9: return (rezultat = ’9’);

17 case 10: return (rezultat = ’-’);

18 case 11: return (rezultat = ’,’);

19 default: return (rezultat = ’?’);

20 }

21 }

Proiectul convertor_FC_3: populare.c

1 #include "headerulnostru.h"

2 #include "convertor.h"

3

4 char * populare(double celsius){

5 char *sir = NULL;

6 int contor = 0, iterator = 0;

7 enum adevar { DA, NU } pozitiv = DA;

8

9 /*---

10 testarea limitelor CELSIUS:

11 ---*/

12 i f (( celsius < CELSIUS_MIN)

13 || (celsius > CELSIUS_MAX)){

25

Page 26: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

14 pr int f s ("Date de intrare "

15 "incorecte...");

16 return NULL;

17 }

18

19 i f ((sir = (char *)malloc(

20 LUNGIME * s i z eo f (char)

21 )) == NULL){

22 pr int f s ("Eroare la alocare ...");

23 return NULL;

24 }

25

26 /*---

27 testarea valorilor negative pentru CELSIUS:

28 ---*/

29 i f (celsius < 0){

30 celsius = -celsius;

31 sir[contor ++] = simbol (10);

32 /* afisam "-" */

33 pozitiv = NU;

34 }

35

36 /*---

37 depistam cifra zecilor in CELSIUS:

38 ---*/

39 for (iterator = 10; iterator <= 100; iterator += 10){

40 i f (( celsius - iterator + 10 >= 0)

41 && (celsius - iterator < 0)){

42 sir[contor++] = simbol(( iterator - 10) /10);

43 celsius += - iterator + 10;

44 }

45 }

46

47 /*---

48 depistam cifra unitatilor in CELSIUS:

49 ---*/

50 for (iterator = 1; iterator <= 10; iterator ++){

51 i f (( celsius - iterator + 1 >= 0)

52 && (celsius - iterator < 0)){

53 sir[contor++] = simbol(iterator - 1);

54 celsius += - iterator + 1;

55 }

56 }

26

Page 27: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

57

58 /*---

59 afisam virgula:

60 ---*/

61 sir[contor ++] = simbol (11);

62

63 /*---

64 depistam prima zecimala in CELSIUS:

65 ---*/

66 celsius *= 10;

67 /*trecem zecimala in stanga virgulei */

68 for (iterator = 1; iterator <= 10; iterator ++){

69 i f (( celsius - iterator + 1 >= 0)

70 && (celsius - iterator < 0)){

71 sir[contor++] = simbol(iterator - 1);

72 }

73 }

74

75 /*---

76 afisam " C" la sfarsitul sirului:

77 ---*/

78 sir[contor ++] = ’ ’;

79 sir[contor ++] = ’C’;

80

81 /*---

82 numere pozitive : compensam lipsa lui "-"

83 cu un spatiu gol la final...

84 ---*/

85 i f (pozitiv == DA){

86 sir[contor++] = ’ ’;

87 }

88

89 /*---

90 sirul se termina in null...

91 ---*/

92 sir[contor] = ’\0’;

93

94 /*---

95 comparam valoarea contorului cu LUNGIME:

96 ---*/

97 i f (contor > LUNGIME){

98 f ree ((void *)sir);

99 sir = NULL;

27

Page 28: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

100 pr int f s ("Probleme cu "

101 "lungimea sirului ...");

102 return NULL;

103 }

104

105 /*---

106 dezactivare DEBUG:

107 #undef MODUL_DEBUG

108 ---*/

109

110 #i f defined ( MODUL_DEBUG )

111 pr int f ("\n\n++++\n%d\n++++\n",contor);

112 #endif

113 return sir;

114 }

“Inversa” functiei populare, si anume “(sir de caractere)−→(numar re-al)” este atof din <stdlib.h>. O implementare a sa se gaseste ın [20, p.71].

3 Alte programe5 ın C

Lista functiilor CRT (libraria run-time a limbajului C) se gaseste la adresa[12] pe platforma MSDN.

Cand pornim un program scris ın limbajul C, vezi [20, pag. 161], sistemulde operare va deschide trei fisiere — intitulate intrarea standard , iesirea stan-dard , respectiv eroarea standard — si ıi va transmite programului pointeri(date de tipul FILE *) la acestea: stdin, stdout si stderr. Pointerii ın cau-za sunt declarati ın <stdio.h>. In mod obisnuit, stdin se refera la tastatura,iar stdout si stderr la ecranului calculatorului. Intrarile si/sau iesirile potfi ınsa redirectionate6.

Program:> Asa cum stim, datele introduse de la tastatura sunt caractere ASCII, vezi[18, p. 137, Sect. 161; p. 515, Sect. 679]. Ceea ce ınseamna ca programul C“vede” intrarile noastre drept siruri de caractere. Urmatorul program preiacinci caractere de la tastatura7 si le afiseaza pe ecran.

Citeste cinci caractere: caract_1.c

1 /* ---

2 citeste cinci caractere de la tastatura

5O recapitulare. . . pe sarite.6In limba engleza, pipe.7Fara taste speciale sau combinatii de taste (d.ex., CTRL + C).

28

Page 29: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

3 si apoi le afiseaza : o parola

4 ---*/

5

6 #include "headerulnostru.h"

7 /* ---

8 <conio.h>: pentru _getch , _putch

9 <stdlib.h>: pentru system

10 ---*/

11 #undef TESTARE

12 #define TESTARE 1

13

14 int main(void){

15 int litera ,

16 contor = 1;

17 #i fd e f TESTARE

18 char * tipar();

19 #endif

20

21 system("cls");

22 pr int f s ("\nTastati parola:\n");

23 for (; contor++ <= 5;){

24 litera = getch ();

25 putch(litera);

26 #i fd e f TESTARE

27 pr int f s ("%scontor :\t%d%s",

28 tipar(/* --- 9 ---*/),

29 contor ,

30 tipar(/* --- 10,"test" ---*/));

31 #endif

32 }

33 LA_REVEDERE

34 return 0;

35 }

36

37 #i fd e f TESTARE

38 char * tipar(){

39 return "\n+++ Testare !+++\n";

40 }

41 #endif

Am folosit void ın locul listei de argumente din functia main. Reamin-tesc faptul ca, pentru a asigura compilatorul ca o functie nu are argumente,se recomanda declaratia nume_functie(void). Cealalta varianta, si anumenume_functie(), nu implica inexistenta argumentelor, ci dezactiveaza veri-

29

Page 30: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

ficarea listei acestora, cf. [20, p. 33]. Compilatorul din Visual Studio poate

emite un avertisment (Warning: too many arguments in function call), da-

ca folosim argumentele 9, respectiv 10,"test" ın apelul functiei tipar.

Program:> Functia tipar din proiectul anterior ignora parametrii dati de noi. Inprogramul de mai jos, vom ilustra o situatie aflata “la polul opus”, si anumefunctia sumare, care tine seama de un numar variabil de parametri. In de-claratia sa, folosim obligatoriu cel putin un argument obisnuit iar la finalelipsa8, “. . . ”, pentru a ne referi la argumentele ın numar variabil, vezi [20,p. 155]. Pentru a implementa functia sumare — care returneaza suma unuinumar variabil de numere, respectand formatul acestora (int, double) —,folosim tipul de date va_list — adica, char * — definit ın <vadefs.h>,respectiv macrourile va_start, va_arg si va_end din <stdarg.h>.

Ilustrarea elipsei: elli0.c

1 #include "headerulnostru.h"

2 #include <stdarg.h>

3 /* ---

4 pt. va_start , va_arg , va_end;

5 in <vadefs.h>, inclus , se gaseste va_list

6 ---*/

7 /* ---

8 pre -ANSI: <varargs.h>, actual "deprecated".

9 Acest header este folosit inca pentru compatibilitate

10 cu sistemele UNIX V, vezi:

11 http:// msdn.microsoft.com/en-us/library/kb57fad8 .aspx

12 http:// msdn.microsoft.com/en-us/library/we9107a3 .aspx

13 ---*/

14

15

16 #undef DEBUG

17 #define DEBUG 1

18 #undef ERORI

19 #define ERORI(texta ,textb ,textc) \

20 pr int f s ("\nEroare de format!\n" \

21 "Grupuri corecte: %d\n", \

22 texta); \

23 pr int f s ("Suma este , pana aici: %f\n", \

24 textb); \

25 pr int f s (textc);

26

27

8In limba engleza, ellipsis .

30

Page 31: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

28 typedef enum valori {NUMAR , EROARE} controlul_erorii;

29

30 int main(){

31 controlul_erorii sumare(char *, ...);

32

33 /*---

34 sumam primele patru numere din lista de intrari ,

35 conform formatului lor:

36 "%d" --- numar intreg ,

37 "%f" --- numar cu virgula (double)

38 ---*/

39 sumare("%f%d%d%d" ,23.0,2,-100,4,"altceva" , -400.67);

40

41 /*---

42 recomandare MSDN:

43 folosirea operatorilor de cast pentru un format corect

44 ---*/

45 sumare("%d%f",( int )23.67, -0.5);

46

47 LA_REVEDERE

48 return 0;

49 }

50

51 controlul_erorii sumare(char *format , ...){

52 char *sir = format;

53 /*---

54 date pentru controlul formatului

55 ---*/

56 int contor_procent = 0,

57 contor_intreg = 0,

58 contor_real = 0,

59 contor_grup = 0;

60 double suma = 0.0;

61

62 /*---

63 introducem un pointer (char *)

64 la sirul argumentelor in numar variabil ,

65 si il pozitionam la primul dintre acestea

66 ---*/

67 va l i s t argumente_fara_nume;

68 va start (argumente_fara_nume ,format);

69

70 /*---

31

Page 32: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

71 analiza formatului

72 ---*/

73 for (;*sir != ’\0’;){

74 i f (*sir++ != ’%’){

75 #i fd e f DEBUG

76 ERORI(contor_grup ,suma ,

77 "Grupul nu incepe cu \"%%\"...")

78 #endif

79 /*---

80 eliberam pointerul la sirul argumentelor

81 ---*/

82 va end(argumente_fara_nume);

83 return EROARE;

84 }

85 i f (*sir == ’d’){

86 contor_intreg++;

87 suma += va arg(argumente_fara_nume , int );

88 }

89 i f (*sir++ == ’f’){

90 contor_real++;

91 suma += va arg(argumente_fara_nume ,double);

92 }

93 contor_grup++;

94

95 /* ---

96 daca apare alta litera dupa %

97 ---*/

98 i f (

99 contor_grup != (contor_intreg + contor_real)

100 ){

101 #i fd e f DEBUG

102 ERORI(contor_grup -1,suma ,

103 "Grupul nu contine: d, f ...")

104 #endif

105 va end(argumente_fara_nume);

106 return EROARE;

107 }

108 }

109 #i fd e f DEBUG

110 pr int f s ("\nStatistici:\n"

111 "grupuri \"%%d\" %d\n"

112 "grupuri \"%%f\" %d\n",

113 contor_intreg ,contor_real);

32

Page 33: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

114 #endif

115 pr int f s ("\nSuma este: %f\n",suma);

116 va end(argumente_fara_nume);

117 return NUMAR;

118 }

Program:> Urmatorul program manipuleaza diferentiat caracterele scrise ın consola:daca ıntalneste litera “z”, programul va trece pe randul urmator, iar dacaapasam ENTER executia se opreste. Vezi [18, p. 226; Sect. 294].

Citire diferentiata: caract_2.c

1 /* ---

2 citeste caracterele de la tastatura ,

3 daca intalneste "z"-ul, trece pe un rand nou

4 iar daca apasam ENTER se opreste

5 ---*/

6 #include "headerulnostru.h"

7

8 int main(void)

9 {

10 int litera;

11 system("cls");

12 do{

13 litera = getch();

14 i f (litera != ’z’)

15 putch(litera);

16 e l se

17 pr int f s ("\n");

18 }

19 while (litera != ’\r’);

20 LA_REVEDERE

21 return 0;

22 }

Program:> Afisarea caracterelor “speciale” se face ın limbajul C cu ajutorul carac-terului escape “\”. Programul care urmeaza contine caracterele: “\n” – linienoua, “\t” – tabulator orizontal, “\r” – returnare de car, “\"” – apostrof,“\\” – backslash, “\?” – semnul ıntrebarii. Vezi si [18, p. 75; Sect. 74].

Caractere cu escape: caract_3.c

1 /* ---

2 caractere speciale in C (cu escape)

3 ---*/

4

33

Page 34: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

5 #include "headerulnostru.h"

6

7 int main(void){

8 int numar = pr int f s ("as\nft\tfds\t\\\ns\nd\?\"sss"

9 "ss\nwerfggggu\ryyy\n");

10 pr int f s ("\nSirul are %d caractere.",numar);

11 LA_REVEDERE

12 return 0;

13 }

Program:> Importanta caracterului escape este relevata de un program care realizeazaurmatoarele sarcini: (i) creaza directorul C:\Diverse Programe ın sistemulde fisiere; (ii) creaza/verifica daca exista fisierul incercare.txt ın folderulC:\ProiecteleMele_Cpp\nume_proiect\nume_proiect; (iii) copiaza acestfisier ın noul director; (iv) introduce ın copie litera “D”. De asemeni, pen-tru un mai bun control vizual al erorilor, am utilizat functia GetACP din<WinNls.h>. Aceasta ne da informatii despre setul de caractere specialedisponibil ın calculator.

Introducerea unui fisier ın sistem: man_fis00.c

1 #define UNICODE

2 #define _UNICODE

3

4 #include "headerulnostru.h"

5

6 /* ---

7 macrouri de eroare , avertizare:

8 ---*/

9 #undef EROARE

10 #define EROARE(text ,cod) \

11 MessageBox(NULL, \

12 TEXT(text), \

13 TEXT("Mesaj de eroare:"), \

14 MBOK); \

15 exit (cod);

16 #undef MESAJ

17 #define MESAJ(text) \

18 MessageBox(NULL, \

19 TEXT(text), \

20 TEXT("Cutie de dialog"), \

21 MBOK);

22

23 /* ---

24 versiunea OS:

34

Page 35: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

25 WX: Windows XP SP3 (Windows -1252 code page)

26 W7: Windows 7 SP1 (Windows -1250 code page)

27 ---*/

28 #undef WX

29 #define WX 1

30

31 #undef W7

32

33 int main(void)

34 {

35 FILE *fisier = NULL;

36

37 /*---

38 construiesc directorul

39 ---*/

40 system("cls & "

41 "mkdir \"C:\\ Diverse Programe \"");

42 #i fd e f WX

43 MESAJ("F\u00E3cut!")

44 #endif

45 #i fd e f W7

46 MESAJ("F\u0103cut!")

47 #endif

48 {

49 /*---

50 Atentie la codurile de pagina Windows (pt. caractere):

51 http:// msdn.microsoft.com/en-us/library/dd317752 .aspx

52 ---*/

53 # include <WinNls.h>

54 pr int f s ("\n\nCodul paginii este: %d\n\n",

55 ( int ) GetACP());

56 }

57

58 /*---

59 testez fisierul "incercare.txt"

60 ---*/

61 i f ( fopen s (&fisier ,"incercare.txt","a+") != 0){

62 EROARE("Eroare la deschidere \" incercare.txt\"!\n",

63 EXIT FAILURE)

64 }

65 i f ( f c l o s e (fisier) != 0){

66 EROARE("Eroare la inchidere \" incercare.txt\"!",

67 EXIT FAILURE)

35

Page 36: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

68 }

69

70 /*---

71 copiez fisierul

72 ---*/

73 system(

74 "copy incercare.txt /A \"C:\\ Diverse Programe \" /A"

75 );

76

77 /*---

78 inserez caracterul "D"

79 ---*/

80 i f ( fopen s (&fisier ,

81 "C:\\ Diverse Programe \\ incercare.txt","a+") != 0){

82 EROARE("Eroare la creare/deschidere!\n",

83 EXIT FAILURE)

84 }

85 fputc(’D’,fisier);

86 i f ( f c l o s e (fisier) != 0){

87 EROARE("Eroare la inchidere!",EXIT FAILURE)

88 }

89

90 LA_REVEDERE

91 return 0;

92 }

Sa presupunem ca avem deja cateva programe scrise ın limbajul C. Inmulte cazuri, dorim sa rulam aceste programe din afara consolei . Reamintesc

faptul ca, tastand grupul de comenzi ALT + ENTER, consola activa se va ıntinde

ın 1-2 secunde la ıntreg ecranul calculatorului. Consola va reveni la dimensiunile

obisnuite daca repetam grupul de comenzi.

Program:> In programul urmator, folosim cateva functii Windows dedicate consolei,cf. [10], pentru a interactiona cu aceasta. In sistemele de operare Windows,

consola reprezinta numai un proces, adica o instanta a unui program ın executie

formata dintr-un obiect-nucleu si un spatiu de adrese, vezi [35, p. 88, Chap. 4].

Schimbarea titlului consolei: consola00.c

1 /* ---

2 Copyright: Octavian , 2011 - -2014

3 ---*/

4

5 #include "headerulnostru.h"

6

36

Page 37: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

7 /* ---

8 lungimea unui sir de caractere

9 ---*/

10 #undef MARIME

11 #define MARIME 300

12

13 /* ---

14 macrouri de eroare , memorie:

15 ---*/

16 #undef EROARE

17 #define EROARE(text) \

18 pr int f s (text); \

19 LA_REVEDERE \

20 exit (EXIT FAILURE);

21 #undef LIBER

22 #define LIBER(nume) \

23 f ree ((void *)nume); \

24 nume = NULL;

25

26 int main(){

27 int litere ,

28 contor = 0;

29 char *titlu_vechi = NULL,

30 *titlu_nou = "Consola de lucru";

31 /* ---

32 date de tip Windows

33 ---*/

34 DWORD cat_am_scris = 10000L;

35 HANDLE maner = NULL;

36

37 /*---

38 aloc spatiu pentru citit titlul consolei

39 ---*/

40 i f (

41 (titlu_vechi =

42 (char *) malloc(MARIME * s i z eo f (char))) == NULL

43 ){

44 EROARE("Probleme de alocare ...")

45 }

46

47 /*---

48 caut consola in registru ...

49 ---*/

37

Page 38: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

50 i f (

51 ((maner = GetStdHandle(STDOUTPUTHANDLE))

52 == INVALIDHANDLEVALUE)

53 /* --- functie din <WinBase.h> ---*/

54 || (maner == NULL)

55 ){

56 LIBER(titlu_vechi)

57 EROARE("Probleme de maner...")

58 }

59

60 system("cls");

61 /*---

62 citesc , modific titlul consolei

63 cu functii din <WinCon.h>

64 ---*/

65 i f (!GetConsoleTitleA ((LPSTR) titlu_vechi ,

66 (DWORD) MARIME * s i z eo f (char) -1)

67 ){

68 LIBER(titlu_vechi)

69 EROARE("Probleme de citit titlul ...")

70 }

71 pr int f s ("\n\nVechiul titlu al consolei este:\n"

72 "\"%s\""

73 "\n\nNoul titlu al consolei este:\n",

74 titlu_vechi);

75 i f (!SetConsoleTitleA(titlu_nou)){

76 LIBER(titlu_vechi)

77 EROARE("Probleme de resetare a titlului ...")

78 }

79

80 /*---

81 scriu in consola cu o functie Windows

82 ---*/

83 i f (!WriteConsoleA(maner ,

84 (const void *)titlu_nou ,

85 (DWORD) countof ("Consola de lucru"),

86 &cat_am_scris ,

87 NULL)

88 ){

89 LIBER(titlu_vechi)

90 EROARE("Probleme de scriere ...")

91 }

92

38

Page 39: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

93 pr int f s ("\n\n+++++++\ n"

94 "Adaugati trei litere:\n\n");

95 for (;

96 contor++ <= 2;

97 litere = getch(), putch(’\n’), putch(litere)

98 );

99

100 LIBER(titlu_vechi)

101

102 LA_REVEDERE

103 return 0;

104 }

Program:> O metoda simpla de rulare, indepedent de consola, a unor programe ex-ecutabile — nume_program.exe — consta ın utilizarea unor fisiere batch(de comenzi), cf. [4], — comenzi.bat —. Presupunand ca, ın directorulC:\Proiectele Mele_Cpp, aducem fisierul caract_3.exe, vezi pagina 33,extras din subdirectorul Debug al proiectului VS respectiv, scriptul batch demai jos — salvat temporar pe ecranul calculatorului, C:\Documents and Set

tings\Octavian\Desktop — ıi comanda executia.

Controlul executiei: nume_program.bat

1 @echo o f f

2 set cale_fisiere=C:\ProiecteleMele_Cpp

3 cd %cale_fisiere%

4 nume_program.exe

5 :: inlocuim "nume_program" cu "caract_3 "

6 :: avem si comanda alternativa:

7 :: start /wait /b nume_program.exe

8 :: vezi http://ss64.com/nt/start.html

9 ca l l cmd

10 :: ramane consola deschisa

11 ::se tasteaza "exit" pt. iesire

Program:> Rezultatul executiei programului caract_3.exe poate fi redirectat catreun fisier, d.ex. rezultat_caract_3.txt, din acelasi director, folosind oper-atorul “>”. Vezi [20, p. 152].

Redirectarea rezultatului: caract_31.bat

1 @echo o f f

2 set cale_fisiere=C:\ProiecteleMele_Cpp

3 cd %cale_fisiere%

4 caract_3.exe > rezultat_caract_3.txt

5 notepad rezultat_caract_3.txt

39

Page 40: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

6 ca l l cmd

7 ::se tasteaza "exit" pt. iesire

Program:> Un exemplu mai elaborat este scriptul batch prin intermediul caruia putemutiliza programul Microsoft Visual C++ 2010 Express (VC++) — gratuit,distribuit independent de VS, cf. [49] —

Codul sursa pentru batch-ul VC++

1 @echo o f f

2 :: variabile pentru VC++ si cmd

3 set cale_principala=C:\Program Files

4 set versiune =\ Microsoft Visual Studio 10.0

5 set drum_exec=\ Common7\IDE

6 set cale_vis=%cale_principala%%versiune%%drum_exec%

7 set help_vis_cont=/en-us/library/60k1461a.aspx

8 set help_vis=http://msdn.microsoft.com%help_vis_cont%

9 set cale_browser=C:\Program Files\Mozilla Firefox

10 set consola=C:\WINDOWS\system32

11 :: sfarsit variabile

12 :: folderul de proiecte

13 echo.

14 set cale_fisiere=C:\ProiecteleMele_Cpp

15 set treaba=mkdir %cale_fisiere%

16 set mesaj=Creat folderul de proiecte "ց

(cont.) ProiecteleMele_Cpp"!

17 i f not exist %cale_fisiere% (%treaba% & echo %mesaj%)

18 :: sfarsit operatii folderul de proiecte

19 chdir %cale_fisiere%

20 start explorer %cale_fisiere%

21 path=%path%;%consola%;%cale_vis%;%cale_browser%

22 echo.

23 echo Pentru Visual C++ Express , tastati: VCExpress

24 echo.

25 echo Pentrul "aplicatiile de consola", folositi ց

(cont.) comanda:

26 echo "cd.\ NumeleProiectului\Debug", dati "Enter" si ց

(cont.) apoi

27 echo tastati: "NumeleProiectului.exe". Pentru a reveni

28 echo la folderul de proiecte , tastati:

29 echo "cd.. & cd..".

30 echo.

31 echo Succes!

32 start firefox %help_vis%

33 echo. & ca l l cmd

40

Page 41: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Program:> Putem rula fisierul caract_31.bat, vezi pagina 39, si dintr-un proiect VS.Astfel, presupunand ca avem proiectul gol octombrie_31_2011 ın directorulde lucru, introducem ın subdirectorul cu acelasi nume fisierele caract_31

.bat si caract_3.exe — calea completa pana la fisiere trebuie sa fie C:\ProiecteleMele_Cpp\octombrie_31_2011\octombrie_31_2011 — . Codul ınlimbajul C de care avem nevoie este listat ın continuare.

Fisiere de comenzi: consola01.c

1 #include "headerulnostru.h"

2

3 int main(void){

4 system("caract_31.bat");

5 LA_REVEDERE

6 return 0;

7 }

Motivatia proiectului anterior este urmatoarea: atunci cand dorim intrarea ın

executie, ıntr-o ordine prestabila, a mai multor fisiere executabile, putem folosi

aceasta cale mixta pentru a evita complicatiile procese-parinte – procese-copil ori

introducerea mai multor fire de executie, vezi [35], [18, p. 561].

Program:> Functia system din <stdlib.h> transmite, asadar, linia de comanda aunui proces catre interpretorul cmd.exe, cf. [8]. Aici, trebuie sa avem grijala modul cum sunt procesate caracterele “speciale” — parsarea argumentelorunei comenzi, tokenizarea lor —. In programul urmator, folosim secventele“\"”, respectiv “^&” pentru o transmitere corecta a acestor argumente.

Linia de comanda: consola02.c

1 #include "headerulnostru.h"

2

3 int main(void){

4 pr int f s ("\nDe dimineata...\n"

5 "Ziare locale si nationale ,\n"

6 "schimb valutar ...\n");

7 system("\"C:\\ Program Files\\Mozilla Firefox"

8 "\\ firefox.exe\""

9 " http://www.gds.ro"

10 " http://www.romanialibera.ro"

11 " http://www.xe.com/currencycharts/"

12 "?from=EUR^&to=USD^&view=1D");

13

14 LA_REVEDERE

15 return 0;

16 }

41

Page 42: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Program:> Functia Windows GetCommandLineW din <WinBase.h> ıntoarce un pointerla bufferul ce contine ıntreaga linie de comanda, cf. [35, p. 97; Chap. 4].Vezi codul C urmator.

Linia de comanda: consola03.c

1 #define UNICODE

2 #define _UNICODE

3 #include "headerulnostru.h"

4

5 int main(void){

6 PWSTR linia_de_comanda = GetCommandLineW();

7 /*---

8 din <WinBase.h>

9 ---*/

10 MessageBox(NULL,linia_de_comanda ,

11 TEXT("Rezultat :"),MBOK);

12 LA_REVEDERE

13 return 0;

14 }

Program:> Urmatorul proiect se ocupa de cautarea unor cuvinte ıntr-un dictionar on-line al limbii romane. Acestea sunt precizate ın linia de comanda, cu careprogramul interactioneaza prin intermediul functiei main, cf. [20, p. 114],[18, p. 510; Sect. 669]. Rutinele din program pot fi realizate si cu functii din<string.h>, d.ex. strcat_s, strncat_s.

Linia de comanda: consola04.c

1 /* ---

2 Un program primitiv de cautare

3 in dictionarul on-line al limbii romane:

4 http:// dexonline.ro

5 -------------------

6 sintaxa:

7 consola04 [cuvant]

8 -------------------

9 Termenul [cuvant] este optional .

10 Cuvantul cautat poate avea <= 40 litere.

11 ---*/

12

13 #undef COMANDA_MAXIMA

14 #define COMANDA_MAXIMA 155

15 #undef COMANDA_REZERVA

16 #define COMANDA_REZERVA 77

17 #undef SPATII_GOALE

42

Page 43: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 #define SPATII_GOALE 40

19

20 /* ---

21 macrouri debugging:

22 ---*/

23 #undef DEBUG

24 #define DEBUG 1

25 /* #undef DEBUG */

26 #undef EROARE_A

27 #define EROARE_A (text) \

28 pr int f s (text); \

29 exit (EXIT FAILURE);

30 #undef EROARE

31 #define EROARE(text ,pointer) \

32 pr int f s (text); \

33 f ree ((void *) pointer); \

34 pointer = NULL; \

35 exit (EXIT FAILURE);

36 #undef SUCCES

37 #define SUCCES(pointer) \

38 LA_REVEDERE \

39 f ree ((void *) pointer); \

40 pointer = NULL; \

41 exit (EXIT SUCCESS);

42

43 #include "headerulnostru.h"

44

45 void main( int argc , char *argv[])

46 {

47 char *comanda_baza = "\"C:\\ Program Files\\ Mozilla ց

(cont.) Firefox \\firefox.exe\" http:// dexonline.ro/",

48 *supliment = "definitie/",

49 *buffer = NULL,

50 *citirea_cuvantului = "standard ";

51 int contor = 0,

52 iterator = 0;

53

54 i f (

55 COMANDA_MAXIMA <= (COMANDA_REZERVA + SPATII_GOALE)

56 ){

57 #i fd e f DEBUG

58 EROARE_A("\nEroare setari!")

59 #else

43

Page 44: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

60 EROARE_A(" ")

61 #endif

62 }

63

64 /*---

65 rezervam memorie pentru linia de comanda "buffer":

66 ---*/

67 i f (

68 (buffer = (char *) ca l l oc (COMANDA_MAXIMA , s i z eo f (char)))

69 == NULL

70 ){

71 #i fd e f DEBUG

72 EROARE_A("\nEroare memorie!")

73 #else

74 EROARE_A(" ")

75 #endif

76 }

77

78 /*---

79 organizarea liniei de comanda:

80 ---*/

81 for (;* comanda_baza != ’\0’;){

82 buffer[contor++] = *comanda_baza++;

83 }

84 #i fd e f DEBUG

85 pr int f s ("contor 1: %d\n",contor);

86 #endif

87

88 for (;* supliment != ’\0’;){

89 buffer[contor++] = *supliment++;

90 }

91 #i fd e f DEBUG

92 pr int f s ("contor 2: %d |%c|\n",

93 contor ,buffer[contor -1]);

94 #endif

95 i f (COMANDA_REZERVA != contor){

96 #i fd e f DEBUG

97 EROARE("\nProbleme de iterare ...",buffer)

98 #else

99 EROARE(" ",buffer)

100 #endif

101 }

102

44

Page 45: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

103 /*---

104 adaugam SPATII_GOALE spatii goale...

105 aici va fi copiat cuvantul ce trebuie

106 cautat in dictionar

107 ---*/

108 for (; iterator <= SPATII_GOALE -1; iterator ++){

109 buffer[contor++] = ’ ’;

110 }

111 buffer[contor] = ’\0’;

112 #i fd e f DEBUG

113 pr int f s ("contor 3: %d %d |%c|\n",

114 contor ,iterator ,buffer[contor -1]);

115 #endif

116

117 /*---

118 linia de comanda poate primi argumentul optional

119 ---*/

120 i f (argc == 1){

121 /* ---

122 in lipsa unui cuvant in linia de comanda (default),

123 cautam cuvantul "standard ":

124 ---*/

125 for (contor = 0; contor <= countof("standard ");){

126 buffer[COMANDA_REZERVA + contor ++]

127 = *citirea_cuvantului++;

128 }

129 i f (

130 pr int f s ("\nAdresa standard :\n%s\n",buffer) < 0

131 ){

132 #i fd e f DEBUG

133 EROARE("\nNu pot afisa adresa standard ...",buffer)

134 #else

135 EROARE(" ",buffer)

136 #endif

137 }

138 system(buffer);

139 SUCCES(buffer)

140 }

141 /*---

142 citesc cuvantul :

143 ---*/

144 citirea_cuvantului = argv[1];

145 for (contor = 0;* citirea_cuvantului != ’\0’;){

45

Page 46: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

146 buffer[COMANDA_REZERVA + contor ++]

147 = *citirea_cuvantului++;

148 }

149 i f ( pr int f s ("\nAdresa :\n%s\n",buffer) < 0){

150 #i fd e f DEBUG

151 EROARE("\nNu pot afisa adresa ...",buffer)

152 #else

153 EROARE(" ",buffer)

154 #endif

155 }

156 system(buffer);

157 SUCCES(buffer)

158 }

Program:> Tratarea erorilor 9 este o parte importanta a oricarui proiect VS, [20, p.164]. Lasand la o parte chestiunea dificila a ıntreruperilor hardware care potsurveni pe parcursul executiei codului C, vezi [37], ın programul de mai josfolosim functiile signal si raise din <signal.h> pentru a organiza iesireadin ıntrerupere, reluarea executiei. Aici, vom activa valoarea SIGILL, [20, p.255], a semnalului de ıntrerupere emis de sistemul de operare — neutilizatade Windows — pentru a ıncalca recomandarea MSDN [38] de a nu folosifunctii de tip printf atunci cand nu cunoastem starea10 operatiei run-time.

Intreruperi: eh00.c

1 #include <conio.h>

2 #include <stdio.h>

3 #include <stdlib.h>

4 #include <signal.h> /* semnalarea erorii*/

5

6 void main(){

7 int numar = SIGILL,

8 /*---

9 codul erorii: instructiune ilegala

10 ---*/

11 caracter = 0;

12 void actiune( int );

13 /*---

14 handlerul erorii;

15 va fi apelat in cazul producerii erorii ...

16 ---*/

17

9In limba engleza, error handling.10Cf. [20, p. 244], intructiunea printf(...) este echivalenta cu fprintf(stdout,...).

46

Page 47: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 pr int f s ("\nSalut!\n"

19 "Pentru a incheia , tastati ’x ’:\t");

20 while(( caracter = getch()) != ’x’){

21 s igna l (numar ,actiune);

22 /*---

23 semnalarea erorii:

24 daca se produce , atunci va fi apelat handlerul;

25 acestuia i se va transmite parametrul numar...

26 ---*/

27 ra i se (numar); /* producerea erorii */

28 pr int f s ("\nReluati operatia !\n"

29 "Pentru a incheia , tastati ’x ’:\t");

30 }

31 exit (EXIT SUCCESS);

32 }

33 void actiune( int cod){

34 f p r in t f s ( stderr ,

35 "\nEroare ...\n"

36 "Codul erorii: %d\n"

37 "Cauza: nu ati tastat ’x ’...\n",

38 cod);

39 }

Program:> In proiectul VS de la pagina 34, am utilizat functia fputc din <stdio.h>

ca sa introducem un caracter ıntr-un fisier. Pentru a ne asigura ca “fluxulde date”11 (fisier deschis) exista, apelasem anterior functia fopen_s. In cazcontrar, functia fputc ar fi invocat un handler (o functie) pentru eroarea de“parametru invalid”. Acest “hamal” (handler) — reprezentat printr-un han-dle, adica un pointer la functie, [20, p. 118] — fie repara eroarea si continuaexecutia, fie va ıncheia executia programului, [35, p. 41; Chap. 1]. CodulC dat ın continuare prezinta un asemenea handler, care afiseaza un mesaj siopreste executia. Pentru a-l vedea “la lucru”, folositi — ca pana acum —optiunea Empty Project la initializarea noului proiect VS. Apoi, construitisolutia via Build\Batch Build...12 si selectati ın fereastra Batch Build,la rubrica Solution Config, varianta Release|Win32. Vezi si tehnica VEH,

cf. [35, p. 751; Chap. 25].

Intreruperi: eh01.c

1 #define UNICODE

2 #define _UNICODE

11 In limba engleza, stream, cf. [9, p. 81]. Vezi si [20, p. 241].12Cu optiunea Debug, veti vedea un Watson crash report (fereastra de depanare stan-

dard).

47

Page 48: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

3 #include <conio.h>

4 #include <stdio.h>

5 #include <stdlib.h>

6 #include <crtdbg.h>

7

8 void main(void){

9 FILE *fisier = NULL;

10 void handler_parametru_invalid(

11 const wchar t *,

12 const wchar t *,

13 const wchar t *,

14 unsigned int ,

15 uintptr t );

16 {

17 set invalid parameter handler (

18 handler_parametru_invalid

19 );

20 i f ( fputc(’D’,fisier))

21 exit (EXIT SUCCESS);

22 }

23 }

24

25 void handler_parametru_invalid(

26 const wchar t *expresia_care_produce_eroare ,

27 const wchar t *functie ,

28 const wchar t *fisier ,

29 unsigned int linie_de_cod ,

30 uintptr t rezervat ){

31 fwprintf s ( stderr ,

32 L"\nParametru invalid detectat la "

33 L"apelul functiei \" fputc\".\n"

34 L"Programul se incheie aici!\n");

35 abort();

36 }

Reamintesc ca, fiind ıntr-un sistem de operare Windows (unde resurselesunt virtualizate), apelul nereusit al functiei fputc va declansa, concomitentcu afisarea ıntr-o consola a mesajului din partea handlerului, o fereastrade dialog a JIT-ului (Just-In-Time Debugger) de la Visual Studio. . . Pre-supunand ca VS-ul este instalat pe calculatorul cu care testam programul.Altfel, ın Windows XP13, ın afara mesajului de consola, va aparea o fereastra

13 Inainte de a apasa de doua ori pe imaginea executabilului Nume_program.exe, inseratiın C:\WINDOWS\system32 fisierul msvcr100.dll, copiat din calculatorul ın care ati “con-

48

Page 49: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

cu textul Nume_program.exe has encountered a problem and needs to

close..., ın timp ce ın Windows 7 textul afisat ın fereastra va fi Nume_pro-

gram.exe has stopped working... In schimb, daca rulati programul eh01.exe din consola, raspunsul handlerului va aparea ın (aceeasi) consola.

Program:> Este util adesea sa dispunem de un program care sa introduca ıntr-unfisier o informatie exprimata printr-un sir de caractere, d.ex. un numar detelefon mobil ori un mesaj scurt (SMS), ımpreuna cu o minima ordonare(formatare), respectiv cu adaugarea timpului curent si a unei parole (chei).Acesta ar fi cel mai simplu model de baza de date, vezi [6, pg. 19, 24]. In modevident, rutinele din program pot fi realizate cu ajutorul functiei scanf_s din<stdio.h>. Proiectul VS care urmeaza este alcatuit din fisierele program.c,headerulnostru.h, macrouri.h si handlere.c.

Baza de date txt, cu timestamp si parola: program.c

1 /* ---

2 sintaxa: nume_program.exe xx.txt [parola]

3 aici , [] desemneaza un argument optional

4 ---*/

5

6 /* ---

7 Formatul bazei de date:

8 ===============================

9 ----inceput inregistrare ----

10 NMC | NCCE | continut

11 ----inceput preluare ----

12 Parola este: P/FP

13 ----sfarsit preluare ----

14 Info timp: TS

15 ----sfarsit inregistrare ----

16 ===============================

17 Aici ,

18 NMC: caracterul dat de hash -ul

19 (int)(nr. maxim de caractere * 0.01) + ’0’

20 NCCE: (int)(nr. de car. citite efectiv * 0.1) +’0’

21 P/FP: parola/Fara parola!

22 TS: timestamp

23 ---*/

24

25 /* ---

26 compilare cu optiunea Release;

27 altfel , nu uitati ca trebuie:

struit” — Batch Build — executabilul.

49

Page 50: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

28 1) definit _DEBUG

29 2) inserat

30 _CrtSetReportMode(_CRT_ASSERT , 0);

31

32 Vezi:

33 http:// msdn.microsoft.com/en-us/library /1 y71x448.aspx

34 ---*/

35

36 /* ---

37 limitari :

38 + cand argc = 2:

39 - nu se testeaza daca introducem numele fisierului

40 sau parola;

41 - nu se parseaza nici numele fisierului nici parola;

42 - nu se aloca/elibereaza memorie pentru parola ,

43 presupunand ca este extrem de scurta;

44 + cand argc >= 3 ...

45 ---*/

46

47 #define UNICODE

48 #define _UNICODE

49

50 #undef LUNGIME_LINIE

51 #define LUNGIME_LINIE 500

52 #undef LUNGIME_MESAJ

53 #define LUNGIME_MESAJ 100

54 #undef FORMATE_MESAJ

55 #define FORMATE_MESAJ 4

56 #undef DATE_TIMP

57 #define DATE_TIMP 70

58

59 #include "headerulnostru.h"

60 #include "macrouri.h"

61 #include <time.h>

62

63 void main( int argc , char *argv[]){

64 /*---

65 handlere de eroare:

66 ---*/

67 extern void handler_pentru__cgets_s(

68 const wchar t *,

69 const wchar t *,

70 const wchar t *,

50

Page 51: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

71 unsigned int ,

72 uintptr t );

73 extern void handler_pentru_ctime_s(

74 const wchar t *,

75 const wchar t *,

76 const wchar t *,

77 unsigned int ,

78 uintptr t );

79 extern void handler_pentru_fprintf_s(

80 const wchar t *,

81 const wchar t *,

82 const wchar t *,

83 unsigned int ,

84 uintptr t );

85 extern void handler_pentru_fputs(

86 const wchar t *,

87 const wchar t *,

88 const wchar t *,

89 unsigned int ,

90 uintptr t );

91 extern void handler_pentru_fclose(

92 const wchar t *,

93 const wchar t *,

94 const wchar t *,

95 unsigned int ,

96 uintptr t );

97 extern void handler_pentru_fopen_s(

98 const wchar t *,

99 const wchar t *,

100 const wchar t *,

101 unsigned int ,

102 uintptr t );

103

104 /*---

105 stream -ul de lucru:

106 ---*/

107 FILE *fisier = NULL;

108 /*---

109 linie: bufferul inregistrarii (continut )

110 mesaj: bufferul mesajului (P/FP)

111 contor_parola: cu/fara cheie

112 alt_contor: iterator

113 ---*/

51

Page 52: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

114 char *linie = NULL,

115 *mesaj = NULL;

116 int contor_parola = 0,

117 alt_contor = 0;

118

119 /*---

120 datele functiilor "_s":

121 ---*/

122 s i z e t numar_standard = LUNGIME_MESAJ;

123 s i z e t *numar_caractere_citite = &numar_standard;

124 time t timp_curent = ( int64 ) 0;

125 char *buffer_timp = NULL;

126

127 i f (

128 (LUNGIME_LINIE <= 2 * (LUNGIME_MESAJ + FORMATE_MESAJ

129 + DATE_TIMP + 2))

130 && (FORMATE_MESAJ < 4) && (DATE_TIMP <= 26)

131 /* ---

132 pentru "nr. magic" 26 vezi:

133 http:// msdn.microsoft.com/en-us/library /4 ey61ayt.aspx

134 ---*/

135 ){

136 #i fd e f DEBUG

137 EROARE_A("Defecte de setare!")

138 #else

139 EROARE_A(" ")

140 #endif

141 }

142

143 /*---

144 rezervarea memoriei : linie , timestamp

145 ---*/

146 i f (

147 (linie = (char *) ca l l oc (LUNGIME_LINIE , s i z eo f (char)))

148 == NULL

149 ){

150 #i fd e f DEBUG

151 EROARE_A("\nEroare memorie linie!")

152 #else

153 EROARE_A(" ")

154 #endif

155 }

156 i f (

52

Page 53: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

157 (buffer_timp = (char *) ca l l oc (DATE_TIMP , s i z eo f (char)))

158 == NULL

159 ){

160 #i fd e f DEBUG

161 EROARE("\nEroare memorie timp!",linie)

162 #else

163 EROARE(" ",linie)

164 #endif

165 }

166

167 /*---

168 analizam linia de comanda:

169 ---*/

170

171 i f (argc == 1){

172 #i fd e f DEBUG

173 EROARE("\nLipsesc fisierul si parola!\n",linie)

174 EROARE(" ",buffer_timp)

175 #else

176 EROARE(" ",linie)

177 EROARE(" ",buffer_timp)

178 #endif

179 }

180 i f (argc == 2){

181 #i fd e f DEBUG

182 pr int f s ("\nLipseste parola!\n");

183 #endif

184 mesaj = "Fara parola!";

185 contor_parola = 1;

186 }

187

188 /*---

189 ne conectam la baza:

190 ---*/

191 {/* incep bloc instructiuni "fopen_s ":

192 doar aici instalez handler -ul

193 de eroare pt. fopen_s ...

194 */

195 set invalid parameter handler (

196 handler_pentru_fopen_s

197 );

198 i f (

199 fopen s (&fisier ,argv[1],"a+") != 0

53

Page 54: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

200 ){

201 /* ---

202 daca am ajuns aici , am revenit din eroare;

203 aceasta pt. ca handler -ul doar a afisat

204 un mesaj...

205 o valoare nenula returnata de fopen_s este

206 un cod de eroare;

207 ---*/

208 #i fd e f DEBUG

209 EROARE("Eroare la deschiderea fisierului!",

210 linie)

211 EROARE(" ",buffer_timp)

212 #else

213 EROARE(" ",linie)

214 EROARE(" ",buffer_timp)

215 #endif

216 }

217 }/* final bloc instructiuni "fopen_s" */

218

219 pr int f s ("\nTastati n <= 100 caractere"

220 "\nsi apoi apasati ENTER:\n\n");

221

222 /*---

223 citirea intrarii si a timpului :

224 ---*/

225 {/*incep bloc intructiuni "_cgets_s " */

226 set invalid parameter handler (

227 handler_pentru__cgets_s

228 );

229 cget s s (linie ,

230 LUNGIME_MESAJ + 1,

231 numar_caractere_citite);

232 }/*final bloc intructiuni "_cgets_s " */

233

234 i f (time(& timp_curent) == -1){

235 #i fd e f DEBUG

236 EROARE("Eroare la citirea timpului !",

237 linie)

238 EROARE(" ",buffer_timp)

239 #else

240 EROARE(" ",linie)

241 EROARE(" ",buffer_timp)

242 #endif

54

Page 55: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

243 }

244

245 {/*incep bloc intructiuni "ctime_s" */

246 set invalid parameter handler (

247 handler_pentru_ctime_s

248 );

249 i f (

250 ctime s(buffer_timp ,DATE_TIMP * s i z eo f (char),

251 &timp_curent) != 0

252 ){

253 #i fd e f DEBUG

254 EROARE("Eroare la structurarea timpului!",

255 linie)

256 EROARE(" ",buffer_timp)

257 #else

258 EROARE(" ",linie)

259 EROARE(" ",buffer_timp)

260 #endif

261 }

262 }/*final bloc intructiuni "ctime_s" */

263

264 /*---

265 formatam linia:

266 1) mutam textul la dreapta cu patru pozitii

267 2) inseram "NMC|NCCE|"

268 ---*/

269

270 for (alt_contor = ( int ) (* numar_caractere_citite) - 1;

271 alt_contor >= 0;

272 linie[alt_contor + 4] = linie[alt_contor --]

273 );

274

275 /*---hash -uri:---*/

276 linie[0] = (char) (( int )(LUNGIME_LINIE * 0.01) + ’0’);

277 linie[1] = ’|’;

278 linie[2] = (char) (( int )(( int ) (* numar_caractere_cititeց

(cont.) ) * 0.1) + ’0’);

279 linie[3] = ’|’;

280

281 /*---

282 incarcam inregistrarea:

283 ---*/

284

55

Page 56: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

285 {/*inceput bloc instructiuni cu "fprintf_s" */

286 set invalid parameter handler (

287 handler_pentru_fprintf_s

288 );

289 i f (

290 f p r in t f s (fisier ,

291 "\n----inceput inregistrare ----\n") < 0

292 ){

293 #i fd e f DEBUG

294 EROARE("Eroare la inserarea "

295 "antetului inregistrarii!",

296 linie)

297 EROARE(" ",buffer_timp)

298 #else

299 EROARE(" ",linie)

300 EROARE(" ",buffer_timp)

301 #endif

302 }

303

304 }/* final bloc instructiuni cu "fprintf_s" */

305

306 { /* aplicam "fputs" pentru linie: */

307 set invalid parameter handler (handler_pentru_fputs);

308 i f ( fputs (linie ,fisier) == EOF){

309 #i fd e f DEBUG

310 EROARE("Eroare la inserarea liniei!",

311 linie)

312 EROARE(" ",buffer_timp)

313 #else

314 EROARE(" ",linie)

315 EROARE(" ",buffer_timp)

316 #endif

317 }

318 } /* final "fputs" */

319

320 /* aplicam "fflush": */

321 i f ( f f lu sh (fisier) == EOF){

322 #i fd e f DEBUG

323 EROARE("Eroare la flush -ul liniei!",

324 linie)

325 EROARE(" ",buffer_timp)

326 #else

327 EROARE(" ",linie)

56

Page 57: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

328 EROARE(" ",buffer_timp)

329 #endif

330 }/* final "fflush" */

331

332 { /*inceput bloc instructiuni cu "fprintf_s" */

333 set invalid parameter handler (

334 handler_pentru_fprintf_s

335 );

336 i f (

337 f p r in t f s (fisier ,"\n----inceput preluare ----\n") < 0

338 ){

339 #i fd e f DEBUG

340 EROARE("Eroare la inserarea "

341 "antetului preluarii!",

342 linie)

343 EROARE(" ",buffer_timp)

344 #else

345 EROARE(" ",linie)

346 EROARE(" ",buffer_timp)

347 #endif

348 }

349 }/* final bloc instructiuni cu "fprintf_s" */

350

351 i f (contor_parola == 0){

352 { /*inceput bloc instructiuni cu "fprintf_s" */

353 set invalid parameter handler (

354 handler_pentru_fprintf_s

355 );

356 i f (

357 f p r in t f s (fisier ,"Parola este:\t") < 0

358 ){

359 #i fd e f DEBUG

360 EROARE("Eroare la inserarea "

361 "mesajului parolei!",

362 linie)

363 EROARE(" ",buffer_timp)

364 #else

365 EROARE(" ",linie)

366 EROARE(" ",buffer_timp)

367 #endif

368 }

369 }/* final bloc instructiuni cu "fprintf_s" */

370

57

Page 58: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

371 { /* aplicam "fputs" pentru parola: */

372 set invalid parameter handler (handler_pentru_fputs);

373 i f ( fputs (argv[2],fisier) == EOF){

374 #i fd e f DEBUG

375 EROARE("Eroare la inserarea parolei!",

376 linie)

377 EROARE(" ",buffer_timp)

378 #else

379 EROARE(" ",linie)

380 EROARE(" ",buffer_timp)

381 #endif

382 }

383 }/* final "fputs" */

384

385 /* aplicam "fflush": */

386 i f ( f f lu sh (fisier) == EOF){

387 #i fd e f DEBUG

388 EROARE("Eroare la flush -ul parolei!",

389 linie)

390 EROARE(" ",buffer_timp)

391 #else

392 EROARE(" ",linie)

393 EROARE(" ",buffer_timp)

394 #endif

395 }/* final "fflush" */

396 }

397 e l se {/* ---

398 daca sunt aici ,

399 nu am dat o parola...

400 ---*/

401 { /*inceput bloc instructiuni cu "fprintf_s" */

402 set invalid parameter handler (

403 handler_pentru_fprintf_s

404 );

405 i f ( f p r in t f s (fisier ,mesaj) < 0){

406 #i fd e f DEBUG

407 EROARE("Eroare la inserarea "

408 "mesajului de lipsa "

409 "a parolei!",

410 linie)

411 EROARE(" ",buffer_timp)

412 #else

413 EROARE(" ",linie)

58

Page 59: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

414 EROARE(" ",buffer_timp)

415 #endif

416 }

417 }/* final bloc instructiuni cu "fprintf_s" */

418 } /* final bloc "else" */

419

420 { /*inceput bloc instructiuni cu "fprintf_s" */

421 set invalid parameter handler (

422 handler_pentru_fprintf_s

423 );

424 i f (

425 f p r in t f s (fisier ,

426 "\n----sfarsit preluare ----\n"

427 "Info timp:\t") < 0

428 ){

429 #i fd e f DEBUG

430 EROARE("Eroare la inserarea "

431 "mesajului de final "

432 "pentru preluare !",

433 linie)

434 EROARE(" ",buffer_timp)

435 #else

436 EROARE(" ",linie)

437 EROARE(" ",buffer_timp)

438 #endif

439 }

440 i f (

441 f p r in t f s (fisier ,buffer_timp) < 0

442 ){

443 #i fd e f DEBUG

444 EROARE("Eroare la inserarea timpului!",

445 linie)

446 EROARE(" ",buffer_timp)

447 #else

448 EROARE(" ",linie)

449 EROARE(" ",buffer_timp)

450 #endif

451 }

452 i f (

453 f p r in t f s (fisier ,

454 "----sfarsit inregistrare ----\n\n") < 0

455 ){

456 #i fd e f DEBUG

59

Page 60: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

457 EROARE("Eroare la inserarea "

458 "mesajului de final "

459 "pentru inregistrare!",

460 linie)

461 EROARE(" ",buffer_timp)

462 #else

463 EROARE(" ",linie)

464 EROARE(" ",buffer_timp)

465 #endif

466 }

467 }/*sfarsit bloc instructiuni cu "fprintf_s" */

468

469 /*---

470 deconectam baza:

471 ----*/

472

473 {/*inceput bloc instructiuni cu "fclose" */

474 set invalid parameter handler (

475 handler_pentru_fclose

476 );

477 i f ( f c l o s e (fisier) == EOF){

478 #i fd e f DEBUG

479 EROARE("Eroare la inchiderea streamului...!",

480 linie)

481 EROARE(" ",buffer_timp)

482 #else

483 EROARE(" ",linie)

484 EROARE(" ",buffer_timp)

485 #endif

486 }

487 }/*sfarsit bloc instructiuni cu "fclose" */

488

489 SUCCES(linie ,buffer_timp)

490 }

Baza de date txt, cu timestamp si parola: macrouri.h

1 #i f !defined ( MACROURI )

2 #define MACROURI

3 /* ---------------------*/

4

5 /* ---

6 macrouri debugging:

7 ---*/

60

Page 61: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

8 #undef DEBUG

9 #define DEBUG 1

10 /* #undef DEBUG */

11 #undef EROARE_A

12 #define EROARE_A (text) \

13 pr int f s (text); \

14 exit (EXIT FAILURE);

15 #undef EROARE

16 #define EROARE(text ,pointer) \

17 pr int f s (text); \

18 f ree ((void *) pointer); \

19 pointer = NULL; \

20 exit (EXIT FAILURE);

21 #undef SUCCES

22 #define SUCCES(pointer_a ,pointer_b) \

23 LA_REVEDERE \

24 f ree ((void *) pointer_a); \

25 pointer_a = NULL; \

26 f ree ((void *) pointer_b); \

27 pointer_b = NULL; \

28 exit (EXIT SUCCESS);

29

30 /* ---------------------*/

31 #endif

Baza de date txt, cu timestamp si parola: handlere.c

1 #include "headerulnostru.h"

2

3 void handler_pentru__cgets_s(

4 const wchar t *expresia_care_produce_eroare ,

5 const wchar t *functie ,

6 const wchar t *fisier ,

7 unsigned int linie_de_cod ,

8 uintptr t rezervat ){

9 fwprintf s ( stderr ,

10 L"\nParametru invalid detectat la "

11 L"apelul functiei \"_cgets_s \".\n");

12 }

13 void handler_pentru_ctime_s(

14 const wchar t *expresia_care_produce_eroare ,

15 const wchar t *functie ,

16 const wchar t *fisier ,

17 unsigned int linie_de_cod ,

61

Page 62: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 uintptr t rezervat ){

19 fwprintf s ( stderr ,

20 L"\nParametru invalid detectat la "

21 L"apelul functiei \"ctime_s \".\n");

22 }

23 void handler_pentru_fprintf_s(

24 const wchar t *expresia_care_produce_eroare ,

25 const wchar t *functie ,

26 const wchar t *fisier ,

27 unsigned int linie_de_cod ,

28 uintptr t rezervat ){

29 fwprintf s ( stderr ,

30 L"\nParametru invalid detectat la "

31 L"apelul functiei \" fprintf_s\".\n");

32 }

33 void handler_pentru_fputs(

34 const wchar t *expresia_care_produce_eroare ,

35 const wchar t *functie ,

36 const wchar t *fisier ,

37 unsigned int linie_de_cod ,

38 uintptr t rezervat ){

39 fwprintf s ( stderr ,

40 L"\nParametru invalid detectat la "

41 L"apelul functiei \"fputs\".\n");

42 }

43 void handler_pentru_fclose(

44 const wchar t *expresia_care_produce_eroare ,

45 const wchar t *functie ,

46 const wchar t *fisier ,

47 unsigned int linie_de_cod ,

48 uintptr t rezervat ){

49 fwprintf s ( stderr ,

50 L"\nParametru invalid detectat la "

51 L"apelul functiei \"fclose \".\n");

52 }

53 void handler_pentru_fopen_s(

54 const wchar t *expresia_care_produce_eroare ,

55 const wchar t *functie ,

56 const wchar t *fisier ,

57 unsigned int linie_de_cod ,

58 uintptr t rezervat ){

59 fwprintf s ( stderr ,

60 L"\nParametru invalid detectat la "

62

Page 63: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

61 L"apelul functiei \"fopen_s \".\n");

62 }

Program:> Urmatorul program studiaza aparitiile unui caracter ıntr-un sir de carac-tere, folosind aritmetica pointerilor (adreselor), vezi [20, p. 100]. Ar puteafi utilizat la parsarea numelor de fisiere din proiectul anterior — cautamcaracterul “.” din sirul “nume_fisier.txt” —.

Numarator de caractere: caract0x.c

1 #include "headerulnostru.h"

2 #include <string.h>

3

4 #undef LUNGIME

5 #define LUNGIME 100

6

7 void main(void){

8 int pozitie = 1,

9 contor = 0;

10 s i z e t inregistrare = 0;

11 char caracter = ’e’,

12 *pointerul /* adresele caracterelor*/,

13 sirul[] = "E acesta un sir feeric cu date , ei?";

14

15 pointerul = sirul;

16 pr int f s ("\nIncepe scanarea ...\n");

17 for (;* pointerul != ’\0’;pozitie ++)

18 i f (* pointerul++ == caracter ){

19 contor ++;

20 pr int f s ("Pozitia: %d\n",pozitie);

21 }

22

23 inregistrare = strn len s (sirul ,LUNGIME);

24

25 pr int f s ("Scanare terminata.\n"

26 "Nr. de aparitii : %d\n"

27 "Lungimea sirului: %d\n",

28 contor ,

29 inregistrare

30 = (inregistrare == LUNGIME) ? -1 : inregistrare

31 );

32

33 LA_REVEDERE

34 exit (EXIT SUCCESS);

35 }

63

Page 64: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

4 Programare ın C++

Limbajul C++ a fost inventat de profesorul Bjarne Stroustrup de la Uni-versitatea A&M Texas si este descris ın cartea [41]. Limbajul a fost denumitla ınceput si C cu clase, vezi [40], [41, p. 10].

Un draft al standardului pentru limbajul C++ se gaseste la adresa [39].Program:> Primul program scris ın C++ trebuie, fireste, sa salute lumea. Cum limbajul

C++ extinde limbajul C, suntem, practic, acasa. De aceea, vom putea folosiın cadrul sau functia printf din biblioteca C standard <stdio.h>. Intr-un proiect VS gol, introducem fisierele centru.cpp, headerulnostru.h siajutor.cpp de mai jos.

“Salut, prieteni!”: centru.cpp

1 #include "headerulnostru.h"

2

3 int main(){

4

5 std:: pr int f ("\nSalut , prieteni !\n");

6 afisare("Suntem la laboratorul: %d\n" ,2);

7 afisare("Maine , venim la laboratorul: %d\n" ,3);

8

9 incheiere();

10 return 0;

11 }

“Salut, prieteni!”: headerulnostru.h

1 #ifndef _HEADERULNOSTRU_

2 #define _HEADERULNOSTRU_

3 /* ------------------*/

4

5 // headere C++:

6 #include <cstdio >

7 #include <cstdlib >

8

9 // headere C:

10 #include <conio.h>

11

12 int afisare(const char*, int );

13 int incheiere();

14

15 /* ------------------*/

16 #endif

64

Page 65: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

“Salut, prieteni!”: ajutor.cpp

1 #include "headerulnostru.h"

2 #include <cstring >

3

4 int afisare(const char *mesaj , int numar){

5 s t a t i c int lungime = 200;

6 i f (

7 std:: str len (mesaj) >= s ta t i c cas t < s i ze t >(lungime)

8 ){

9 std:: pr int f ("\nMesaj prea lung...\n");

10 return -1;

11 }

12 return std:: pr int f (mesaj ,numar /*+ (lungime ++)*/);

13 }

14

15 int incheiere(){

16 std:: pr int f ("\nTastati o litera pentru a incheia: ");

17 return getch();

18 }

Observam prefixul std al functiei printf. Pentru a-l explica, mentionezca biblioteca C++ standard preia fisierele <nume.h> ale bibliotecii C standardsub forma <cnume>, cf. [41, p. 202]. In aceste fisiere se foloseste un mecanismC++ denumit nume de spatiu14, [41, pg. 167, 176], pentru a evita conflictelede nume15 care apar atunci cand, fara sa stie, programatori diferiti folosescacelasi nume pentru a desemna marimi diferite. Precizand — prin numele despatiu — spatiul (zona din program16) unde numele marimii respective (vari-abila, functie) este valabil, problema se rezolva eficient. In fisierul <cstdio>,numele de spatiu ın care se gaseste functia C printf este std (standard).Pentru a atesta apartenenta unui nume la un nume de spatiu se foloste oper-atorul de spatiu17 “::”, vezi [41, p. 82]. Expresiile nume_de_spatiu::nume

constituie nume complete18 ale marimilor.Cuvantul cheie static, [41, pg. 145, 200, 819], trebuie folosit doar ın

codul de implementare al functiilor19, e.g., afisare. El cere ca variabila ıncauza sa fie initializata o singura data — la primul apel al functiei —, indifer-

14 In limba engleza, namespace, cf. [18, p. 867].15 In limba engleza, name clashes .16 In limba engleza, scope, vezi [41, p. 168]. Se foloseste si sintagma domeniu de valabi-

litate, adica zona din program ın care marimea este activa, cf. [23, pg. 48, 49].17 In limba engleza, scope resolution operator .18 In limba engleza, fully qualified names , cf. [42, p. 291].19Si al claselor. . . Vezi si [41, p. 819, Section B.2.3].

65

Page 66: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

ent de cate ori va fi apelata aceasta. Daca activati expresia + (lungime++)

din codul functiei afisare, veti observa ca programul “tine minte” valoarealungime ıntre apeluri consecutive.

Mai departe, remarcam ca functia strlen returneaza valori de tip size_t,adica unsigned int. Pentru a face comparatia cu marimea lungime, trebuierealizata o conversie explicita de tip (cast). Codul C (size_t) lungime estereorganizat ın C++ via operatorul static_cast<nume_tip>, cf. [41, p. 130].

La pornirea unui program C++, sistemul de operare ıi va atasa o seriede fluxuri de date, intitulate std::cout, std::cin, std::cerr, std::clog,etc20. Elementele (functii, date) necesare utilizarii acestora se gasesc ın fi-sierele antet <iostream> si <iomanip> — sau <iostream.h>, <iomanip.h>cf. [18, p. 718, Sect. 980] —. Lucrand ın consola, sunt mai usor de retinuturmatoarele “traduceri” ale denumirilor acestor fluxuri de intrare–iesire: cin(console–in, citire), cout (console–out21, scriere), cerr (console–error, erori,fara buffer) si clog (console–log, erori, cu buffer), vezi si [18, p. 598, Sect.817]. Practic, reamintindu-ne fluxurile din limbajul C, vezi pagina 28, coutse refera la stdout, cin la stdin, iar cerr si clog la stderr, vezi [41, p.637].

Program:> Putem lucra cu fluxurile de intrare–iesiere la fel ca ıntr-un program C,utilizand omoloage ale functiilor din libraria standard getchar si puts, cf.[20, p. 247].

Afisand un caracter. . . : ajutor.cpp

1 #include <iostream >

2 #include <iomanip >

3 #include <conio.h>

4

5 using namespace std;

6 // evitam scrierea prefixului "std::"

7

8 int main(){

9 char litera = ’\n’;

10 litera = cin.get();

11 cout.put(litera);

12 getch();

13 return 0;

14 }

20Lor li se adauga stream-urile pentru caractere multi-byte, vezi [41, p. 609].21 In realitate, prof. Stroustrup abreviaza cu cout expresia “character output stream”,

cf. [42, p. 45, Sect. 2.2].

66

Page 67: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Limbajul C++ ofera ınsa o alternativa performanta a comunicarii I/O prinfunctii via notiunea de operatori , ca e.g., ın urmatoarea situatie familiara:

a+ b ınseamna + (a, b)

Program:> Operatorul pentru fluxurile–de–iesire cout, cerr si clog este “<<”, iarpentru cin avem “>>”. In programul urmator, folosim manipulatorii22 —setprecision, scientific, fixed din numele de spatiu std — ca sa schim-bam modul de afisare al unor date numerice.

Precizia ın C++: unu.cpp

1 #include <iostream >

2 #include <iomanip > //pt. manipulatorul setprecision

3 #include <conio.h>

4 int main()

5 {

6 double valoare = 1.345;

7 system("cls");

8 std::cout << std:: setprec i s ion (0)//vedem tot numarul

9 << valoare << std::endl;

10 std::cout << std:: setprec i s ion (2)

11 << valoare << std::endl;

12 std::cout << std:: s c i e n t i f i c << std:: setprec i s ion (2)

13 << valoare << std::endl;

14 std::cout << std:: f ixed << std:: setprec i s ion (4)

15 << valoare << std::endl

16 << 23.4567891 << " " << -12.54

17 << std:: setprec i s ion (12)

18 << " alta precizie! "

19 << 0.88 << std::endl;

20 getch();

21 return 0;

22 }

Program:> Cum numeroase programe C++ manipuleaza date numerice, este conven-abil sa dispunem de cel putin o “functie de format” personalizata, care saafiseze pe ecran ori sa scrie ıntr-un fisier rezultatele calculelor noastre ınurma unei simple apelari! Proiectul Visual Studio listat ın continuare oferaun astfel de mecanism de formatare si este compus din fisierele program.cpp,headerulnostru.h, format_afisare.h si format_afisare.cpp. Fara a nepreocupa de semnificatia anumitor instructiuni C++, putem folosi mecanis-mul ca ın fisierul program.cpp — pana acum am manevrat cu succes functia

22 In fapt, niste functii, apelate de operator printr-un pointer la functie, cf. [41, p. 631].Manipulatorii se gasesc ın <iomanip>, <ios>.

67

Page 68: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

MessageBox, fara sa tinem seama de ceea ce este un callback, cf. [41, p.650] si [18, pg. 1013, 1014] —.

O functie de format: program.cpp

1 #include "headerulnostru.h"

2 #include "format_afisare.h"

3 #include <iostream >

4 #include <iomanip >

5

6 using namespace octavian ;

7

8 int main(){

9

10 /* ---

11 Explicatii:

12 (+): aplicam la sfarsit "formatul ",

13 el modifica afisarea pentru intreg randul ,

14 adica pana la ";"...;

15 (++): aplicand la inceput "formatul ", el ramane

16 valabil si pe randurile urmatoare;

17 (+++): modificator de precizie ; numai unul pe rand ,

18 spre deosebire de cazul clasic ...;

19 (++++): revenim la formatul standard ...

20 ---*/

21

22 std::cout

23 << 2.00 << " "

24 << 3.12345678901234 << " " << 4.12345678901234 << " "

25 << 5.12345678901234 << " " << 6.12345678901234 << " "

26 << 7.12345678901234 << " " << 8.12345678901234 << " "

27 << 9.12345678901234 << " " << 10.12345678901234

28 << " "

29 << Afisare (& std::cout ,2)//(+)

30 << std::endl;

31 std::cout << 2.00 << std::endl;

32 {

33 Afisare afis(& std::cout ,9);

34 std::cout << 2.00 << " "

35 << 3.12345678901234 << " " << 4.12345678901234

36 << " "

37 << 5.12345678901234 << " " << 6.12345678901234

38 << " " << std::endl;

39 std::cout <<3.00 << std::endl;//(++)

68

Page 69: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

40 }

41 std::cout << 4.00 << std::endl;

42 {

43 Afisare afis(& std::cout ,7);

44 std::cout << 2.00 << " "

45 << 3.12345678901234 << " " << 4.12345678901234

46 << " "

47 << afis(5)//(+++)

48 << 5.12345678901234 << " " << 6.12345678901234

49 << " "

50 << std::endl;

51 std::cout << 5.00 << std::endl;

52 }

53 std::cout << 6.00 << std::endl;// (++++)

54

55 LA_REVEDERE

56 return 0;

57 }

O functie de format: format_afisare.h

1 /* ---

2 Copyright: Octavian , 2011 - -2014

3 ---*/

4 #ifndef _FORMAT_AFISARE_

5 #define _FORMAT_AFISARE_

6

7 #include <cstdio >

8 #include <iostream >

9

10 namespace octavian{

11 typedef unsigned int numar;

12 typedef std:: streamsize lungime;

13 typedef std::ostream iesire;

14 typedef std:: ios base :: fmtflags date_fanioane;

15

16 enum tip_flux {flux_cout , flux_cerr};

17

18 c la s s Santinela{

19 tip_flux fel_flux;

20

21 //date "cout":

22 /*

23 explicatie:

69

Page 70: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

24 - afisat_contor_flux_cout: afisarea numarului

25 de "obiecte -format"

26 - flux_start_cout: adresa stream -ului utilizat

27 - fanioane_cout: flag -urile precedente ale

28 stream -ului utilizat

29 - precizie_arhiva_cout: precizia precedenta a

30 stream -ului utilizat

31 */

32 s t a t i c numar afisat_contor_flux_cout;

33 s t a t i c iesire* flux_start_cout;

34 s t a t i c numar contor_flux_start_cout;

35 s t a t i c date_fanioane fanioane_cout;

36 s t a t i c lungime precizie_arhiva_cout;

37

38 //date "cerr":

39 s t a t i c numar afisat_contor_flux_cerr;

40 s t a t i c iesire* flux_start_cerr;

41 s t a t i c numar contor_flux_start_cerr;

42 s t a t i c date_fanioane fanioane_cerr;

43 s t a t i c lungime precizie_arhiva_cerr;

44

45 public :

46 //citirea adresei stream -ului:

47 iesire* sentry_flux() const;

48 //citirea flag -urilor:

49 date_fanioane sentry_flux_flaguri() const;

50 //citirea preciziei:

51 lungime sentry_flux_precizie() const ;

52 //periculoase --->

53 /* ---

54 explicatie:

55 Datele statice din clasa "sentry" -- Santinela sunt ,

56 defapt , marimi globale private. Uneori , trebuie sa

57 le citesc/modific fara a avea la indemana un obiect

58 Santinela... Aici intervin

59 functiile -membru statice (publice)!

60 ---*/

61 s t a t i c iesire* sentry_flux_stat(numar);

62 s t a t i c date_fanioane sentry_flux_flaguri_stat(numar);

63 s t a t i c lungime sentry_flux_precizie_stat(numar);

64 s t a t i c numar afisat_cititor(numar);

65 s t a t i c void afisat_resetor(numar);

66 s t a t i c numar contor_flux_cititor(numar);

70

Page 71: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

67 //<--- periculoase

68 // constructor predefinit la "cout":

69 exp l i c i t Santinela(

70 numar ffel_flux = s ta t i c cas t <numar >(1)

71 );

72 //pt. initializare directa ca sub -obiect ...

73 exp l i c i t Santinela(iesire* fflux);

74 Santinela(const Santinela&);

75 Santinela operator=( const Santinela&);

76 ~Santinela();

77 };

78

79 c la s s Afisare{

80 fr iend iesire;

81 fr iend iesire& operator <<(iesire&,Afisare&);

82 Santinela sentry_afisare;

83 tip_flux flux_duplicat;

84 numar precizie ;

85 date_fanioane optiunea_mea;

86 public :

87 // predefinit la "cout":

88 exp l i c i t Afisare( int pprecizie = 3);

89 exp l i c i t Afisare(iesire*, int pprecizie = 3);

90 Afisare(const Afisare &);

91 Afisare operator=( const Afisare &);

92 Afisare& operator()( int );

93 ~Afisare();

94 };

95 }

96 #endif

O functie de format: format_afisare.cpp

1 /* ---

2 Copyright: Octavian , 2011 - -2014

3 ---*/

4 #include "headerulnostru.h"

5 #include "format_afisare.h"

6 #include <iomanip >

7

8 #undef VERIFICARE

9 #define VERIFICARE 1

10 //#undef VERIFICARE

11

71

Page 72: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

12 // santinela fluxurilor...

13 //"cerr":

14 octavian ::iesire*

15 octavian :: Santinela::

16 flux_start_cerr = &std:: cerr;

17 octavian ::numar

18 octavian :: Santinela::

19 contor_flux_start_cerr = numar();

20 octavian ::numar

21 octavian :: Santinela::

22 afisat_contor_flux_cerr = numar();

23 octavian :: date_fanioane

24 octavian :: Santinela::

25 fanioane_cerr = (* flux_start_cerr)

26 . f l a g s ();

27 octavian ::lungime

28 octavian :: Santinela::

29 precizie_arhiva_cerr = (* flux_start_cerr)

30 .precis ion ();

31 //"cout":

32 octavian ::iesire*

33 octavian :: Santinela::

34 flux_start_cout = &std::cout;

35 octavian ::numar

36 octavian :: Santinela::

37 contor_flux_start_cout = numar();

38 octavian ::numar

39 octavian :: Santinela::

40 afisat_contor_flux_cout = numar();

41 octavian :: date_fanioane

42 octavian :: Santinela::

43 fanioane_cout = (* flux_start_cout)

44 . f l a g s ();

45 octavian ::lungime

46 octavian :: Santinela::

47 precizie_arhiva_cout = (* flux_start_cout)

48 .precis ion ();

49

50 octavian ::iesire*

51 octavian :: Santinela:: sentry_flux() const {

52 i f (fel_flux == flux_cout)

53 return flux_start_cout;

54 e l se

72

Page 73: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

55 return flux_start_cerr;

56 }

57

58 octavian ::iesire*

59 octavian :: Santinela::

60 sentry_flux_stat(numar fls){

61 i f (fls == s ta t i c cas t <numar >(1))

62 return flux_start_cout;

63 e l se

64 return flux_start_cerr;

65 }

66

67 octavian :: date_fanioane

68 octavian :: Santinela::

69 sentry_flux_flaguri() const {

70 i f (fel_flux == flux_cout)

71 return fanioane_cout;

72 e l se

73 return fanioane_cerr;

74 }

75

76 octavian :: date_fanioane

77 octavian :: Santinela::

78 sentry_flux_flaguri_stat(numar fls){

79 i f (fls == s ta t i c cas t <numar >(1))

80 return fanioane_cout;

81 e l se

82 return fanioane_cerr;

83 }

84

85 octavian ::lungime

86 octavian :: Santinela::

87 sentry_flux_precizie() const {

88 i f (fel_flux == flux_cout)

89 return precizie_arhiva_cout;

90 e l se

91 return precizie_arhiva_cerr;

92 }

93

94 octavian ::lungime

95 octavian :: Santinela::

96 sentry_flux_precizie_stat(numar fls){

97 i f (fls == s ta t i c cas t <numar >(1))

73

Page 74: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

98 return precizie_arhiva_cout;

99 e l se

100 return precizie_arhiva_cerr;

101 }

102

103 octavian ::numar

104 octavian :: Santinela::

105 afisat_cititor(numar nac){

106 i f (nac == s ta t i c cas t <numar >(1))

107 return afisat_contor_flux_cout;

108 e l se

109 return afisat_contor_flux_cerr;

110 }

111

112 void

113 octavian :: Santinela::

114 afisat_resetor(numar nar){

115 i f (nar == s ta t i c cas t <numar >(1))

116 afisat_contor_flux_cout = numar();

117 e l se

118 afisat_contor_flux_cerr = numar();

119 }

120

121 octavian ::numar

122 octavian :: Santinela::

123 contor_flux_cititor(numar ncfc){

124 i f (ncfc == s ta t i c cas t <numar >(1))

125 return contor_flux_start_cout;

126 e l se

127 return contor_flux_start_cerr;

128 }

129

130 octavian :: Santinela::

131 Santinela(numar ffel_flux)

132 {

133 i f (ffel_flux == s ta t i c cas t <numar >(1)){

134 fel_flux = flux_cout;

135 contor_flux_start_cout++;

136 }

137 e l se {

138 fel_flux = flux_cerr;

139 contor_flux_start_cerr++;

140 }

74

Page 75: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

141 }

142

143 octavian :: Santinela::

144 Santinela(iesire* fflux){

145 i f (fflux == &std::cout){

146 fel_flux = flux_cout;

147 contor_flux_start_cout++;

148 }

149 e l se {

150 fel_flux = flux_cerr;

151 contor_flux_start_cerr++;

152 }

153 }

154

155 octavian :: Santinela::

156 Santinela(const Santinela& o_santinela){

157 i f (o_santinela.fel_flux == flux_cout){

158 fel_flux = flux_cout;

159 contor_flux_start_cout++;

160 }

161 e l se {

162 fel_flux = flux_cerr;

163 contor_flux_start_cerr++;

164 }

165 }

166

167 octavian :: Santinela

168 octavian :: Santinela::

169 operator=( const Santinela& o_santinela){

170 i f (o_santinela.fel_flux == flux_cout){

171 fel_flux = flux_cout;

172 contor_flux_start_cout++;

173 return * th is ;

174 }

175 e l se {

176 fel_flux = flux_cerr;

177 contor_flux_start_cerr++;

178 return * th is ;

179 }

180 }

181

182 octavian :: Santinela::

183 ~Santinela(){

75

Page 76: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

184 i f (fel_flux == flux_cout){

185 /* ---

186 primul apel al destructorului va fi la

187 incheierea scope -ului ultimului obiect Afisare ...

188 atentie: nu putem crea obiecte Santinela decat in

189 constructorul obiectului Afisare!

190 ---*/

191 contor_flux_start_cout --;

192 afisat_contor_flux_cout++;

193 }

194 i f (fel_flux == flux_cerr){

195 contor_flux_start_cerr --;

196 afisat_contor_flux_cerr++;

197 }

198 }

199

200 octavian ::Afisare ::

201 Afisare( int pprecizie) :

202 precizie ( s ta t i c cas t <numar >( pprecizie)),

203 flux_duplicat(flux_cout),

204 sentry_afisare(Santinela(& std::cout ))

205 {

206 optiunea_mea = std:: ios base ::dec

207 | std:: ios base :: f ixed

208 | std:: ios base ::showpoint;

209 lungime

210 noua_precizie = s ta t i c cas t <lungime >(precizie );

211 (*( sentry_afisare.sentry_flux()))

212 . se t f (optiunea_mea);

213 (*( sentry_afisare.sentry_flux()))

214 .precis ion (noua_precizie);

215 // curatat contoare ...

216 numar

217 locala_contor_afisari = Santinela::

218 afisat_cititor( s ta t i c cas t <numar >(1)),

219 locala_contor_flux = Santinela::

220 contor_flux_cititor( s ta t i c cas t <numar >(1));

221 i f (locala_contor_flux == s ta t i c cas t <numar >(1)){

222 /* ---

223 niciun obiect Afisare "in viata"...,

224 Santinela a incrementat deja...

225 ---*/

226 #i fd e f VERIFICARE

76

Page 77: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

227 std:: pr int f ("\n\nFolosim formatul meu\n\n");

228 #endif

229 i f (locala_contor_afisari == s ta t i c cas t <numar >(1))

230 //sub -obiectul sau Santinela distrus anterior ...

231 Santinela:: afisat_resetor( s ta t i c cas t <numar >(1));

232 }

233 }

234

235 octavian ::Afisare ::

236 Afisare(iesire* fflux , int pprecizie):

237 precizie ( s ta t i c cas t <numar >( pprecizie)),

238 sentry_afisare(Santinela(fflux))

239 {

240 i f (fflux == &std::cout){

241 flux_duplicat = flux_cout;

242 numar

243 locala_contor_afisari = Santinela::

244 afisat_cititor( s ta t i c cas t <numar >(1)),

245 locala_contor_flux = Santinela::

246 contor_flux_cititor( s ta t i c cas t <numar >(1));

247 i f (locala_contor_flux == s ta t i c cas t <numar >(1)){

248 #i fd e f VERIFICARE

249 std:: pr int f ("\n\nFolosim formatul meu!\n\n");

250 #endif

251 i f (locala_contor_afisari == s ta t i c cas t <numar >(1))

252 Santinela:: afisat_resetor( s ta t i c cas t <numar >(1));

253 }

254 }

255 i f (fflux == &std:: cerr){

256 flux_duplicat = flux_cerr;

257 numar

258 locala_contor_afisari = Santinela::

259 afisat_cititor( s ta t i c cas t <numar >(2)),

260 locala_contor_flux = Santinela::

261 contor_flux_cititor( s ta t i c cas t <numar >(2));

262 i f (locala_contor_flux == s ta t i c cas t <numar >(1)){

263 #i fd e f VERIFICARE

264 std:: pr int f ("\n\nFolosim formatul meu!\n\n");

265 #endif

266 i f (locala_contor_afisari == s ta t i c cas t <numar >(1))

267 Santinela:: afisat_resetor( s ta t i c cas t <numar >(2));

268 }

269 }

77

Page 78: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

270 optiunea_mea = std:: ios base ::dec

271 | std:: ios base :: f ixed

272 | std:: ios base ::showpoint;

273 lungime

274 noua_precizie = s ta t i c cas t <lungime >( precizie);

275 (*( sentry_afisare.sentry_flux()))

276 . se t f (optiunea_mea);

277 (*( sentry_afisare.sentry_flux()))

278 .precis ion (noua_precizie);

279 }

280

281 octavian ::Afisare ::~ Afisare (){

282 // resetarea datelor stream -urilor:

283 /*---

284 Nu doresc sa folosesc functiile -membru ale

285 obiectului Santinela! Conform Stroustrup ,

286 Special edition , Section 10.4.6 , pag. 247,

287 atunci cand incepe executia unui destructor pentru

288 obiectele Afisare , are loc secventa "intai executam

289 codul destructorului , apoi apelam destructorii sub -

290 obiectelor"!

291 Pentru a evita sa tinem seama de aceasta secventa :

292 - am introdus functii -membru statice

293 in clasa Santinela;

294 - am introdus membrul "flux_duplicat"

295 in clasa Afisare;

296 ---*/

297 i f (flux_duplicat == flux_cout){

298 (*Santinela::

299 sentry_flux_stat( s ta t i c cas t <numar >(1)))

300 .unsetf (optiunea_mea);

301 (*Santinela::

302 sentry_flux_stat( s ta t i c cas t <numar >(1)))

303 . se t f (Santinela::

304 sentry_flux_flaguri_stat( s ta t i c cas t <numar >(1))

305 );

306 (*Santinela::

307 sentry_flux_stat( s ta t i c cas t <numar >(1)))

308 .precis ion (Santinela::

309 sentry_flux_precizie_stat( s ta t i c cas t <numar >(1))

310 );

311 }

312 i f (flux_duplicat == flux_cerr){

78

Page 79: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

313 (* Santinela::

314 sentry_flux_stat( s ta t i c cas t <numar >(2)))

315 .unsetf (optiunea_mea);

316 (* Santinela::

317 sentry_flux_stat( s ta t i c cas t <numar >(2)))

318 . se t f (Santinela::

319 sentry_flux_flaguri_stat( s ta t i c cas t <numar >(2))

320 );

321 (* Santinela::

322 sentry_flux_stat( s ta t i c cas t <numar >(2)))

323 .precis ion (Santinela::

324 sentry_flux_precizie_stat( s ta t i c cas t <numar >(2))

325 );

326 }

327 precizie = numar();

328 optiunea_mea = date_fanioane();

329

330 /*---

331 In acest moment , pe fluxul "nume", unde "nume"

332 este fie "cout", fie "cerr", am (nedistruse)

333 atatea obiecte -format

334 Afisare: contor_flux_start_nume...

335 Au fost deja distruse atatea obiecte -format

336 Afisare:

337 afisat_contor_flux_nume...

338 In mod corect , lucrul cu un obiect -format Afisare

339 se realizeaza astfel: introduc un asemenea obiect

340 si apoi ii folosesc operatorul de apel --- opera -

341 tor() --- pentru a modifica precizia afisarii

342 datelor numerice ...

343 Se poate intampla sa introduc mai multe obiecte

344 -format pe acelasi flux.

345 ---*/

346

347 /*---

348 Doresc sa afisez un mesaj la distrugerea ultimului

349 obiect Afisare "in viata"...

350 Aici ma bazez pe secventa : "intai destructorul

351 obiectului mare , apoi cel al sub-obiectului"!

352 ---*/

353 i f (flux_duplicat == flux_cout){

354 numar

355 locala_contor_afisari = Santinela::

79

Page 80: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

356 afisat_cititor( s ta t i c cas t <numar >(1)),

357 locala_contor_flux = Santinela::

358 contor_flux_cititor( s ta t i c cas t <numar >(1));

359 i f (locala_contor_flux == s ta t i c cas t <numar >(1)){

360 #i fd e f VERIFICARE

361 std:: pr int f (

362 "\nRevenim la formatul precedent pe fluxul "

363 "\"cout\"!\n"

364 "Asadar , pe acest flux , formatul meu "

365 "a fost aplicat de %d ori!\n\n",

366 s ta t i c cas t < int >( locala_contor_afisari) + 1);

367 // inca nu s-a incrementat afisarea ...

368 #endif

369 /* ---

370 Anterior , am folosit un obiect Afisare.

371 Dupa distrugerea lui , contorul

372 afisat_contor_flux_nume

373 a fost incrementat...

374 ---*/

375 Santinela:: afisat_resetor( s ta t i c cas t <numar >(1));

376 }

377 }

378 i f (flux_duplicat == flux_cerr){

379 numar

380 locala_contor_afisari = Santinela::

381 afisat_cititor( s ta t i c cas t <numar >(2)),

382 locala_contor_flux = Santinela::

383 contor_flux_cititor( s ta t i c cas t <numar >(2));

384 i f (locala_contor_flux == s ta t i c cas t <numar >(1)){

385 #i fd e f VERIFICARE

386 std:: pr int f (

387 "\nRevenim la formatul precedent pe fluxul "

388 "\"cerr\"!\n"

389 "Asadar , pe acest flux , formatul meu "

390 "a fost aplicat de %d ori!\n\n",

391 s ta t i c cas t < int >( locala_contor_afisari) + 1);

392 #endif

393 Santinela:: afisat_resetor( s ta t i c cas t <numar >(2));

394 }

395 }

396 }

397

398 octavian ::Afisare ::

80

Page 81: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

399 Afisare(const Afisare& o_afisare):

400 sentry_afisare(o_afisare.sentry_afisare)

401 {

402 flux_duplicat = o_afisare.flux_duplicat;

403 precizie = o_afisare.precizie ;

404 optiunea_mea = o_afisare.optiunea_mea;

405 lungime

406 noua_precizie = s ta t i c cas t <lungime >( precizie );

407 (*( sentry_afisare.sentry_flux()))

408 . se t f (optiunea_mea);

409 (*( sentry_afisare.sentry_flux()))

410 .precis ion (noua_precizie);

411 }

412

413 octavian ::Afisare

414 octavian :: Afisare ::

415 operator=( const Afisare& o_afisare){

416 i f ( th is == &o_afisare)

417 return * th is ;

418 (*( sentry_afisare.sentry_flux()))

419 .unsetf (optiunea_mea);

420 sentry_afisare = o_afisare.sentry_afisare;

421 flux_duplicat = o_afisare.flux_duplicat;

422 precizie = o_afisare.precizie ;

423 optiunea_mea = o_afisare.optiunea_mea;

424 lungime

425 noua_precizie = s ta t i c cas t <lungime >(precizie );

426 (*( sentry_afisare.sentry_flux()))

427 . se t f (optiunea_mea);

428 (*( sentry_afisare.sentry_flux()))

429 .precis ion (noua_precizie);

430 return * th is ;

431 }

432

433 octavian ::Afisare&

434 octavian :: Afisare ::

435 operator()( int nnum){

436 numar transf_precizie = s ta t i c cas t <numar >(nnum);

437 precizie = transf_precizie;

438 return * th is ;

439 }

440

441 octavian ::iesire&

81

Page 82: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

442 octavian ::

443 operator <<(octavian :: iesire& stream_iesire ,

444 octavian :: Afisare& af){

445 iesire*

446 locale_flux =af.sentry_afisare.sentry_flux();

447 (*locale_flux). f lush ()

448 .precis ion ( s ta t i c cas t <lungime >(af.precizie ));

449 return (* locale_flux);

450 }

Codul C++ din fisierul headerulnostru.h se gaseste la pagina 5.Program:> In mod asemanator, putem construi diverse mecanisme de introducere

(citire) a datelor de la tastatura ori via redirectare. In cartea sa despreınvatarea C++ [42], profesorul Stroustrup foloseste urmatoarea functie “deıncheiere”:

Functie de ıncheiere

1 void keep_window_open(){

2 std:: cin. c lear ();

3 std::cout << "Please enter a character to exit\n";

4 char ch;

5 std:: cin >> ch;

6 return;

7 }

O varianta a sa poate fi organizata astfel23:

Functie de ıncheiere: varianta

1 #include <iostream >

2 #include <iomanip >

3

4 void iesire();

5

6 int main(){

7 iesire();

8 return 0;

9 }

10

11 void iesire(){

12 for (

13 std:: cin. c lear (),

14 std::cout << "\nApasati ENTER"

15 " pentru a incheia: "

23 In anumite situatii, aceasta da gres. Vezi discutia de la pagina 137.

82

Page 83: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

16 << std::endl ,

17 std:: cin. ignore();;

18 ) return;

19 }

Intotdeauna trebuie testata starea fluxului–de–intrare, cf. [41, p. 615,616]. Functia clear — cu valoarea prestabilita std::ios_base::goodbit

pentru parametru — seteaza starea fluxului la “buna”, iar functia ignore

citeste, fara sa stocheze, urmatorul caracter al fluxului, vezi [41, p. 619]. A-ceasta din urma se opreste din executie cand ıntalneste EOF din <stdio.h>.Este recomandabil, [41, p. 601], sa se foloseasca std::cin.eof() ın loculmacroului popular EOF din limbajul C — defapt, EOF este valoarea returnatade std::char_traits<char>::eof() din <iosfwd>, cf. [41, pg. 581, 620]— .

Program:> Pentru a usura codul C++, fluxurile de intrare–iesire dispun de operatorulvoid*. Astfel, starea fluxului este testata implicit pe baza acestui operator ınsecventele–bucla — for(/**/;/**/;/**/){/**/}, while(/**/){/**/} —ori ın executiile conditionate — if(/**/) then{/**/} —, cf. [41, p. 617]:

Testand starea fluxurilor. . .

1 #include <iostream >

2 #include <iomanip >

3 #include <cstdlib >

4

5 void main(){

6 char litera;

7 for (; std:: cin. c lear (), std:: cin >> litera;)

8 i f (litera == ’a’)

9 exit (EXIT SUCCESS);

10 }

Program:> Un alt aspect interesant poate fi remarcat ın cadrul programului unu.cppde la pagina 67, si anume ca nu este nevoie de instructiuni suplimentarepentru a afisa “numere” si “cuvinte” laolalta. Putem spune ca programul“ghiceste” felul output-ului. Mecanismul C++ care permite aceasta simplifi-care se numeste sablon24 si este reprezentat prin expresia <numele_tipului_

datei>. Fara prea multe detalii, poate fi folosit astfel:

Utilizarea sabloanelor: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

24 In limba engleza, template.

83

Page 84: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

4

5 #include "sablon.cpp"

6

7 int main(){

8 out("\nSalut!\n");

9 out(3);

10 out("\nPa...");

11

12 getch();

13 return 0;

14 }

Utilizarea sabloanelor: sablon.cpp

1 #include <iostream >

2 #include <iomanip >

3

4 template<typename T>

5 void out(const T& t){

6 std:: cerr << t;

7 }

Desi ın locul cuvantului cheie typename putem scrie class, este reco-mandabil sa-l pastram pe primul, cf. [48, p. 10].

Program:> De multe ori, ın interiorul programelor de dimensiuni mai mari, se puneproblema sa raspundem unei anumite cerinte (periodice) printr-un bloc decod ın care este implementata o suita de pasi bine stabiliti (un algoritm).De exemplu, pentru a-si putea citi documentele din e-mail , un utilizatorurmeaza pasii standard: (i) insereaza un nume–de–utilizator, (ii) furnizeazao parola, (iii) apasa un buton, etc. In programul anterior, ın corpul functieiout a fost implementat un astfel de algoritm, si anume afisarea parametrilorreali. Insa, ın anumite situatii, la executarea unora dintre pasi trebuie apli-cate masuri particulare, specifice cerintei — e.g., utilizatorul respectivuluicont de e-mail este VIP , foloseste un serviciu suplimentar platit, etc. — .Aceste masuri constituie trasaturile25 raspunsului. Limbajul C++ folosestemecanismul sabloanelor si pentru a pune ın executie politica26, adica suita demasuri particulare prin care se rezolva o cerinta speciala, vezi [41, pg. 340,757].

Urmatorul program, scris ın limbajul C, se refera la o situatie ın caremecanismul C++ de implementare a politicilor poate micsora substantial can-titatea de cod. Reamintindu-ne discutia de la pagina 10 despre sistemul

25 In limba engleza, traits .26 In limba engleza, policy.

84

Page 85: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

publicistic TEX, sa presupunem ca procesam un document stiintific (LATEX)pe platforma MiKTEX [25], via interfata grafica TEXnicCenter [43], vezi [27].Documentul ın cauza contine cateva zeci de fotografii mari, ın formatul eps,iar compilarea LATEX =⇒ PS dureaza cateva minute. Cum suntem nevoiti sacompilam documentul de sute de ori pe parcursul producerii sale, este util sadispunem de un program care sa dezactiveze/activeze fotografiile din codulLATEX. Dat fiind ca documentul este un sir de caractere ASCII, una dintresolutiile la ındemana consta ın apelarea la expresii regulate, vezi [20, p. 116],[42, p. 836].

In cazul nostru, problema este simpla, caci suntem interesati de douaexpresii exacte: \includegraphics[ si %\includegraphics[.

Cautarea unor expresii ıntr-un sir: graphics2.c

1 /* ---

2 >>>>graphics2:

3 un program simplu

4 de prepare a fisierelor "tex"

5 pentru compilarea "LaTeX ==> PS"

6 cu ajutorul "MiKTeX"

7 Copyright: Octavian , 2011 - -2014

8

9 >>>>Sintaxa liniei de comanda:

10 graphics2 nume_fisier.tex tip_procesare

11 Aici ,

12 nume_fisier: numele fisierului de

13 procesat

14 tip_procesare: tastati "i" (inserez)

15 sau "s" (sterg)

16

17 >>>>Ce face graphics2:

18 in fisierul "nume_fisier.tex",

19 blocurile de comenzi LaTeX destinate procesarii

20 imaginilor sunt de forma

21 =============

22 \begin{figure *}[h]

23 \centering

24 \includegraphics[DIMENSIUNI]{ ADRESA POZEI}\\

25 {CAPTURA POZEI}% INFORMATII AUXILIARE

26 \label{REFERINTA FIGURII%DEZACTIVATA}

27 \end{figure*}

28 =============

29 Aici (LaTeX),

30 "\\" desemneaza o noua linie ,

85

Page 86: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

31 "%" un comentariu.

32 Pentru a DEZACTIVA (tip_procesare: "i") imaginea ,

33 graphics2 cauta expresia "\ includegraphics[" si

34 o prefateaza cu "%".

35 Pentru a ACTIVA (tip_procesare: "s") imaginea ,

36 graphics2 cauta expresia "%\ includegraphics[" si

37 sterge caracterul "%".

38

39 >>>>Limitarile graphics2:

40 -- nu analizeaza numele fisierului de procesat

41 -- nu rezerva memorie pt. expresia de procesat

42 -- daca fisierul de procesat nu exista ,

43 programul nu defineste un handler de eroare

44 (cerut de "fopen_s ")

45 -- fisierul procesat are nume fix: "scriere.tex"

46 -- ...

47 ---*/

48

49 #include <stdlib.h>

50 #include <stdio.h>

51 #include <conio.h>

52 #include <string.h>

53

54 /* ---

55 Numarul de caractere procesate la o alocare:

56 ---*/

57 #undef LUNGIME

58 #define LUNGIME 20

59

60 int main( int argc , char *argv[]){

61

62 /*---

63 Explicatia datelor:

64 fisier: stream -ul din care citim

65 executie : stream -ul in care scriem

66 model: expresia pe care o cautam

67 buffer: sirul in care salvam procesarea

68 particula: caracterul curent

69 fisier_intrare: numele fisierului de procesat

70 sir_intrare: tipul de procesare

71 iterator_sir: numarul total de caractere citite

72 alt_iterator: numarul de aparitii ale primului

73 caracter din expresia "model"

86

Page 87: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

74 secv_iterator: numarul de aparitii ale

75 expresiei "model"

76 iterato:

77 iterator :

78 iteratorr:

79 salt: diversi iteratori

80 limita: lungimea blocului de memorie

81 lungime_model: lungimea expresiei "model"

82 contor: memoreaza pozitiile in care apare

83 primul caracter din expresia "model"

84 secvente : memoreaza pozitiile in care apare

85 expresia "model"

86 pa: handler de incheiere

87 ---*/

88

89 FILE *fisier = NULL, *executie = NULL;

90 char *buffer = NULL, particula = 0,

91 *fisier_intrare = NULL,* sir_intrare = NULL;

92 int iterator_sir = 0, alt_iterator = 0,

93 secv_iterator = 0, iterator = 0,

94 iteratorr = 0, iterato = 0, salt = 0,

95 limita = LUNGIME , lungime_model = 0,

96 *contor = NULL, *secvente = NULL;

97 void pa(char *, int *, int *);

98

99 i f (argc < 3){

100 pr int f s ("\nArgumente incomplete!\n"

101 "Vezi linia de comanda ...\n"

102 "Tasteaza o litera pentru a iesi: ");

103 getch();

104 return 0;

105 }

106 fisier_intrare = argv[1];

107 sir_intrare = argv[2];

108 i f (strcmp(sir_intrare ,"i") == 0){

109 /* ---

110 tipul procesarii: "i"

111 ---*/

112 char model[] = "\\ includegraphics[";

113 /* caracterul "\" este special in C...*/

114 lungime_model = countof (model) - 1;

115

116 buffer = (char *) ca l l oc (limita , s i z eo f (char));

87

Page 88: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

117 contor = ( int *) ca l l oc (limita , s i z eo f ( int ));

118 secvente = ( int *) ca l l oc (limita , s i z eo f ( int ));

119

120 fopen s (&fisier ,fisier_intrare ,"r");

121 fopen s (&executie ,"scriere.tex","w");

122

123 /* blocul de citire:*/

124 for (;( particula = getc (fisier)) != EOF;

125 iterator_sir++){

126 i f (iterator_sir == limita){

127 limita += LUNGIME;

128 buffer = (char *) rea l l oc ((void *)buffer ,

129 limita* s i z eo f (char));

130 contor = ( int *) rea l l oc ((void *)contor ,

131 limita* s i z eo f ( int ));

132 secvente = ( int *) rea l l oc ((void *)secvente ,

133 limita* s i z eo f ( int ));

134 }

135 i f (particula == ’\\’){

136 contor[alt_iterator] = iterator_sir;

137 alt_iterator++;

138 }

139 buffer[iterator_sir] = particula;

140 }

141

142 /* daca suntem aici , atunci putem avea

143 iterator_sir == limita ...

144 altfel , limita > iterator_sir...*/

145 pr int f s ("\nStatistica:\n"

146 "Numar total de caractere: %d\n"

147 "Numar de aparitii ale caracterului: %d\n"

148 "Ultimul caracter citit: %c\n\n",

149 iterator_sir ,

150 alt_iterator ,

151 buffer[iterator_sir -1]);

152

153 /* blocul de testare:*/

154 for (iterator = 0;iterator < alt_iterator;

155 iterator ++){

156 for (iteratorr = 0; iteratorr < lungime_model;

157 iteratorr++)

158 i f (buffer[contor[iterator ]+iteratorr]

159 == model[iteratorr])

88

Page 89: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

160 {salt++;}

161 i f (salt == lungime_model){

162 pr int f s ("Secventa apare "

163 "la pozitia: %d\n"

164 "Secventa este: ",

165 contor[iterator] + 1);

166 for (iterato = 0; iterato < lungime_model;

167 iterato ++){

168 pr int f s ("%c",

169 buffer[contor[iterator ]+iterato ]);

170 }

171 pr int f s ("\n");

172 secvente [secv_iterator] = contor[iterator ];

173 secv_iterator++;

174 }

175 salt = 0;

176 }

177

178 pr int f s ("\nStatistica:\n"

179 "Numar de aparitii ale secventei: %d\n",

180 secv_iterator);

181

182 /*blocul de manevre pentru sirul "buffer":*/

183 /*adaug memorie pentru introducere...

184 ultimul caracter citit: iterator_sir - 1...

185 de asemeni , putem avea

186 limita == iterator_sir...

187 vreau sa adaug cel putin un caracter ...

188 avem secv_iterator aparitii ale expresiei;

189 pt fiecare aparitie introducem un %...

190 deci mai adaugam: */

191 i f (iterator_sir == limita){

192 salt = 1;

193 }

194 limita += (1 + secv_iterator)

195 /*atentie: secv_iterator este obligatoriu nenul!!!*/

196 + (salt == 0 ? 0 : 1);

197 buffer = (char *) rea l l oc ((void *)buffer ,limita);

198 buffer[limita -1] =’\0’; /* inchei sirul de acum...*/

199 for (iterator = iterator_sir;iterator <limita -1;

200 iterator ++)

201 buffer[iterator] = ’%’; /* completare standard ...*/

202 for (iteratorr = secv_iterator -1; iteratorr >= 0;

89

Page 90: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

203 iteratorr --){

204 /* avem iterator_sir+1 <= limita -1...*/

205 for (iterator = iterator_sir

206 +( secv_iterator -1-iteratorr);

207 iterator >= secvente [iteratorr];

208 iterator --

209 ){

210 buffer[iterator +1]=buffer[iterator ];

211 }

212 buffer[secvente[iteratorr]] = ’%’;

213 }

214

215 /*blocul de manevre pentru fisierul nou:*/

216 fputs (buffer ,executie);

217 f f lu sh (executie );

218

219 /*blocul de final: inchiderea fisierelor ,

220 eliberarea memoriei ...*/

221 f c l o s e (fisier);

222 f c l o s e (executie );

223 pa(buffer ,contor ,secvente);

224 buffer = NULL;

225 contor = NULL;

226 secvente = NULL;

227 }/*---

228 final pentru tipul procesarii: "i"

229 ---*/

230 i f (strcmp(sir_intrare ,"s") == 0){

231 /* ---

232 tipul procesarii: "s"

233 ---*/

234 char model[] = "%\\ includegraphics[";

235 /* caracterul "\" este special in C...*/

236 lungime_model = countof(model) - 1;

237

238 buffer = (char *) ca l l oc (limita , s i z eo f (char));

239 contor = ( int *) ca l l oc (limita , s i z eo f ( int ));

240 secvente = ( int *) ca l l oc (limita , s i z eo f ( int ));

241

242 fopen s (&fisier ,fisier_intrare ,"r");

243 fopen s (&executie ,"scriere.tex","w");

244

245 /*blocul de citire:*/

90

Page 91: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

246 for (;( particula = getc (fisier)) != EOF;

247 iterator_sir++){

248 i f (iterator_sir == limita){

249 limita += LUNGIME;

250 buffer = (char *) rea l l oc ((void *)buffer ,

251 limita* s i z eo f (char));

252 contor = ( int *) rea l l oc ((void *)contor ,

253 limita* s i z eo f ( int ));

254 secvente = ( int *) rea l l oc ((void *)secvente ,

255 limita* s i z eo f ( int ));

256 }

257 i f (particula == ’%’){

258 contor[alt_iterator] = iterator_sir;

259 alt_iterator++;

260 }

261 buffer[iterator_sir] = particula;

262 }

263

264 /*daca suntem aici , atunci putem avea

265 iterator_sir == limita ...

266 altfel , limita > iterator_sir...*/

267 pr int f s ("\nStatistica:\n"

268 "Numar total de caractere: %d\n"

269 "Numar de aparitii ale caracterului: %d\n"

270 "Ultimul caracter citit: %c\n\n",

271 iterator_sir ,

272 alt_iterator ,

273 buffer[iterator_sir -1]);

274

275 /*blocul de testare:*/

276 for (iterator = 0; iterator < alt_iterator;

277 iterator ++){

278 for (iteratorr = 0; iteratorr < lungime_model;

279 iteratorr++)

280 i f (buffer[contor[iterator ]+ iteratorr]

281 == model[iteratorr])

282 {salt++;}

283 i f (salt == lungime_model){

284 pr int f s ("Secventa apare "

285 "la pozitia: %d\n"

286 "Secventa este: ",

287 contor[iterator ] + 1);

288 for (iterato = 0; iterato < lungime_model;

91

Page 92: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

289 iterato ++){

290 pr int f s ("%c",

291 buffer[contor[iterator ]+ iterato ]);

292 }

293 pr int f s ("\n");

294 secvente [secv_iterator] = contor[iterator ];

295 secv_iterator++;

296 }

297 salt = 0;

298 }

299

300 pr int f s ("\nStatistica:\n"

301 "Numar de aparitii ale secventei: %d\n",

302 secv_iterator);

303

304 /*blocul de manevre pentru sirul "buffer":*/

305 /*adaug memorie pentru introducere...

306 ultimul caracter citit: iterator_sir - 1...

307 de asemeni , putem avea limita == iterator_sir...

308 vreau sa adaug cel putin un caracter ...

309 avem secv_iterator aparitii ale expresiei;

310 pt fiecare aparitie introducem un %...

311 deci mai adaugam: */

312 i f (iterator_sir == limita){

313 salt = 1;

314 }

315 limita += (1 + secv_iterator)

316 /*atentie: secv_iterator este obligatoriu nenul!!!*/

317 + (salt == 0 ? 0 : 1);

318 buffer = (char *) rea l l oc ((void *)buffer ,limita);

319 buffer[limita -1] =’\0’; /* inchei sirul de acum...*/

320 for (iterator = iterator_sir;iterator <limita -1;

321 iterator ++)

322 buffer[iterator ] = ’%’; /* completare standard ...*/

323 for (iteratorr = 0;iteratorr <= secv_iterator -1;

324 iteratorr++){

325 for (iterator = secvente [iteratorr]-iteratorr;

326 iterator <= iterator_sir -iteratorr;

327 iterator ++

328 ){

329 buffer[iterator ]=buffer[iterator +1];

330 }

331 }

92

Page 93: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

332

333 /*blocul de manevre pentru fisierul nou:*/

334 fputs (buffer ,executie);

335 f f lu sh (executie );

336

337 /*blocul de final: inchiderea fisierelor ,

338 eliberarea memoriei ...*/

339 f c l o s e (fisier);

340 f c l o s e (executie );

341 pa(buffer ,contor ,secvente);

342 buffer = NULL;

343 contor = NULL;

344 secvente = NULL;

345 }/*---

346 final pentru tipul procesarii: "s"

347 ---*/

348 i f (!(strcmp(sir_intrare ,"s") == 0)

349 &&

350 !(strcmp(sir_intrare ,"i") == 0)){

351 pr int f s ("\nOptiune eronata !\n"

352 "Vezi linia de comanda ...\n"

353 "Tasteaza o litera pentru a iesi: ");

354 }

355 getch();

356 return 0;

357 }

358

359 void pa(char *bufer , int *conto , int *ssecv){

360 f ree ((void *)bufer);

361 f ree ((void *)conto);

362 f ree ((void *)ssecv);

363 pr int f s ("\n\nLa revedere !\n\n\t");

364 }

Asa cum se poate observa, codul programului este ımpartit ın doua ras-punsuri la cereri specifice. Ar fi fost excelent sa dispunem de functia:

1 template<typename Expresie , typename Procesare >

2 char* graphics2(Expresie e, Procesare p){

3 // instructiuni...

4 }

Aici, cel de-al doilea argument precizeaza politica: i (inserare), respectiv s

(stergere).Doua tipuri de date din libraria standard C++, si anume vector si string,

93

Page 94: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

folosesc unul dintre parametrii mecanismului sablon pentru a-si preciza polit-ica spatiului alocat (ın memorie), necesar bunei lor functionari — expandare—, cf. [41, pg. 442, 582]. Vezi si [24, p. 63, Item 13]. Aceste doua tipuri dedate pot fi folosite cu succes drept ınlocuitori de siruri de date “obisnuite”— adica, bool, char, int, double, [41, p. 70] —, vezi [42, pg. 60, 116], chiardaca nu cunoastem organizarea lor ın detaliu. Fiind implementate cu aju-torul sabloanelor, partea din libraria standard a limbajului C++ care descriedatele vector si string se mai numeste si libraria standard de sabloane27.

Program:> In acest program construim un vector de date double, pe care ıl sortam[15, p. 109] si ıl afisam — ınainte si dupa sortare —.

Sortarea unor numere reale: sortare1.cpp

1 #include "headerulnostru.h"

2 #include <iostream >

3 #include <vector >

4 #include <algorithm > //pt. sort

5

6 int main(){

7 std::vector <double > vectocta;

8 for ( int i = 0;i <= 6; i++)

9 vectocta .push back(1.27*(10-i)+3);

10 std::cout << "\nAfisare nesortata:\n"

11 <<std::endl;

12 for ( int i = 0;

13 i < s ta t i c cas t < int >( vectocta . s i ze ());

14 i++)

15 std::cout << "vectocta[" << i << "] = "

16 << vectocta[i]

17 << std::endl;

18 /*---

19 pentru "sort" vezi si

20 http://www.cppreference.com/wiki/algorithm/sort

21 ---*/

22 std:: sort (vectocta .begin(),vectocta.end());

23 std::cout << "\nAfisare sortata :\n"

24 <<std::endl;

25 for ( int i = 0;

26 i < s ta t i c cas t < int >( vectocta . s i ze ());

27 i++)

28 std::cout << "vectocta[" << i << "] = "

27 In limba engleza, Standard Template Library (STL), cf. [42, p. 1096]. Vezi si [18, pg.825, 909].

94

Page 95: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

29 << vectocta[i]

30 << std::endl;

31 LA_REVEDERE

32 return 0;

33 }

Program:> Un program simplu ın care construim un string — acest tip de date, spredeosebire de vector, se refera numai la secvente de caractere28 — reia temacautarii ıntr-un dictionar on-line, vezi programul consola04.c de la pagina42, dar foloseste dictionarul Cambridge pentru engleza britanica. Deoareceinterogarile bazei de date, vezi [6, p. 26], [14, p. 139], sunt mai complicatedecat ın cazul dictionarului limbii romane, anumite cuvinte nu vor fi gasitecu expresia de interogare folosita ın program.

Dictionar: cambridge_1.cpp

1 #include "headerulnostru.h"

2 #include <iostream >

3 #include <string >

4

5 int main(){

6 std:: str ing

7 sirul = "\"C:\\ Program Files\\Mozilla Firefox"

8 "\\firefox.exe\""

9 " http:// dictionary.cambridge.org/"

10 "dictionary/british/";

11 std::cout << "\nDictionar on-line. "

12 "Inchideti fereastra browser -ului\n"

13 "dupa ce ati citit definitia.\n"

14 "Introduceti un cuvant: "

15 << std::endl;

16 std:: str ing adaos;

17 std:: cin >> adaos;

18 sirul += adaos + "_1?q=" + adaos;

19 std::cout << "\n-----------------\n"

20 "Adresa completa :\n"

21 << sirul

22 << "\n-----------------\n"

23 << std::endl;

24 sirul += "& (echo La revedere !)"

25 " & echo.";

26 system(sirul. c s t r ());

27 LA_REVEDERE

28Cf. [41, p. 583], string ınseamna basic_string<char>.

95

Page 96: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

28 return 0;

29 }

Facem observatia ca fluxurile std::cout si std::cin sunt “legate”29 unulde celalalt, astfel ca programul va afisa pe ecran mesajul “Introduceti un

cuvant:” ıntotdeauna ınainte sa ceara, via cursor, tastarea unui cuvant ınlimba engleza, cf. [41, p. 623].

Program:> Folosim specificatorul de legaturi extern, vezi [18, p. 623, Sect. 863],pentru a ne referi la datele definite ıntr-o alta unitate de traducere30 (fisiercompilat, cu extensia obj). In programul care urmeaza, aceste date suntdiverse caractere speciale.

Afisare: afisat_caractere.cpp

1 #include "headerulnostru.h"

2 #include "litere.h"

3 #include <iostream >

4

5 int main(){

6

7 using namespace octavian ;

8 std::cout

9 << patr_stanga << " " << patr_dreapta

10 << ’\n’

11 << aco_stanga << " " << aco_dreapta

12 << std::endl

13 << rot_stanga << " " << rot_dreapta

14 << ’\n’

15 << coada_maimuta << spatiu << diez

16 << spatiu << bar_vert

17 << std::endl

18 << dolar << std::ends << tilda

19 << std::endl;

20 LA_REVEDERE

21 return 0;

22 }

Afisare: litere.h

1 #ifndef _LITERE_

2 #define _LITERE_

3

4 namespace octavian{

29 In limba engleza, tie.30 In limba engleza, translation unit , cf. [41, p. 197].

96

Page 97: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

5 typedef char litere;

6 extern litere

7 spatiu ,

8 rot_stanga ,

9 rot_dreapta ,

10 patr_stanga ,

11 patr_dreapta ,

12 aco_stanga ,

13 aco_dreapta ,

14 diez ,

15 bar_vert ,

16 coada_maimuta ,

17 dolar ,

18 tilda;

19 }

20

21 #endif

Afisare: litere.cpp

1 #include "litere.h"

2 typedef octavian ::litere octalt;

3

4 // vezi http://en.wikipedia.org/wiki/ASCII_table

5 octalt

6 octavian :: spatiu = ’\040’,

7 octavian :: rot_stanga = ’\050’,

8 octavian :: rot_dreapta =’\051’,

9 octavian :: patr_stanga = ’\133’,

10 octavian :: patr_dreapta = ’\135’,

11 octavian :: aco_stanga = ’\173’,

12 octavian :: aco_dreapta = ’\175’,

13 octavian :: bar_vert = ’\174’,

14 octavian :: coada_maimuta = ’\100’,

15 octavian ::diez = ’\043’,

16 octavian :: dolar = ’\044’,

17 octavian :: tilda = ’\176’;

Utilizand cuvantul cheie typedef, introducem un pseudonim31 pentrunumele unui tip de date, vezi [41, p. 84]. Astfel, este mult mai usor demodificat programul atunci cand schimbam tipul de date — d.ex. utilizamtipul wchar_t [41, p. 72] ın loc de char —.

31 In limba engleza, alias .

97

Page 98: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Program:> Reamintesc ca, ın cadrul limbajului C, un obiect este o zona de memorie,a carei interpretare depinde de clasa de stocare32 — aceasta din urma deter-mina durata de viata33 a stocarii; avem doua clase de stocare34: automata sistatica —, si de tipul datelor stocate, cf. [20, pg. 195, 197] si [42, p. 60]. Ex-emplul imediat este dat de literele “de un octet” lungime. Astfel, obiectului(variabilei) litera din definitia

1 char litera = ’a’;

ıi este alocat un bloc de opt biti ın memorie35. Insa, ın afara tipurilor fun-damentale de date, exista si tipuri derivate, cum ar fi structurile si uniunile,cf. [20, p. 196], care ınglobeaza diverse siruri de obiecte. Aici, organizareamemoriei (cuvinte, aliniere36, etc.) tine de compilatorul folosit, vezi [20, pg.147, 149].

Limbajul C++ pune la dispozitia noastra un instrument suplimentar pen-tru crearea de noi tipuri de date (tipuri definite–de–utilizatori37), si anumeclasa (tipul class). Spre deosebire de cazul tipurilor fundamentale de dateint, char sau double, compilatorul trebuie “ınvatat” cum sa stocheze ınmemorie datele UDT, respectiv cum sa le manipuleze — ne putem ıntreba ceınseamna: (UDT data1) + (UDT data2) —. Cea de-a doua sarcina poartadenumirea de supraıncarcarea38 operatorilor, cf. [18, p. 623]. Nu toti oper-atorii limbajului C++ pot fi supraıncarcati, d.ex. operatorul conditional [23,p. 11], “?:”, nu poate fi supraıncarcat, cf. [42, p. 1070].

Datele de tipul class sunt reprezentate prin obiecte, vezi [42, p. 301].Astfel, o clasa, notata C, este familia (colectia) tuturor obiectelor de tipul C.Putem descrie ce ınseamna “sa faci parte” din clasa C, adica sa prezentam ca-racteristicile (datele–membru39 si functiile–membru) unui element din clasaC, si apoi exemplifica pe baza unui obiect (element) din colectia (familia,clasa, setul, etc.) notata C. Prin extrapolare, spunem ca datele–membrusi functiile–membru ale unui obiect oarecare al clasei C sunt datele–membru

32 In limba engleza, storage class .33 In limba engleza, lifetime, storage duration sau (local) extent , cf. [23, p. 49].34 In C++ apare cea de-a treia clasa de stocare, si anume free store (heap), cf. [42, p.

1047]. In standardul limbajului C++ ea se numeste (clasa de) stocare dinamica, vezi [39,p. 65]. Lasam la o parte chestiunea (stocarii) datelor din firele de executie, precizata destandard. . .

35Vezi si [42, p. 78, Section 3.9] pentru type safety.36Nu trebuie presupus ca marimea unei structuri este suma marimilor datelor sale [20,

p. 138].37 In limba engleza, user-defined types (UDT), cf. [42, p. 300].38 In limba engleza, operator overloading, vezi [42, p. 316 si urm.].39 In limba engleza, data members , cf. [42, p. 301]. In romaneste, se ıntalnesc frecvent

sintagmele variabile membre, cf. [18, p. 637], respectiv campuri , cf. [13, p. 91].

98

Page 99: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

si functiile–membru ale clasei C40: mai precis, clasa C ne da un “sablon”al datelor pe care le ınmagazineaza un obiect al clasei (acestea sunt datele–membru), respectiv al functiilor (–membru) ce opereaza (de regula) cu dateleınmagazinate de obiectul ın cauza al clasei, vezi [18, p. 638, Sect. 885].Uneori, datele–membru ale unei clase sunt numite proprietatile clasei, iarfunctiile–membru ale clasei desemneaza metodele41 clasei, cf. [18, p. 643,Sect. 893]. Referindu-ne generic la proprietatile si metodele unei clase, dis-cutam despre membrii clasei. Atunci cand vorbim despre un obiect oarecareal clasei, spunem ca el este o instanta a clasei, vezi [18, ibid.].

Proiectul Visual Studio listat ın continuare se refera la o clasa fara date–membru. El este format din fisierele program.cpp, salut.h, salut.cpp siheaderulnostru.h — de la pagina 5 —.

Primul proiect cu clase: program.cpp

1 #include "headerulnostru.h"

2 #include "salut.h"

3

4 int main(){

5 octavian :: Salut primul_salut;

6 primul_salut.functie_salut();

7 LA_REVEDERE

8 return 0;

9 }

Primul proiect cu clase: salut.h

1 #ifndef _SALUT_

2 #define _SALUT_

3

4 namespace octavian{

5 c la s s Salut{

6 public :

7 void functie_salut();

8 }; //atentie , nu trebuie omis acest ";"!

9 }

10

11 #endif

40Cf. [41, p. 754], clasa si nu obiectul constituie unitatea de ıncapsulare.41 In paradigma object–oriented (OO) — programare orientata–obiect —, vezi [44, p.

12]. In limbajul Java [19, p. 111], toate functiile–membru sunt metode. Cf. [41, p. 310],ın C++ o metoda desemneaza mai degraba o functie–membru virtuala.

99

Page 100: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Primul proiect cu clase: salut.cpp

1 #include "salut.h"

2 #include <iostream >

3 #include <iomanip >

4

5 using namespace octavian ;

6 void Salut:: functie_salut(){

7 std::cout << "\nSalut , prieteni !\n" << std::endl;

8 }

Ca regula generala: declaratia unei clase din “viata reala” se introduceın fisierul nume_clasa.h ın timp ce implementarea membrilor sai — ın cazulnostru, definirea functiei octavian::Salut::functie_salut — trebuie fa-cuta ın fisierul nume_clasa.cpp.

Specificatorul de acces public ne permite sa apelam functia–membru cusintaxa:

1 numele_obiectului.numele_functiei_membru();

Alti specificatori sunt private — aprioric, nu este nevoie sa-l inseram ındeclaratii — si protected, vezi [41, pg. 402, 849].

Program:> Evident, un nume de spatiu, d.ex. octavian, va fi compus din declaratiilemai multor clase, plus alte date relevante (vezi programul afisat_caracterede la pagina 96), ca ın urmatorul proiect VS.

Al doilea proiect cu clase: program.cpp

1 #include "headerulnostru.h"

2 #include "salut.h"

3 #include "cutii.h"

4

5 int main(){

6 octavian ::Salut primul_salut;

7 primul_salut.functie_salut();

8 octavian ::Cutie al_doilea_salut ,

9 al_treilea_salut;

10 al_doilea_salut.functie_salut();

11 al_treilea_salut.functie_salut();

12 LA_REVEDERE

13 return 0;

14 }

Al doilea proiect cu clase: salut.h

1 #ifndef _SALUT_

2 #define _SALUT_

100

Page 101: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

3 namespace octavian{

4 c la s s Salut{

5 typedef unsigned int numere;

6 s t a t i c numere contor;

7 public :

8 void functie_salut();

9 };

10 }

11 #endif

Al doilea proiect cu clase: salut.cpp

1 #include "salut.h"

2 #include <iostream >

3 #include <iomanip >

4

5 using namespace octavian ;

6 Salut::numere

7 Salut::contor = 0;

8

9 void Salut:: functie_salut(){

10 i f (contor++ == 0)

11 std::cout << "Salut , prieteni !\n" << std::endl;

12 }

Al doilea proiect cu clase: cutii.h

1 #ifndef _CUTII_

2 #define _CUTII_

3

4 namespace octavian{

5 c la s s Cutie{

6 public :

7 void functie_salut();

8 };

9 }

10

11 #endif

Al doilea proiect cu clase: cutii.cpp

1 #include "cutii.h"

2 #include <iostream >

3 #include <iomanip >

4

101

Page 102: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

5 using namespace octavian ;

6 #include "salut.h"

7

8 void Cutie:: functie_salut(){

9 Salut salut;

10 salut.functie_salut();

11 std::cout << "Ne revedem , prieteni !\n" << std::endl;

12 }

Pana acum, ın numele de spatiu octavian am introdus clase cu caracteris-tici asemanatoare — ambele se ocupa de prelucrarea/transmiterea unui mesajcatre utilizator —, ceea ce ne-a facut sa dam acelasi nume functiilor–membruınsarcinate cu afisarea mesajului, chiar daca implementarile lor difera. Acestefunctii–membru publice constituie interfata (publica) a claselor [41, p. 760],si reprezinta, ın fapt, tot ceea ce ıl intereseaza pe utilizatorul respectivelorclase, vezi [41, p. 225], [23, p. 100].

Membrii statici ai unei clase — atunci cand sunt specificati drept publici— pot fi apelati, chiar daca nu dispunem ın program de obiecte ale clasei ıncauza, cu sintaxa:

1 /**/ numele_clasei:: numele_membrului /**/;

cf. [41, p. 228].Program:> Introducem ın discutie un tip special de functie–membru, si anume cons-

tructorul . In primul rand, un constructor nu returneaza valori si are numeleclasei , cf. [34, p. 46]. De asemeni, nu putem introduce pointeri la construc-tori [41, p. 424].

1 // diversi constructori:

2 numele_clasei();

3 numele_clasei(tip_un_argument ,tip_alt_argument);

4 // alte functii --membru:

5 tip_data_iesire

6 numele_functiei_membru(tip_data_intrare);

Atunci cand este apelat, acesta construieste (initializeaza) un obiect alclasei, adica realizeaza o instantiere a clasei, vezi [42, pg. 182, 183]. Astfel,datele–membru ale unei clase pot fi initializate prin intermediul construc-torilor: ın fisierul program.cpp al proiectului VS listat mai jos, obiectulcutiedoi din clasa Cutie_doi are valoarea 4 la campul numar. Multimeavalorilor pe care le au la un moment dat datele–membru ale unui obiect con-stituie starea (valoarea) obiectului la momentul respectiv, cf. [41, p. 748].

Initializarea/modificarea datelor–membru poate fi ınsa realizata si cu altefunctii–membru — este cazul clasei Cutie_unu din acelasi fisier, care folosestemembrul functie_scris pentru initializarea campului numar —.

102

Page 103: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Functiile–membru ale unei clase se ımpart, asadar, ın doua categorii: celecare “citesc” (nu modifica) date si cele care “scriu” (modifica) date. Putemfolosi terminologia inspectori si modificatori [41, p. 706], accesori si mutatori[44, p. 16], functii–set si functii–get [22, pg. 218, 229], etc. Impartirea este,evident, neriguroasa, caci putem vorbi si despre manageri – implementori –functii-helping42 – functii-de-acces – membri-const , vezi [22, p. 223 si urm.].

In anumite situatii — indiferent daca folosim un constructor sau o functie–membru oarecare —, dorim sa initializam unele dintre campuri cu valori“tipice” (standard). De exemplu, o valoare tipica pentru o data–membrude tip int este numarul zero. Ne putem pune ıntrebarea: ce ınseamna ovaloare tipica pentru o data UDT? Aceasta chestiune a condus la notiuneagenerala de invariant , cf. [42, p. 309], [41, p. 749], prin care descriem stareabuna(bine-definita) a unui obiect. In C++, valoarea standard a unei date detip T este oferita de expresia T(). Astfel, instructiunile int x = int(); siint x = 0; sunt echivalente, vezi [42, p. 323]. Prima dintre ele este esentialaatunci cand scriem sabloane, cf. [41, p. 131].

Daca valoarea standard a tipului unei anumite date este cunoscuta43,putem alege sa nu definim un constructor — el va fi generat de compilator(cel putin44) pentru datele UDT [41, pg. 243, 244] — sau sa folosim unconstructor fara argumente. Acesta este constructorul implicit45, cu sintaxanumele_clasei().

Constructori: program.cpp

1 #include "diverse.h"

2 #include "cutii.h"

3 using namespace octavian ;

4

5 int main(){

6 Cutie_zero cutiezero;

7 cutiezero.functie_citit();

8 Cutie_unu cutieunu;

9 cutieunu .functie_scris(

10 s ta t i c cas t <Cutie_unu::numere_in >(12)

11 );

12 cutieunu .functie_citit();

13 Cutie_doi cutiedoi;

14 cutiedoi .functie_citit();

15 Cutie_doi cutiedoii(

42sau –helper , vezi [41, p. 240].43De catre compilator!44 In Visual C++. . .45 In limba engleza, default constructor , cf. [42, p. 324].

103

Page 104: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

16 s ta t i c cas t <Cutie_doi::numere_doi >(4)

17 );

18 cutiedoii.functie_citit();

19 cutiedoii = 34;

20 cutiedoii.functie_citit();

21 Cutie_trei cutietrei;

22 cutietrei.functie_citit();

23 iesire();

24 return 0;

25 }

Constructori: diverse.h

1 #ifndef _DIVERSE_

2 #define _DIVERSE_

3

4 #include <cstdlib >

5 #include <cstdio >

6 #include <conio.h>

7

8 namespace octavian{

9 void iesire();

10 }

11

12 #endif

Constructori: diverse.cpp

1 #include "diverse.h"

2 #include <iostream >

3 #include <iomanip >

4

5 void octavian :: iesire(){

6 for (

7 std:: cin. c lear (),

8 std::cout << "\nApasati ENTER"

9 " pentru a incheia: "

10 << std::endl ,

11 std:: cin.ignore();;

12 ) return;

13 }

Constructori: cutii.h

1 #ifndef _CUTII_

104

Page 105: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

2 #define _CUTII_

3

4 namespace octavian{

5 c la s s Cutie_zero{

6 public :

7 void functie_citit();

8 };

9 c la s s Cutie_unu{

10 public :

11 typedef int numere_in;

12 typedef int numere_out;

13 void functie_citit() const ;

14 numere_out functie_scris(numere_in);

15 private:

16 numere_in numar;

17 };

18 c la s s Cutie_doi{

19 public :

20 typedef int numere_doi;

21 void functie_citit() const ;

22 Cutie_doi();

23 Cutie_doi(numere_doi nnumar);

24 private:

25 numere_doi numar;

26 };

27 c la s s Cutie_trei{

28 public :

29 typedef int numere_trei;

30 void functie_citit() const ;

31 exp l i c i t

32 Cutie_trei(numere_trei nnumar = numere_trei());

33 private:

34 numere_trei numar;

35 };

36 }

37

38 #endif

Constructori: cutii.cpp

1 #include "cutii.h"

2 #include <iostream >

3 #include <iomanip >

4 using namespace octavian ;

105

Page 106: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

5

6 void Cutie_zero:: functie_citit(){

7 #undef STA

8 #define STA std::

9 STA cout << "In Cutie_zero avem:\n"

10 << STA endl;

11 #undef STA

12 }

13

14 Cutie_unu:: numere_out

15 Cutie_unu:: functie_scris(Cutie_unu:: numere_in nnumar){

16 numar = nnumar;

17 return stat i c cas t <numere_out >( numar);

18 }

19

20 void Cutie_unu:: functie_citit() const{

21 std::cout << "In Cutie_unu avem: "

22 << s ta t i c cas t < int >(numar) << "\n"

23 << std::endl;

24 }

25

26 Cutie_doi:: Cutie_doi(){

27 numar = Cutie_doi:: numere_doi();

28 }

29

30 Cutie_doi:: Cutie_doi(Cutie_doi:: numere_doi nnumar){

31 numar = nnumar;

32 }

33

34 void Cutie_doi:: functie_citit() const{

35 using namespace std;

36 cout << "In Cutie_doi avem: "

37 << s ta t i c cas t < int >( numar) << "\n"

38 << endl;

39 }

40

41 Cutie_trei:: Cutie_trei(Cutie_trei:: numere_trei nnumar){

42 numar = nnumar;

43 }

44

45 void Cutie_trei:: functie_citit() const {

46 #undef IES

47 #define IES std::cout

106

Page 107: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

48 #undef SFARSIT

49 #define SFARSIT std::endl;

50 IES << "In Cutie_trei avem: "

51 << s ta t i c cas t < int >(numar) << "\n"

52 << SFARSIT

53 #undef IES

54 #undef SFARSIT

55 }

Functiile–membru etichetate const nu pot modifica starea obiectului, cf.[41, pg. 229, 230].

Atunci cand obiectele unei clase nu sunt masive, vezi [41, p. 282], leputem folosi ca argumente standard pentru functiile–membru (ın particular,pentru constructori) — ıntotdeauna ultimele argumente, cf. [41, p. 153] —:

1 tip_date_iesire

2 nume_functie(

3 tip_unu argument_unu ,

4 tip_doi argument_doi = valoare_standard_doi ,

5 tip_trei argument_trei = valoare_standard_trei

6 );

Ultimul aspect al discutiei de fata priveste operatorul de atribuire46 = careintervine la linia 19 ın codul sursa al fisierului program.cpp. Starea obiectuluicutiedoii se modifica, valoarea campului numar fiind 34, ıncepand cu linia20. Pentru a evita o asemenea situatie, constructorul uniparametric al claseiCutie_trei a fost declarat explicit, vezi [41, p. 284].

Program:> Uneori, datele–membru manipulate ın program ocupa un spatiu consistentın memorie. De aceea, dorim ca — la sfarsitul domeniului de valabilitateal unui obiect — valorile datelor–membru ale acestuia sa fie “sterse”47. Inacest scop, limbajul C++ ne pune la dispozitie o functie–membru speciala, sianume destructorul , cu sintaxa ~numele_clasei(). In proiectul VS listatın continuare, la apelul destructorului va fi afisat un mesaj catre utilizatorulclasei. Daca destructorul nu este apelat ın mod explicit — o situatie mai rarıntalnita [22, p. 286] —, atunci programul ıl va apela ın mod automat .

Destructor: program.cpp

1 #include "diverse.h"

2 #include "cutie.h"

3

46 In limba engleza, assignment operator [41, p. 110].47Mai precis, trebuie sa “dezinitializam” obiectul clasei respective (dezinstantiere) si

apoi, daca am alocat ın mod explicit memorie pentru anumite manipulari, sa ıi returnam(dealocam) adresele de memorie folosite spatiului liber (free store), cf. [22, pg. 146, 285].

107

Page 108: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

4 int main(){

5

6 {

7 octavian :: Cutie o_cutie;

8 }//fortez apelarea destructorului!

9

10 octavian :: iesire();

11 return 0;

12 }

Destructor: cutie.h

1 #ifndef _CUTIE_

2 #define _CUTIE_

3

4 namespace octavian{

5 c la s s Cutie{

6 typedef unsigned int numere;

7 numere numar;

8 numere initializor(numere);

9 public :

10 Cutie();

11 ∼Cutie();

12 };

13 }

14

15 #endif

Destructor: cutie.cpp

1 #include "cutie.h"

2 #include <iostream >

3 #include <iomanip >

4 using namespace octavian ;

5

6 Cutie::numere

7 Cutie:: initializor(numere nnumar){

8 return nnumar;

9 }

10

11 Cutie::Cutie(){

12 numar = initializor(

13 s ta t i c cas t <numere >(2 * numere() + 100)

14 );

15 }

108

Page 109: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

16

17 Cutie::∼Cutie(){

18 std::cout << "Valoarea din Cutie este: "

19 << s ta t i c cas t < int >(numar) << ’\n’

20 << std::endl;

21 numar = numere();

22 }

Fisierele diverse.h, diverse.cpp se gasesc la pagina 104.Program:> In cazul unor constructori multiparametrici este recomandata utilizarea

unei liste de initializare a membrilor [41, pg. 247, 248], cu sintaxa:

1 nume_clasa:: nume_clasa(tip_unu param_unu ,

2 tip_doi param_doi ,

3 tip_trei param_trei

4 ) :

5 data_unu(param_unu),

6 data_doi(param_doi),

7 data_trei(param_trei) {}

De asemeni, pentru a controla aparitia obiectelor unei clase, anumiti cons-tructori pot fi declarati private, ca ın proiectul care urmeaza. Un exemplutehnic este oferit de clasa std::slice_array<T> din STL, vezi [41, p. 671].Totusi, este indicat sa dispunem macar — public—de constructorul implicitpentru a nu avea probleme atunci cand fie introducem ın program o declaratiede tipul [22, p. 279]:

1 const octavian ::Cutie0 ocutie0_constanta;

fie avem date–membru const [41, p. 244].

Constructori2: program.cpp

1 #include "diverse.h"

2 #include "alte_cutii.h"

3

4 int main(){

5 octavian :: Cutie0 ocutie0;

6 ocutie0.initializor(

7 s ta t i c cas t <octavian ::numere_gen >(25)

8 );

9 pr int f s ("\n%d\n",ocutie0.cititor ());

10 pr int f s ("\n%d\n",

11 ocutie0.initializor(

12 s ta t i c cas t <octavian ::numere_gen >(26)

13 )

14 );

109

Page 110: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

15 octavian :: Cutie1 ocutie1 (23 , -45.88);

16 pr int f s ("\n%d\n",

17 s ta t i c cas t < int >(

18 ocutie1.cititor_naturali()

19 )

20 );

21 pr int f s ("\n%f\n",

22 s ta t i c cas t <double >(

23 ocutie1.cititor_reali()

24 )

25 );

26 octavian :: iesire();

27 return 0;

28 }

Constructori2: alte_cutii.h

1 #ifndef _ALTE_CUTII_

2 #define _ALTE_CUTII_

3 namespace octavian{

4 // diverse

5

6 typedef int numere_gen;

7 c la s s Cutie0{

8 public :

9 typedef unsigned int numere;

10 numere initializor(numere_gen);

11 numere_gen cititor() const;

12 private:

13 numere numar;

14 };

15 typedef unsigned int naturali_gen;

16 typedef double reali_gen;

17 c la s s Cutie1{

18 public :

19 typedef unsigned int naturali ;

20 typedef double reali;

21 naturali_gen cititor_naturali() const;

22 reali_gen cititor_reali() const ;

23 exp l i c i t

24 Cutie1(naturali_gen nnat ,

25 reali_gen rreal = reali_gen()

26 );

27 ∼Cutie1();

110

Page 111: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

28 private:

29 Cutie1();//ctor -ul "default" este privat!

30 naturali nat;

31 reali real;

32 };

33 }

34 #endif

Constructori2: alte_cutii.cpp

1 #include "alte_cutii.h"

2 using namespace octavian ;

3

4 Cutie0:: numere

5 Cutie0:: initializor(numere_gen nnumar){

6 return (numar = s ta t i c cas t <numere >(nnumar));

7 }

8

9 numere_gen Cutie0:: cititor () const {

10 return stat i c cas t <numere_gen >(numar);

11 }

12

13 Cutie1:: Cutie1(naturali_gen nnat , reali_gen rreal) :

14 nat(nnat), real(rreal) {}//lista de initializare!

15

16 Cutie1::∼Cutie1(){

17 nat = naturali ();

18 real = reali();

19 }

20 naturali_gen Cutie1:: cititor_naturali() const {

21 return stat i c cas t <naturali_gen >(nat);

22 }

23

24 reali_gen Cutie1:: cititor_reali() const{

25 return stat i c cas t <reali_gen >(real);

26 }

Fisierele diverse.h, diverse.cpp se gasesc la pagina 104.Mentionez o regula generala: desi nu are importanta ın ce ordine declaram

membrii clasei (date, functii, sabloane, tipuri [41, p. 755]) — fireste, separandpartea public de partile private si protected —, ın cazul unor constructorimultiparametrici, initializatorii acestora trebuie dati ın ordinea pe care amales-o la declararea constructorilor respectivi, cf. [42, pg. 310, 562].

Program:> In proiectul VS listat ın cadrul sectiunii de fata, introducem operatorii

111

Page 112: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

new/new[] si delete/delete[], folositi de limbajul C++ pentru alocarea, re-spectiv dezalocarea unui spatiu de memorie, cf. [42, pg. 262, 578, 584], ınzona heap(free store). Vezi si [18, p. 610]. Trebuie precizat ca un obiect con-struit cu new va exista pana cand va fi distrus ın mod explicit cu delete [41,p. 128]. Astfel, se renunta la manipularea memoriei prin apelarea directa48

a functiilor malloc, calloc, realloc, free, etc., vezi [41, p. 577].

Manipularea memoriei: program.cpp

1 #include "diverse.h"

2 #include "vector.h"

3 using namespace octavian ;

4

5 int main(){

6 functie(

7 s ta t i c cas t <intregi_gen >(3),

8 s ta t i c cas t <reali_gen >(44.2)

9 );

10 iesire();

11 return 0;

12 }

Manipularea memoriei: vector.h

1 #ifndef _VECTOR_

2 #define _VECTOR_

3

4 namespace octavian{

5 typedef int intregi_gen;

6 typedef double reali_gen;

7 void functie(intregi_gen ,reali_gen);

8 c la s s Vector{

9 typedef int intregi;

10 typedef double reali;

11 typedef reali* preali;

12 intregi marime;

13 preali elem;

14 // marimi private , nu le implementam:

15 Vector();

16 Vector(const Vector&);

17 Vector& operator=( const Vector&);

18 reali_gen& operator[]( intregi_gen);

48Cf. [39, p. 81/67, nota de subsol 35], urmand standardul limbajului C++, implemen-tarea operatorului new ar trebui sa se bazeze pe functiile std::malloc si std::callocdin <cstdlib>.

112

Page 113: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

19 public :

20 exp l i c i t Vector(intregi_gen mmarime);

21 ∼Vector();

22 intregi_gen lungime () const ;

23 void scriere(intregi_gen , reali_gen);

24 reali_gen citire(intregi_gen) const;

25 bool sir_sau_numar() const {

26 return ( s ta t i c cas t < int >( marime) == 1);

27 }

28 };

29 }

30 #endif

Manipularea memoriei: vector.cpp

1 #include "vector.h"

2 #include <iostream >

3 #include <iomanip >

4

5 octavian ::Vector::

6 Vector(intregi_gen mmarime) :

7 marime( s ta t i c cas t <intregi >(mmarime)),

8 elem(new reali_gen[mmarime ])

9 {

10 for ( int i = 0;

11 i < s ta t i c cas t < int >( mmarime);

12 i++

13 )

14 elem[i] = 1.1;

15 std::cout << "\nAm initializat Vectorul !\n"

16 << std::endl;

17 }

18 octavian ::Vector::

19 ∼Vector(){

20 delete [] elem;

21 std::cout << "\nAm sters Vectorul !\n"

22 << std::endl;

23 }

24 octavian :: intregi_gen

25 octavian :: Vector:: lungime () const {

26 #undef CONV

27 #define CONV(a) s ta t i c cas t <intregi_gen >(a)

28 return CONV(marime);

29 #undef CONV

113

Page 114: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

30 }

31 void octavian :: Vector::

32 scriere(intregi_gen index ,reali_gen valoare){

33 typedef unsigned int ui;

34 elem[ s ta t i c cas t <ui >( index)]

35 = s ta t i c cas t <reali >( valoare);

36 }

37 octavian :: reali_gen

38 octavian :: Vector:: citire(intregi_gen index) const{

39 typedef unsigned int ui;

40 return stat i c cas t <reali_gen >(

41 elem[ s ta t i c cas t <ui >(index)]

42 );

43 }

44

45 void octavian ::

46 functie(intregi_gen index , reali_gen adaos){

47 octavian :: Vector un_vector(index);

48 i f (! un_vector.sir_sau_numar())

49 std::cout << "Vectorul are mai mult de o intrare!"

50 << std::endl;

51 for ( int i = 0;

52 i < s ta t i c cas t < int >( un_vector.lungime ());

53 i++

54 ){

55 un_vector.scriere(

56 s ta t i c cas t <intregi_gen >(i),

57 s ta t i c cas t <reali_gen >(1.2 * i) + adaos

58 );

59 std::cout << "\nun_vector[" << i << "] = "

60 << s ta t i c cas t <double >( un_vector.

61 citire( s ta t i c cas t <intregi_gen >(i))

62 )

63 << std::endl;

64 }

65 }

La fel ca pana acum, folosim fisierele diverse.h si diverse.cpp de la pagina104.

In codul sursa al fisierului vector.h apar, ıntre liniile 14 si 19, mai multemarimi (functii, operatori) pe care nu le definim — implementam —, cidoar le declaram. Fiind private, dupa cum am mai spus, aceste marimirestrictioneaza anumite utilizari ale obiectelor din clasa octavian::Vector.

114

Page 115: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

La marimile de la liniile 16–17 ma voi referi ın proiectul Visual Studiourmator. Operatorul de indexare49 [] va putea fi introdus urmand tehnicasupraıncarcarii operatorilor, pe care o voi prezenta ulterior.

Ideea de a grupa date, functii, sabloane si tipuri ıntr-un ansamblu (clasa)care detine reguli precise de accesare a acestora poarta numele de ıncapsu-larea50 informatiei, cf. [18, pg. 635, 639].

Atunci cand implementarea unei functii–membru este minimala, ca ıncazul functiei octavian::Vector::sir_sau_numar, instructiunile acesteiapot fi inserate ın declaratia clasei, ceea ce va spori performanta executieiınsa va augmenta spatiul de memorie51 ocupat de cod [42, p. 312]. In modechivalent, o functie poate fi precedata de cuvantul cheie inline, vezi [41,pg. 144, 235] si [18, pg. 617, 658].

Program:> Ne ocupam ın acest proiect VS cu Regula Celor Trei, [36] si [41, pg. 283,284], adica vom implementa initializarea–directa si initializarea–cu–copiere52

a obiectelor unei clase. Pentru prima chestiune introducem constructorulde copiere53 al clasei, care are sintaxa nume_clasa(const nume_clasa&).Cea de-a doua chestiune priveste operatorul de atribuire al clasei, cu sintaxanume_clasa& operator =(const nume_clasa&).

Regula Celor Trei: program.cpp

1 #include "diverse.h"

2 #include "perechi.h"

3

4 int main(){

5 {

6 octavian :: Pereche0 prima_pereche;

7 prima_pereche.initializare(2,3.54);

8 octavian :: Pereche0 a_doua_pereche;

9 a_doua_pereche = prima_pereche;

10 a_doua_pereche.afisare ();

11 octavian :: Pereche0 a_treia_pereche(prima_pereche);

12 a_treia_pereche.afisare ();

13 }

14 {

15 octavian :: Pereche1 prima_pereche;

49 In limba engleza, subscript operator , cf. [41, p. 286].50 In limba engleza, encapsulation [42, p. 496].51Vezi [42, p. 577], [18, p. 439, Sect. 571].52 In limba engleza, direct–initialization — adica, blocul {T a; T b(a);} — si copy–

initialization — adica, blocul {T a; T b = a;} — [39, p. 216/202, Sect. 8.5, articolele14, 15]. Aici, T desemneaza tipul datei.

53 In limba engleza, copy constructor , cf. [41, p. 271].

115

Page 116: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

16 prima_pereche.afisare ();

17 octavian :: Pereche1 a_doua_pereche(1 ,13.33);

18 a_doua_pereche.afisare ();

19 prima_pereche = a_doua_pereche;

20 prima_pereche.afisare ();

21 octavian :: Pereche1 a_treia_pereche(a_doua_pereche);

22 a_treia_pereche.afisare ();

23 }

24 octavian :: iesire();

25 #undef UN_TEXT

26 return 0;

27 }

Regula Celor Trei: perechi.h

1 #ifndef _PERECHI_

2 #define _PERECHI_

3 namespace octavian{

4 c la s s Pereche0 {

5 typedef int intregi;

6 typedef double reali;

7 intregi intreg;

8 reali real;

9 public :

10 void initializare( int , double);

11 void afisare () const;

12 };

13 c la s s Pereche1 {

14 typedef int intregi;

15 typedef double reali;

16 intregi intreg;

17 reali real;

18 Pereche1 ( int );

19 Pereche1 (double);

20 public :

21 Pereche1 ();

22 Pereche1 ( int ,double);

23 Pereche1 (const Pereche1 &);

24 Pereche1 & operator=( const Pereche1 &);

25 ∼Pereche1 ();

26 void afisare () const;

27 };

28 }

29 #endif

116

Page 117: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Regula Celor Trei: perechi.cpp

1 #include "perechi.h"

2 #include <iostream >

3 #include <iomanip >

4

5 #undef UN_TEXT

6 #define UN_TEXT \

7 std::cout << "\nMembrul intreg este: " \

8 << s ta t i c cas t < int >(intreg) \

9 << "\nMembrul real este: " \

10 << s ta t i c cas t <double >( real) \

11 << std::endl;

12 void

13 octavian :: Pereche0 ::

14 initializare( int iintreg , double rreal){

15 intreg = s ta t i c cas t <intregi >(iintreg);

16 real = s ta t i c cas t <reali >(rreal);

17 }

18 void octavian :: Pereche0 :: afisare() const{

19 UN_TEXT

20 }

21 octavian :: Pereche1 ::Pereche1 (){

22 intreg = intregi();

23 real = reali();

24 }

25 octavian :: Pereche1 ::

26 Pereche1 ( int iintreg ,double rreal){

27 intreg = s ta t i c cas t <intregi >(iintreg);

28 real = s ta t i c cas t <reali >(rreal);

29 }

30

31 octavian :: Pereche1 ::

32 Pereche1 (const octavian ::Pereche1 & o_pereche){

33 intreg = o_pereche.intreg;

34 real = o_pereche.real;

35 }

36 octavian :: Pereche1&

37 octavian :: Pereche1 ::

38 operator=( const octavian ::Pereche1 & o_pereche){

39 i f ( th is == &o_pereche)

40 return * th is ;//cazul "a == a"

41 intreg = o_pereche.intreg;

42 real = o_pereche.real;

117

Page 118: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

43 return * th is ;

44 }

45 octavian :: Pereche1 ::∼Pereche1 (){

46 intreg = intregi();

47 real = reali();

48 }

49 void octavian :: Pereche1 :: afisare() const{

50 UN_TEXT

51 }

Fisierele diverse.h, diverse.cpp se gasesc la pagina 104.In primul bloc de cod — liniile 5–13 — din fisierul program.cpp am

folosit initializarea–directa si initializarea–cu–copiere pentru obiectele cla-sei Pereche0, care nu dispune de Cei Trei, si anume destructorul – cons-tructorul de copiere – operatorul de atribuire. Totusi, compilatorul ıncearcao initializare/copiere membru–cu–membru(superficiala)54 a datelor [41, pg.229, 245]. In cel de-al doilea bloc de cod — liniile 14–23 —, initializam o-biecte ale clasei Pereche1, care se bucura de sprijinul Celor Trei! Atuncicand clasa cu care operam contine date complexe — d.ex. siruri de caractere—, copierea/initializarea superficiala nu ne este de folos!

Datele UDT cu constructor de copiere si operator de atribuire au o semantica

de tip valoare, ın timp ce datele UDT pentru care folosim copierea/initializarea

superficiala detin o semantica de tip pointer(referinta), vezi [42, p. 619]. Aceasta

idee este generalizata ın limbajul C#, unde vorbim despre tipuri valoare si tipuri

referinta, cf. [16, pg. 140, 152].

Trebuie facut un comentariu privind design-ul celor doua clase Pereche0si Pereche1: campurile lor au tipuri independente, d.ex. octavian::Pere

che0::intregi nu are nimic de a face cu octavian::Pereche1::intregi.Pentru a pastra aceasta independenta, functiile–membru octavian::Pere

che0::afisare si octavian::Pereche1::afisare au coduri-sursa identice,si evitam duplicarea codului via macro-ul UN_TEXT55. Alta varianta pre-supune universalizarea tipurilor, si anume:

1 namespace octavian{

2 typedef int intregi;

3 typedef double reali;

4 void functie_afisare(intregi ,reali);//helper!

5 c la s s Pereche0 {

6 intregi intreg;

7 reali real;

54 In limba engleza, memberwise initialization, vezi [22, p. 295], si shallow/memberwisecopy, cf. [42, pg. 619, 621].

55Tot duplicat. . .

118

Page 119: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

8 public :

9 //restul clasei , neschimbat

10 };

11 c la s s Pereche1 {

12 intregi intreg;

13 reali real;

14 Pereche1 ( int );

15 Pereche1 (double);

16 public :

17 //restul clasei , neschimbat

18 };

19 }

Acum, o implementare a functiei octavian::Pereche0::afisare poate fidata de codul:

1 void

2 octavian :: Pereche0 ::

3 afisare() const{

4 octavian :: functie_afisare(intreg ,real);

5 }

unde

1 void octavian :: functie_afisare(intregi iintreg ,

2 reali rreal){

3 std::cout << "\nMembrul intreg este: "

4 << s ta t i c cas t < int >(iintreg)

5 << "\nMembrul real este: "

6 << s ta t i c cas t <double >( rreal)

7 << std::endl;

8 }

In ce ma priveste, prefer utilizarea unui cod repetitiv introducerii de functii–helper.

O clasa pentru “perechi” profesionala este std::pair<T1,T2> din <utili

ty>, cf. [41, p. 482].In codul fisierului perechi.h, la liniile 23 si 24, apare un tip special de

date, si anume tipul referinta [22, pg. 38, 127, 130] avand sintaxa T&, undeT constituie un tip oarecare de date. Simbolul & desemneaza operatorul dereferentiere56 iar datele de tip referinta trebuie initializate, cf. [41, p. 97],fiind pseudonimele unor obiecte. De aceea, atunci cand aplicam initializarea–cu–copiere a unor obiecte UDT, vezi nota de subsol 53 de la pagina 115, au

56 In limba engleza, address-of operator [41, p. 264].

119

Page 120: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

loc urmatorii pasi: se initializeaza obiectul a, apoi obiectul b, dupa careobiectul a va fi copiat ın obiectul b!

Pentru conformitate, limbajul C++ ne permite sa aplicam tipurilor de datepredefinite57, care nu sunt clase [22, p. 600], o sintaxa tipica claselor. Evi-dent, atunci cand introducem ıntr-un calcul numarul 7 (data de tip int)este “pretentios” sa ne referim la 7 ca la o instanta a clasei int. Totusi, 7este un element al multimii ıntregilor 58, astfel ca noul concept de obiect O

al clasei C poate fi fortat sa includa si tipurile predefinite de date. Astfel,initializarea–cu–copiere are sintaxa {int x = 7;} iar initializarea–directa sescrie {int x(7);} [42, p. 311].

Ultimul detaliu al discutiei se refera la pointerul this ıntalnit la liniile 39si 43 ın codul fisierului perechi.cpp. Astfel, atunci cand exista mai multeobiecte ale clasei C, fiecare poseda o copie a starii sale. In schimb, functiile–membru apelate prin intermediul instantelor (nestatice) folosesc aceeasi copiea functiei–membru respective (din declaratia clasei). Aceasta pentru ca fie-care functie–membru contine un pointer this de tipul C*. Pointerul thisda adresa instantei din clasa C prin intermediul careia functia–membru ıncauza a fost invocata, cf. [22, pg. 234-235] si [41, p. 231]. Functiile–membrustatice nu au, bine-nteles, un pointer this, vezi [41, p. 278].

Program:> Proiectul VS de fata implementeaza clasa octavian::Sir, tinand seamade Regula Celor Trei si supraıncarcand anumiti operatori ai limbajului C++.Unul dintre campurile clasei este un pointer la un sir de caractere, deci avemnevoie de alocari/dezalocari de memorie.

In fisierul sir.h de mai jos, folosim — ıncepand cu linia 15 — cuvantulcheie friend59. Entitatile etichetate drept prietene nu sunt membre aleclasei, ınsa exista conventia stilistica sa fie declarate la ınceputul bloculuide instructiuni [22, p. 240]. Marimile friend au access direct la membriiprivati ai clasei [41, pg. 278, 760]. Functia octavian::verificare — ınfisierul program.cpp, linia 5 — ısi foloseste atributul friend pentru a testaimplementarea initializarii–directe si a initializarii–cu–copiere a obiectelorclasei.

Un comentariu privind design-ul clasei. Ca si anterior, am utilizat pseudo-nime pentru diverse tipuri de date, pregatind clasa pentru aplicarea tehniciisabloanelor , vezi e.g., [41, p. 443]. Insa, pentru a nu complica excesiv co-dul, am folosit functiile strcpy_s si strcat_s din <string.h> ımpreuna cuoperatorul static_cast<T> ın locul unor algoritmi [41, p. 529].

57 In limba engleza, built-in [41, p. 241].58 In limba engleza, integers . Valoarea 7 este o constanta literala, neadresabila; cu alte

cuvinte, ea este stocata undeva ın calculator, ınsa nu putem “ajunge” la ea, vezi [22, p.17].

59 In limba romana, prieten.

120

Page 121: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Cu ajutorul macro-ului “de depanare” VERIFICARE pot fi observate efec-tele unor decizii ın design-ul operatorilor. Mai precis, analizand lista parame-trilor formali ai acestora, ne punem ıntrebarea: cand trebuie folosit apelulprin valoare60 [18, p. 187], si cand apelul prin referinta al functiilor (opera-torilor) [18, pg. 189, 192]?

Introducand cuvantul cheie explicit ın declaratia constructorului uni-parametric, ımpiedicam conversia (const char*) =⇒ octavian::Sir dinblocul {Sir a = "mac", b("mac");}. De asemeni, fiind date obiectele {Sira,b,c;}, nu putem realiza operatia {c = a + "mac";}, desi putem calculaexpresia {c = "mac" + b;}!

Pentru “numarul magic” 30 folosit ımpreuna cu operatorul new[], vezi[41, p. 423, Sect. 15.6.1].

Supraıncarcarea operatorilor: program.cpp

1 #include "diverse.h"

2 #include "sir.h"

3

4 int main(){

5 //octavian :: verificare();

6 char* asd = "mac";

7 octavian ::Sir pel(

8 s ta t i c cas t <octavian ::ptip_caracter >(asd)

9 );

10 pel = s ta t i c cas t <octavian :: ptip_caracter >("bip")

11 + pel;

12 pel += s ta t i c cas t <octavian :: ptip_caracter >(

13 "123456789777"

14 );

15 octavian :: tip_flux_iesire* ss = & std::cout;

16 (*ss) << pel;

17 octavian :: iesire();

18 return 0;

19 }

Supraıncarcarea operatorilor: sir.h

1 #ifndef _SIR_

2 #define _SIR_

3 #include <iostream >

4 #include <iomanip >

5 namespace octavian{

6 typedef char tip_caracter;

60 In limba engleza, pass–by–value [22, p. 125].

121

Page 122: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

7 typedef tip_caracter* ptip_caracter;

8 typedef unsigned int tip_natural;

9 typedef int tip_intreg;

10 typedef tip_intreg& rtip_intreg;

11 typedef std:: ostream tip_flux_iesire;

12 typedef tip_flux_iesire& rtip_flux_iesire;

13

14 c la s s Sir{

15 fr iend void verificare();

16 fr iend tip_flux_iesire;

17 fr iend rtip_flux_iesire

18 operator <<(rtip_flux_iesire ,Sir&);

19 fr iend Sir

20 operator+( const ptip_caracter ,Sir);

21 public :

22 Sir();

23 exp l i c i t Sir(const ptip_caracter);

24 Sir(const Sir&);

25 ∼Sir();

26 Sir& operator=( const Sir&);

27 Sir& operator+=( const Sir&);

28 Sir& operator+=( const ptip_caracter);

29 Sir operator+( const Sir&) const ;

30 private:

31 tip_natural lungimea;

32 ptip_caracter sirul;

33 Sir(tip_natural);

34 Sir& operator+=( const rtip_intreg);

35 tip_intreg operator!() const ;

36 tip_caracter operator[]( tip_intreg);

37 };

38 }

39 #endif

Supraıncarcarea operatorilor: sir.cpp

1 #include "sir.h"

2 #include <string.h>

3 #include <errno.h>

4

5 #undef VERIFICARE

6 #define VERIFICARE 1

7 #undef VERIFICARE

8

122

Page 123: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

9 octavian ::Sir::Sir(){

10 s t a t i c tip_natural

11 numar_standard = s ta t i c cas t <tip_natural >(

12 s i z eo f ("eusebiu") - 1

13 );

14 lungimea = numar_standard;

15 int numar_intern = s ta t i c cas t < int >( numar_standard)

16 + 1 /* + 30 */ ;

17 s t a t i c ptip_caracter sir_standard = "eusebiu";

18 sirul = new tip_caracter[numar_intern];

19 strcpy s ( s ta t i c cas t <char*>(sirul),

20 numar_intern ,

21 s ta t i c cas t <char*>(sir_standard)

22 );

23 #i fd e f VERIFICARE

24 pr int f s ("\n=====\n"

25 "Ctor. fara argumente pentru Sir!\n"

26 "Datele standard: sirul - %s, lungimea - %d."

27 "\n=====\n",

28 s ta t i c cas t <char*>(sirul),

29 s ta t i c cas t < int >( lungimea )

30 );

31 #endif

32 }

33 octavian ::Sir::Sir(const ptip_caracter ssirul){

34 int numar_intern = s ta t i c cas t < int >(

35 std:: str len (ssirul)

36 )

37 + 1 /* + 30 */ ;

38 lungimea = s ta t i c cas t <tip_natural >(

39 numar_intern - 1 /* - 30 */

40 );

41 sirul = new octavian :: tip_caracter[numar_intern];

42 strcpy s ( s ta t i c cas t <char*>(sirul),

43 numar_intern ,

44 s ta t i c cas t <char*>(ssirul)

45 );

46 #i fd e f VERIFICARE

47 pr int f s ("\n=====\n"

48 "Ctor. cu argument secv. pentru Sir!\n"

49 "Datele sale: sirul - %s, lungimea - %d."

50 "\n=====\n",

51 s ta t i c cas t <char*>(sirul),

123

Page 124: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

52 s ta t i c cas t < int >( lungimea ));

53 #endif

54 }

55 octavian ::Sir::Sir(const Sir& un_sir){

56 lungimea = un_sir.lungimea ;

57 int numar_intern = s ta t i c cas t < int >( lungimea)

58 + 1 /* + 30 */ ;

59 sirul = new octavian :: tip_caracter[numar_intern];

60 strcpy s ( s ta t i c cas t <char*>(sirul),

61 numar_intern ,

62 s ta t i c cas t <char*>(un_sir.sirul)

63 );

64 #i fd e f VERIFICARE

65 pr int f s ("\n=====\n"

66 "Ctor. cu argument Sir& pentru Sir!\n"

67 "Datele sale: sirul - %s, lungimea - %d."

68 "\n=====\n",

69 s ta t i c cas t <char*>(sirul),

70 s ta t i c cas t < int >( lungimea )

71 );

72 #endif

73 }

74 octavian ::Sir::∼Sir(){

75

76 #i fd e f VERIFICARE

77 pr int f s ("\n=====\n"

78 "Dtor. pentru Sir!\n"

79 "Datele inaintea stergerii: "

80 "sirul - %s, lungimea - %d."

81 "\n=====\n",

82 s ta t i c cas t <char*>(sirul),

83 s ta t i c cas t < int >( lungimea )

84 );

85 #endif

86 delete [] sirul;

87 lungimea = tip_natural();

88 }

89 octavian ::Sir&

90 octavian ::Sir::

91 operator=( const octavian ::Sir& ssir){

92 i f ( th is == &ssir){

93 #i fd e f VERIFICARE

94 pr int f s ("\n=====\n"

124

Page 125: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

95 "Cazul \"a == a\" la atribuire!"

96 "\n=====\n"

97 );

98 #endif

99 return * th is ;

100 }

101 delete [] sirul;

102 lungimea = ssir.lungimea ;

103 int numar_intern = s ta t i c cas t < int >( lungimea )

104 + 1 /* + 30 */ ;

105 sirul = new octavian :: tip_caracter[numar_intern];

106 strcpy s ( s ta t i c cas t <char*>(sirul),

107 numar_intern ,

108 s ta t i c cas t <char*>(ssir.sirul));

109 #i fd e f VERIFICARE

110 pr int f s ("\n=====\n"

111 "Oper. de atribuire pentru Sir!\n"

112 "Dupa aplicare , datele sunt: "

113 "sirul - %s, lungimea - %d."

114 "\n=====\n",

115 s ta t i c cas t <char*>(sirul),

116 s ta t i c cas t < int >( lungimea)

117 );

118 #endif

119 return * th is ;

120 }

121 octavian ::Sir&

122 octavian ::Sir::

123 operator+=( const octavian ::Sir& un_sir){

124 lungimea += un_sir.lungimea;

125 int numar_intern = s ta t i c cas t < int >( lungimea )

126 + 1 /* + 30 */ ;

127 ptip_caracter sir_intern = new octavian ::

128 tip_caracter[numar_intern];

129 strcpy s ( s ta t i c cas t <char*>(sir_intern),

130 numar_intern ,

131 s ta t i c cas t <char*>(sirul)

132 );

133 s t rcat s ( s ta t i c cas t <char*>(sir_intern),

134 numar_intern ,

135 s ta t i c cas t <char*>(un_sir.sirul)

136 );

137 delete [] sirul;

125

Page 126: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

138 sirul = new tip_caracter[numar_intern];

139 strcpy s ( s ta t i c cas t <char*>(sirul),

140 numar_intern ,

141 s ta t i c cas t <char*>(sir_intern)

142 );

143 #i fd e f VERIFICARE

144 pr int f s ("\n=====\n"

145 "Oper. \"+=\" cu argument Sir& "

146 "pentru Sir!\n"

147 "Dupa aplicare , datele sunt: "

148 "sirul - %s, lungimea - %d."

149 "\n=====\n",

150 s ta t i c cas t <char*>(sirul),

151 s ta t i c cas t < int >( lungimea)

152 );

153 #endif

154 delete [] sir_intern;

155 return * th is ;

156 }

157 octavian ::Sir&

158 octavian ::Sir::

159 operator+=( const ptip_caracter alt_sir){

160 lungimea += s ta t i c cas t <tip_natural >(

161 std:: str len (alt_sir)

162 );

163 int numar_intern = s ta t i c cas t < int >(

164 lungimea

165 )

166 + 1 /* + 30 */ ;

167 ptip_caracter sir_intern = new octavian ::

168 tip_caracter[numar_intern];

169 strcpy s ( s ta t i c cas t <char*>(sir_intern),

170 numar_intern ,

171 s ta t i c cas t <char*>(sirul)

172 );

173 s t rcat s ( s ta t i c cas t <char*>(sir_intern),

174 numar_intern ,

175 s ta t i c cas t <char*>(alt_sir)

176 );

177 delete [] sirul;

178 sirul = new tip_caracter[numar_intern];

179 strcpy s ( s ta t i c cas t <char*>(sirul),

180 numar_intern ,

126

Page 127: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

181 s ta t i c cas t <char*>(sir_intern)

182 );

183 #i fd e f VERIFICARE

184 pr int f s ("\n=====\n"

185 "Oper. \"+=\" cu argument Sir& "

186 "pentru Sir!\n"

187 "Dupa aplicare , datele sunt: "

188 "sirul - %s, lungimea - %d."

189 "\n=====\n",

190 s ta t i c cas t <char*>(sirul),

191 s ta t i c cas t < int >( lungimea)

192 );

193 #endif

194 delete [] sir_intern;

195 return * th is ;

196 }

197 octavian ::Sir

198 octavian ::Sir::

199 operator+( const Sir& iar_sir) const{

200 #i fd e f VERIFICARE

201 pr int f s ("\n=====\n"

202 "Oper. \"+\" - membru "

203 "este apelat!\n"

204 "Ce se intampla aici:"

205 );

206 #endif

207 Sir rezultat = * th is ;

208 rezultat += iar_sir;

209 #i fd e f VERIFICARE

210 pr int f s ("Final de apel pentru oper.\"+\""

211 " - membru!"

212 "\n=====\n"

213 );

214 #endif

215 return rezultat;

216 }

217 octavian ::Sir

218 octavian ::

219 operator+( const ptip_caracter ssir ,Sir sirr){

220 tip_natural numar_lucru = sirr.lungimea

221 + s ta t i c cas t <tip_natural >(

222 std:: str len (ssir)

223 );

127

Page 128: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

224 int numar_intern = s ta t i c cas t < int >( numar_lucru)

225 + 1 /* + 30 */ ;

226 ptip_caracter sir_intern = new octavian ::

227 tip_caracter[numar_intern];

228 strcpy s ( s ta t i c cas t <char*>(sir_intern),

229 numar_intern ,

230 s ta t i c cas t <char*>(ssir)

231 );

232 s t rcat s ( s ta t i c cas t <char*>(sir_intern),

233 numar_intern ,

234 s ta t i c cas t <char*>(sirr.sirul)

235 );

236 #i fd e f VERIFICARE

237 pr int f s ("\n=====\n"

238 "Oper. \"+\" -nemembru este apelat!\n"

239 "Ce se intampla aici:");

240 pr int f s ("\n=====\n"

241 "Actiuni interne !\n"

242 "Datele intermediare sunt: "

243 "sirul - %s, lungimea - %d."

244 "\n=====\n",

245 s ta t i c cas t <char*>(sir_intern),

246 s ta t i c cas t < int >( numar_lucru)

247 );

248 #endif

249 octavian ::Sir alt_sir(sir_intern);

250 delete [] sir_intern;

251 #i fd e f VERIFICARE

252 pr int f s ("Final de apel pentru oper.\"+\""

253 " - nemembru !"

254 "\n=====\n"

255 );

256 #endif

257 return alt_sir;

258 }

259 octavian :: rtip_flux_iesire

260 octavian ::

261 operator <<(octavian :: rtip_flux_iesire os, Sir& ss){

262 return os << "\nSirul este: "

263 << s ta t i c cas t <char*>(ss.sirul) << ’\n’

264 << "Lungimea sa este: "

265 << s ta t i c cas t < int >(ss.lungimea)

266 << std::endl;

128

Page 129: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

267 }

268 void octavian :: verificare(){

269 //verific implementarea:

270 Sir a("comert");

271 Sir aa = Sir();

272 Sir b(a);

273 Sir c = a + b;

274 c += aa;

275 octavian :: tip_flux_iesire*

276 ss = & std::cout;

277 (*ss) << c;

278 }

Program:> In continuare, implementam minimal clasa octavian::Cuvant pentru aafisa ın consola informatii despre diverse staruri de cinema — ele au legaturacu. . .matematica61 —. Unul dintre campurile clasei reprezinta o data de tipoctavian::Sir din proiectul VS precedent. El va ınmagazina prenumeleacestor staruri. Deoarece durata de viata a obiectelor de tip Sir este con-trolata de destructorul clasei ın cauza, clasa Cuvant nu are destructor iarproliferarea obiectelor de tip Cuvant este supervizata de un contor static.

Proiectul prezent se compune din fisierele program.cpp, diverse.h, diverse.cpp — vezi pagina 104—, sir.h, sir.cpp, cuvant.h, cuvant.cpp.

Atunci cand un obiect al clasei Cuvant are drept camp un obiect al claseiSir, spunem ca clasa Cuvant este ıntr-o relatie de tip are–un62 (cu clasa)Sir.

Relatii has-a: program.cpp

1 #include "diverse.h"

2 #include "sir.h"

3 #include "cuvant.h"

4

5 int main(){

6 octavian :: Cuvant McKellar("Danica" ,33);

7 McKellar .afisare ();

8 octavian ::Sir Portman("Natalie");

9 octavian :: Cuvant Oscar(Portman ,31);

10 Oscar.afisare ();

11 octavian :: Cuvant

12 doiMcKellar(Portman ,31),

13 treiMcKellar("Danica" ,33)

14 /*,patruMcKellar(Portman ,31)*/;

61Let’s google them!62 In limba engleza, has–a relationship [41, p. 741].

129

Page 130: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

15 octavian :: iesire();

16 return 0;

17 }

Relatii has-a: cuvant.h

1 #ifndef _CUVANT_

2 #define _CUVANT_

3 #include "sir.h"

4 namespace octavian{

5 typedef unsigned int nr_natural;

6 c la s s Sir;// declaratia clasei Sir

7 c la s s Cuvant{

8 public :

9 Cuvant(const char*, nr_natural);

10 Cuvant(const Sir&, nr_natural);

11 void afisare () const;

12 void control ();

13 private:

14 Cuvant();

15 Cuvant(const char*);

16 Cuvant(const Sir&);

17 Cuvant(nr_natural);

18 nr_natural numar_poz;

19 Sir sir_car;

20 };

21 }

22 #endif

Relatii has-a: cuvant.cpp

1 #include "cuvant.h"

2 #include "sir.h"

3 #include <iostream >

4 #include <iomanip >

5

6 #undef CONTROLOR

7 #define CONTROLOR 1

8 #undef CONTROLOR

9

10 void octavian :: Cuvant:: control (){

11 s t a t i c

12 nr_natural contor = s ta t i c cas t <nr_natural >(1);

13 #i fd e f CONTROLOR

14 pr int f s ("\n+++%d+++\n",

130

Page 131: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

15 s ta t i c cas t < int >( contor)

16 );

17 #endif

18 i f (contor == 5){

19 pr int f s ("\n=============\n"

20 "\nPrea multe cuvinte ... "

21 "La revedere !"

22 "\n=============\n"

23 );

24 exit (EXIT FAILURE);

25 }

26 i f (contor++ == 4)

27 pr int f s ("\n=============\n"

28 "Nu mai definiti alt Cuvant!"

29 "\n=============\n"

30 );

31 }

32 octavian ::Cuvant::

33 Cuvant(const char* ssir , nr_natural nr) :

34 sir_car( const cast <octavian ::ptip_caracter >(ssir)),

35 numar_poz(nr) { control (); }

36 octavian ::Cuvant::

37 Cuvant(const Sir& ssir , nr_natural nnr){

38 control ();

39 sir_car = ssir;

40 numar_poz = nnr;

41 }

42 void octavian :: Cuvant::

43 afisare () const {

44 std::cout << "Pozitia in clasament: "

45 << s ta t i c cas t < int >( numar_poz) << ’\n’

46 << "Detalii :\n"

47 << const cast <Sir&>(sir_car)

48 << std::endl;

49 }

Operatorul const_cast<T> este folosit pentru “ındepartarea” califica-tivului const al unei date de tip T, vezi [41, p. 131].

Program:> (Let’s get. . .math!) Reamintesc identitatea dublului produs vectorial (Gra-ssmann)

(u× v)× w = (u · w)v − (v · w)u, (1)

unde u, v si w sunt vectori liberi ın spatiul fizic (SF), cf. [28, p. 61]. In pro-iectul VS urmator implementam clasa octavian::VectLiber, cu care vom

131

Page 132: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

modela vectorii liberi: u = xi+yj+zk ≡ (x, y, z) ∈ R3. Deoarece ın limbajul

C++ nu este permisa introducerea de noi operatori, ci numai supraıncarcareacelor predefiniti, vezi [22, p. 304], [41, p. 265], vom folosi operatorii “%” si “/”pentru a defini produsul scalar , respectiv produsul vectorial al vectorilor liberi(directiilor) din SF. La randul sau, forma determinant va fi implementata defunctia octavian::m.

Proiectul este alcatuit din fisierele program.cpp, headerulnostru.h —pagina 5 —, format_afisare.h, format_afisare.cpp — paginile 69, 71 —si vectliber.h, vectliber.cpp, listate ın continuare.

Cum “functioneaza” codul din programul principal program.cpp: afisamın consola componentele x, y si z pentru cei doi vectori liberi reprezentatide membrul stang, respectiv membrul drept al identitatii (1). Folosim douatipuri de date pentru cei trei vectori liberi din identitate: mai ıntai compo-nente int, apoi componente double. Marea dificultate a calculelor de acestfel o constituie precizia rezultatelor, deci avem nevoie de o functie “de for-mat” — nu uitati sa activati instructiunea #undef VERIFICARE din codulsursa al fisierului format_afisare.cpp! —.

Un produs scalar profesional este algoritmul inner_product<T1,T2,T3>din <numeric>, vezi [41, p. 683].

Identitatea lui Grassmann: program.cpp

1 #include "headerulnostru.h"

2 #include "vectliber.h"

3 #include <iostream >

4 #include <iomanip >

5

6 int main(){

7 system("cls");

8 octavian :: VectLiber unu(1,2,3),

9 doi(0,4,-1),

10 trei(7,5,6);

11 octavian :: verificare(unu ,doi ,trei ,5);

12 std::cout << ’\n’

13 << std::endl;

14 octavian :: verificare(unu ,doi ,trei ,30);

15 std::cout << "\n\n++++++++++\n"

16 << std::endl;

17 octavian :: VectLiber uunu(2 ,3 ,44.5),

18 ddoi( -2.12 ,8.09 ,1),

19 ttrei(0.002 ,1.3, 76.5);

20 octavian :: verificare(uunu ,ddoi ,ttrei ,5);

21 std::cout << ’\n’

132

Page 133: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

22 << std::endl;

23 octavian :: verificare(uunu ,ddoi ,ttrei ,30);

24 LA_REVEDERE

25 return 0;

26 }

Identitatea lui Grassmann: vectliber.h

1 #ifndef _VECTLIBER_

2 #define _VECTLIBER_

3 namespace octavian{

4 c la s s VectLiber{

5 fr iend void verificare(VectLiber&,

6 VectLiber&,

7 VectLiber&,

8 unsigned int

9 );

10 fr iend

11 void afis_verificare(VectLiber&,unsigned int );

12 fr iend bool operator==( VectLiber&,VectLiber&);

13 fr iend VectLiber operator+( VectLiber&,VectLiber&);

14 fr iend VectLiber operator -( VectLiber&,VectLiber&);

15 fr iend VectLiber operator*(double ,VectLiber&);

16 fr iend VectLiber operator*( VectLiber&,double);

17 fr iend double operator%( VectLiber&,VectLiber&);

18 fr iend VectLiber operator/( VectLiber&,VectLiber&);

19 fr iend double m(VectLiber&,VectLiber&,VectLiber&);

20 public :

21 VectLiber();

22 VectLiber(double ,double ,double);

23 VectLiber(const VectLiber&);

24 ∼VectLiber();

25 VectLiber& operator=( const VectLiber&);

26 private:

27 VectLiber& operator+=( const VectLiber&);

28 VectLiber& operator -=( const VectLiber&);

29 double operator[]( int );

30 double operator()();

31 double* componente;

32 };

33 }

34 #endif

133

Page 134: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Identitatea lui Grassmann: vectliber.cpp

1 #include "vectliber.h"

2 #include "format_afisare.h"

3 #include <iostream >

4 #include <iomanip >

5 octavian :: VectLiber:: VectLiber(){

6 componente = new double[3];

7 for ( int i = 0; i < 3; i++)

8 componente[i] = double();

9 }

10 octavian :: VectLiber::

11 VectLiber(double x, double y, double z){

12 componente = new double[3];

13 componente[0] = x;

14 componente[1] = y;

15 componente[2] = z;

16 }

17 octavian :: VectLiber::

18 VectLiber(const VectLiber& un_vect){

19 componente = new double[3];

20 for ( int i = 0; i < 3; i++)

21 componente[i] = un_vect.componente[i];

22 }

23 octavian :: VectLiber::∼VectLiber(){

24 delete [] componente;

25 }

26 octavian :: VectLiber&

27 octavian :: VectLiber::

28 operator=( const octavian :: VectLiber& vlib){

29 i f ( th is == &vlib) return * th is ;

30 delete [] componente;

31 componente = new double[3];

32 for ( int i = 0; i < 3; i++)

33 componente[i] = vlib.componente[i];

34 return * th is ;

35 }

36 octavian :: VectLiber

37 octavian ::

38 operator+( octavian :: VectLiber& vlib ,

39 octavian :: VectLiber& vvlib

40 ){

41 VectLiber lucru;

42 for ( int i = 0; i < 3; i++)

134

Page 135: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

43 lucru.componente[i] = vlib.componente[i]

44 + vvlib.componente[i];

45 return lucru;

46 }

47 octavian :: VectLiber

48 octavian ::

49 operator -( octavian :: VectLiber& vlib ,

50 octavian :: VectLiber& vvlib

51 ){

52 VectLiber lucru;

53 for ( int i = 0; i < 3; i++)

54 lucru.componente[i] = vlib.componente[i]

55 - vvlib.componente[i];

56 return lucru;

57 }

58 octavian :: VectLiber

59 octavian ::

60 operator*(double scal ,VectLiber& vlibb){

61 VectLiber lucru = vlibb;

62 for ( int i = 0; i < 3; i++)

63 lucru.componente[i] *= scal;

64 return lucru;

65 }

66 octavian :: VectLiber

67 octavian ::

68 operator*( VectLiber& vlib ,double scal){

69 VectLiber lucru = scal * vlib;

70 return lucru;

71 }

72 double

73 octavian ::

74 operator%( VectLiber& primul ,

75 VectLiber& aldoilea

76 ){

77 double numar = double();

78 for ( int i = 0; i < 3; i++)

79 numar += primul.componente[i]

80 * aldoilea.componente[i];

81 return numar;

82 }

83 octavian :: VectLiber

84 octavian ::

85 operator/( VectLiber& primul ,

135

Page 136: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

86 VectLiber& aldoilea

87 ){

88 VectLiber vlb;

89 vlb.componente[0] = primul.componente[1]

90 * aldoilea.componente[2]

91 - aldoilea.componente[1]

92 * primul.componente[2];

93 vlb.componente[1] = primul.componente[2]

94 * aldoilea.componente[0]

95 - aldoilea.componente[2]

96 * primul.componente[0];

97 vlb.componente[2] = primul.componente[0]

98 * aldoilea.componente[1]

99 - aldoilea.componente[0]

100 * primul.componente[1];

101 return vlb;

102 }

103 double

104 octavian ::

105 m(VectLiber& unu ,VectLiber& doi ,VectLiber& trei){

106 double lucru = double();

107 lucru += unu.componente[0] * doi.componente[1]

108 * trei.componente[2];

109 lucru += unu.componente[2] * doi.componente[0]

110 * trei.componente[1];

111 lucru += unu.componente[1] * doi.componente[2]

112 * trei.componente[0];

113 lucru -= unu.componente[2] * doi.componente[1]

114 * trei.componente[0];

115 lucru -= unu.componente[0] * doi.componente[2]

116 * trei.componente[1];

117 lucru -= unu.componente[1] * doi.componente[0]

118 * trei.componente[2];

119 return lucru;

120 }

121 bool

122 octavian ::

123 operator==( VectLiber& stanga ,VectLiber& dreapta){

124 for ( int i = 0; i < 3; i++){

125 i f (

126 stanga.componente[i] != dreapta.componente[i]

127 )

128 return f a l s e ;

136

Page 137: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

129 }

130 return true;

131 }

132 void octavian :: verificare(octavian :: VectLiber& a,

133 octavian :: VectLiber& b,

134 octavian :: VectLiber& c,

135 unsigned int precz){

136 VectLiber unu = (a/b)/c;

137 VectLiber doi = ((a%c)*b) -((b%c)*a);

138 afis_verificare(unu ,precz);

139 afis_verificare(doi ,precz);

140 i f (unu == doi)

141 std::cout << "Egali!"

142 << std::endl;

143 e l se

144 std::cout << "Inegali!"

145 << std::endl;

146 }

147 void octavian :: afis_verificare(VectLiber& vvlib ,

148 unsigned int prec){

149 std::cout << "\n==========="

150 << std::endl;

151 for ( int i = 0; i < 3; ++i)

152 std::cout << "Coordonata nr. " << i

153 << " este: "

154 << vvlib.componente[i]

155 << octavian ::Afisare (& std::cout ,prec)

156 << std::endl;

157 std::cout << "=============\n"

158 <<std::endl;

159 }

Program:> In proiectul VS anterior, ın afara afisarilor produse de functia de for-mat, a trebuit sa departajam anumite blocuri de date din consola “manual”,introducand “randuri decorative”. De aceea, ın programul de mai jos imple-mentam o formatare pentru mesajele “generale” de afisat ın consola.

Cu aceasta ocazie, revin la functia de tip getch a profesorului Stroustrup— vezi pagina 82 —. Aceasta seteaza la “buna” starea fluxului-de-intrare,apoi citeste urmatorul caracter (din flux). Varianta functiei, implementataın fisierul diverse.cpp de la pagina 104, si anume octavian::iesire, faceacelasi lucru, ınsa nu stocheaza caracterul citit — fluxurile de intrare si iesirefolosesc buffere pentru operatiile efectuate cu ele, vezi [41, p. 642] —. Cese ıntampla ınsa daca, dupa ce a “sarit” peste caracterul ın cauza, functia

137

Page 138: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

iesire mai gaseste ın bufferul fluxului std::cin caractere necitite? Evident,ea ısi va ınceta executia, iar consola se va ınchide! O asemenea situatie poateavea loc ın timpul executiei programului de fata. Pentru a ımpiedica ınchi-derea consolei, modificam implementarea functiei iesire — vezi codul dinfisierul diverse.cpp listat ın continuare —, impunand golirea bufferului laınceputul executiei sale [41, p. 644]. Astfel, functia va trebui sa ıi cearautilizatorului introducerea unui caracter de la tastatura.

Un alt aspect al proiectului de fata ıl constituie supraıncarcarea functieioctavian::afisare, permisa de limbajul C++.

De asemeni, folosim date de tip std::string pentru a colecta sirul decaractere introdus de la tastatura pana la primul caracter “spatiu”, respectivfunctia get din <istream> pentru a citi caracterele de dupa spatiile goale[41, p. 619].

Afisari formatate: program.cpp

1 #include "diverse.h"

2 #include "afisare_gen.h"

3 #include <iostream >

4 #include <iomanip >

5 #include <string >

6

7 int main(){

8 std::cout << "Scrieti un cuvant cu maxim "

9 "cinsprezece litere: "

10 << std::endl;

11 /*---

12 Ce se intampla daca tastati:

13 acdert 23w

14 ---*/

15 std:: str ing cuvant;

16 std:: cin >> cuvant;

17 std::cout << "\nAti scris:\n"

18 << std::endl;

19 octavian ::afisare(cuvant);

20 octavian ::afisare (3,"intrebare");

21 /*for(int i = 1; i < 6; i++)

22 octavian :: afisare (3,"raspuns ");*/

23 char sir[] = "Un serif la panda!";

24 int numar = s ta t i c cas t < int >( countof(sir) / 2);

25 std::cout << "Scrieti un cuvant cu minim "

26 << numar

27 << " litere.\n"

28 "Daca este mai scurt , "

138

Page 139: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

29 "incheiati -l cu litera "

30 "\"x\": "

31 << std::endl;

32 std:: cin.sync();

33 std:: cin. c lear ();

34 std:: cin.

35 get(sir ,

36 s ta t i c cas t <std:: streamsize >(numar),

37 ’x’

38 );

39 octavian ::afisare (3,sir);

40 octavian ::iesire();

41 return 0;

42 }

Afisari formatate: diverse.cpp

1 #include "diverse.h"

2 #include <iostream >

3 #include <iomanip >

4

5 void octavian :: iesire(){

6 for (

7 std:: cin.sync(),

8 std:: cin. c lear (),

9 std::cout << "\nApasati ENTER"

10 " pentru a incheia: "

11 << std::endl ,

12 std:: cin. ignore();;

13 ) return;

14 }

Afisari formatate: afisare_gen.h

1 #ifndef _AFISARE_GEN_

2 #define _AFISARE_GEN_

3 #include <string >

4

5 namespace octavian{

6 void afisare( std:: str ing &);

7 void afisare(unsigned int ,const char*);

8 void desen(unsigned int );

9 }

10 #endif

139

Page 140: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Afisari formatate: afisare_gen.cpp

1 #include "afisare_gen.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5 #include <string >

6

7 void

8 octavian ::desen(unsigned int variab){

9 std::cout.width(variab);

10 std::cout. f i l l (’+’);

11 std::cout << "";

12 }

13

14 void

15 octavian :: afisare( std:: str ing & ccuvant){

16 unsigned int

17 numar = s ta t i c cas t <unsigned int >( ccuvant. s i ze ());

18 i f (( numar == 0) || (numar > 15)){

19 std::cout << "Prea multe litere !!!!!\n";

20 octavian :: iesire();

21 exit (EXIT FAILURE);

22 }

23 int lungime_afis = 12;

24 i f ((numar % 2) == 1) lungime_afis++;

25 int offset = lungime_afis - numar;

26 octavian ::desen(

27 s ta t i c cas t <unsigned int >( lungime_afis)

28 );

29 std::cout << std::endl;

30 octavian ::desen(

31 s ta t i c cas t <unsigned int >( offset /2)

32 );

33 std::cout << ccuvant;

34 octavian ::desen(

35 s ta t i c cas t <unsigned int >( offset /2)

36 );

37 std::cout << std::endl;

38 octavian ::desen(

39 s ta t i c cas t <unsigned int >( lungime_afis)

40 );

41 std::cout << ’\n’ << std::endl;

42 }

140

Page 141: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

43

44 void

45 octavian ::

46 afisare(unsigned int nnr , const char* ssir){

47 i f (nnr == 1){//mod de apel: afisare (1," ");

48 std:: cin.unsetf ( std:: ios base :: skipws);

49 return;

50 }

51 e l se {

52 s t a t i c unsigned int contor = 1;

53 i f (contor++ < 5){

54 std:: str ing sir_intern = ssir;

55 octavian ::afisare(sir_intern);

56 }

57 e l se {

58 pr int f s ("\nPrea multe apeluri "

59 "\"afisare \"!"

60 );

61 octavian :: iesire();

62 exit (EXIT FAILURE);

63 }

64 }

65 }

Program:> (Let’s get math. . . again!) Utilizam clasa octavian::VectLiber ca sa pro-bam urmatoarea identitate fundamentala privind produsul mixt a trei vectoriliberi din SF [28, p. 47]:

(u, v, w) = (u× v) · w = (v × w) · u = (w × u) · v.

Pentru aceasta vom folosi pointeri la functii [20, p. 201], a caror initia-lizare poate fi facuta ca mai jos:

1 extern double octavian :: o_functie( int unu ,char doi);

2 double (* nume_pointer)( int ,char) = octavian :: o_functie;

Reamintesc ca tipul unei functii este dat de tipurile argumentelor sale63

si de tipul valorilor returnate [22, p. 201]. De asemeni, apelul unei func-tii se compune din numele functiei, operatorul de apel (), respectiv listaparametrilor reali . Astfel, luat de unul singur, numele functiei constituie unpointer la o functie de tipul curent, cf. [22, p. 202]. Prin suprasarcina64 func-tiei ıntelegem timpul de ıncarcare/descarcare a informatiilor pe stiva [22, p.

63Lista argumentelor unei functii este numita uneori si semnatura functiei. In limbaengleza, signature [22, p. 121].

64 In limba engleza, overhead .

141

Page 142: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

112], care — la apelul prin valoare al functiei, atunci cand compilatorul ıitransmite acesteia cate o copie a fiecarui parametru real — poate fi semni-ficativ [18, p. 183]. Limbajul C++ introduce datele de tip referinta, T& [41,p. 97], unde T este un tip predefinit sau UDT, pentru a usura apelul prinreferinta al functiilor. Astfel, ın locul apelului a la limbajul C:

1 tip1 variabila1 = valoare_initiala1;

2 tip2 variabila2 = valoare_initiala2;

3

4 tip_date o_functie(tip1 *argument1 , tip2 *argument2)

5 {/* implementare */};

6 o_functie(&variabila1 , &variabila2);

unde argument1 este parametru formal si &variabila1 parametru real, pu-tem scrie ca

1 tip1 variabila1 = valoare_initiala1;

2 tip2 variabila2 = valoare_initiala2;

3

4 tip_date o_functie(tip1& argument1 , tip2& argument2)

5 {/* implementare */};

6 o_functie(variabila1 , variabila2);

Proiectul se compune din fisierele program.cpp, headerulnostru.h, diverse.h, diverse.cpp — de la pagina 139 —, vectliber.h, vectliber.cpp,format_afisare.h, format_afisare.cpp — activati instructiunea #undef

VERIFICARE din codul sursa al fisierului format_afisare.cpp! —, prodmixt.h, prodmixt.cpp.

Pointeri la functii: program.cpp

1 #include "diverse.h"

2 #include "vectliber.h"

3 #include "prodmixt.h"

4 #include <iostream >

5 #include <iomanip >

6

7 int main(){

8 system("cls");

9 octavian :: VectLiber unu(1,2,3);

10 octavian :: VectLiber doi(0,4,-1);

11 octavian :: VectLiber trei(7,5,6);

12 std::cout << "Testam identitatea lui Grassmann:"

13 << std::endl;

14 octavian :: verificare(unu ,doi ,trei ,5);

15 std::cout << "\n\n(unu x doi) . trei =" << std::endl;

142

Page 143: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

16 octavian :: test_mix (unu ,doi ,trei ,octavian ::pm ,10);

17 std::cout << "\n\n(doi x trei) . unu =" << std::endl;

18 octavian :: test_mix (doi ,trei ,unu ,octavian ::pm ,10);

19 std::cout << "\n\n(trei x unu) . doi =" << std::endl;

20 octavian :: test_mix (trei ,unu ,doi ,octavian ::pm ,10);

21 std::cout << "\n\n(unu ,doi ,trei) =" << std::endl;

22 octavian :: test_mix (unu ,doi ,trei ,octavian ::m,10);

23 std::cout << std::endl;

24 octavian :: iesire();

25 return 0;

26 }

Pointeri la functii: prodmixt.h

1 #ifndef _PRODMIXT_

2 #define _PRODMIXT_

3 #include "vectliber.h"

4 namespace octavian{

5 typedef octavian :: VectLiber& tip;

6 typedef unsigned int ui;

7 typedef double(* functii)(tip ,tip ,tip);

8 double pm(tip ,tip ,tip);

9 void test_mix (tip ,tip ,tip ,functii ,ui);

10 }

11 #endif

Pointeri la functii: prodmixt.cpp

1 #include "prodmixt.h"

2 #include "vectliber.h"

3 #include "format_afisare.h"

4 #include <iostream >

5 #include <iomanip >

6

7 double octavian ::pm(tip a,tip b,tip c){

8 octavian :: VectLiber lucru = a / b;

9 return (lucru % c);

10 }

11 void

12 octavian ::

13 test_mix (tip a,tip b,tip c,functii f,ui prec){

14 double raspuns = f(a,b,c);

15 std::cout << raspuns

16 << octavian ::

17 Afisare (& std::cout ,

143

Page 144: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 s ta t i c cas t < int >(prec)

19 )

20 << std::endl;

21 }

Program:> O structura reprezinta o agregare de date de diverse tipuri [20, p. 127],[41, p. 101]. Practic, ea este o clasa avand membrii aprioric publici al careiconstructor — daca exista! — trebuie folosit numai pentru simplificareainitializarii datelor componente, vezi [41, p. 234]. Un exemplu de structuraeste std::char_traits<T> din <iosfwd>, cf. [41, p. 580].

Structuri: program.cpp

1 #include "diverse.h"

2 #include "fise.h"

3

4 int main(){

5 octavian :: Fisa_guest vizitator;

6 vizitator.identificare = 134;

7 vizitator.nume = "Mustafa";

8 vizitator.prenume = "Octavian";

9 vizitator.raspuns ();

10 octavian :: Fisa_member popescu(1,

11 10,

12 "Popescu",

13 "Ionel",

14 "11.11.2011"

15 );

16 popescu.raspuns ();

17 octavian :: iesire();

18 #undef GAZDA

19 #undef OASPETE

20 #undef TEXT_FISA

21 return 0;

22 }

Structuri: fise.h

1 #ifndef _FISE_

2 #define _FISE_

3

4 namespace octavian{

5 struct Fisa_guest{

6 typedef int fisa_guest_intregi;

7 typedef char fisa_guest_caractere;

8 typedef

144

Page 145: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

9 fisa_guest_caractere* pfisa_guest_caractere;

10 fisa_guest_intregi identificare;

11 pfisa_guest_caractere nume , prenume;

12 void raspuns ();

13 };

14 struct Fisa_member{

15 typedef int fisa_member_intregi;

16 typedef char fisa_member_caractere;

17 typedef

18 fisa_member_caractere* pfisa_member_caractere;

19 typedef

20 Fisa_guest::

21 pfisa_guest_caractere tip_data_inscriere;

22 fisa_member_intregi identificare , parola;

23 pfisa_member_caractere nume , prenume;

24 tip_data_inscriere data_inscriere;

25 void raspuns ();

26 Fisa_member( int , int ,char*,char*,char*);

27 };

28 }

29 #endif

Structuri: fise.cpp

1 #include "fise.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5 #include <string.h>

6

7 #undef GAZDA

8 #define GAZDA octavian :: Fisa_member

9 #undef OASPETE

10 #define OASPETE octavian :: Fisa_guest

11 #undef TEXT_FISA

12 #define TEXT_FISA(q) \

13 std::cout << "Salut , " \

14 << s ta t i c cas t <char*>( ## q ::nume) \

15 << " " \

16 << s ta t i c cas t <char*>( ## q ::prenume) \

17 << "!\nID: " \

18 << s ta t i c cas t < int >( ## q :: identificare)

19

20 void octavian :: Fisa_guest::raspuns (){

145

Page 146: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

21 TEXT_FISA(octavian :: Fisa_guest) << std::endl;

22 }

23 void octavian :: Fisa_member::raspuns (){

24 TEXT_FISA(octavian :: Fisa_member)

25 << "\nDrepturi: "

26 << s ta t i c cas t < int >( octavian :: Fisa_member:: parola)

27 << "\nInscris pe data: "

28 << s ta t i c cas t <char*>(

29 octavian :: Fisa_member:: data_inscriere

30 )

31 << std::endl;

32 }

33 octavian ::

34 Fisa_member:: Fisa_member( int iidentificare ,

35 int pparola ,

36 char* nnume ,

37 char* pprenume ,

38 char* ddata_inscriere

39 ) :

40 identificare(iidentificare),

41 parola(pparola)

42 {

43 int lungime_nume = std:: str len (nnume),

44 lungime_prenume = std:: str len (pprenume ),

45 lungime_data_inscriere = std:: str len (

46 ddata_inscriere

47 );

48 i f (lungime_nume > 100 ||

49 lungime_prenume > 100 ||

50 lungime_data_inscriere > countof(

51 "32 decembrie 10000"

52 )

53 ){

54 pr int f s ("\nSiruri prea lungi!");

55 octavian ::iesire();

56 exit (EXIT FAILURE);

57 }

58 nume = nnume;

59 prenume = pprenume;

60 data_inscriere = ddata_inscriere;

61 }

Program:> In afara fluxurilor de intrare si de iesire, ın limbajul C++ se folosesc fluxuripentru “comunicarea” cu fisierele. Astfel, ca sa citim, vezi [42, p. 344], dintr-

146

Page 147: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

un fisier–text — ASCII —, vom utiliza un obiect al clasei65 std::ifstream,iar ca sa scriem ıntr-un fisier, de acelasi tip, un obiect al clasei66 std::ofstream din <fstream>.

In proiectul VS de fata implementam un contor global — structura —pentru a depista adresele de e-mail dintr-un fisier–text, salvat ın directorulC:\ProiecteleMele_Cpp\NumeleProiectului\NumeleProiectului. Con-torul ne ofera si informatii auxiliare: cate cuvinte exista ın fisier, cate contincaracterul “@” si la cate dintre acestea din urma caracterul respectiv este ıninterior 67. Reamintesc si programul UNIX intitulat wc — word counting —din [20, p. 20], bazat pe starea de ınauntrul/ın afara unui cuvant.

Structuri, fluxuri de fisier: program.cpp

1 #include "diverse.h"

2 #include "caractere.h"

3 #include "contoare.h"

4 #include <iostream >

5 #include <iomanip >

6 #include <fstream >

7 #include <string >

8

9 int main(){

10 std::cout << "\nIntroduceti numele "

11 "unui fisier din folderul curent.\n"

12 "Numele este: ";

13 std:: str ing nume;

14 std:: cin >> nume;

15 std:: i fstream citesc(nume. c s t r ());

16 i f (! citesc){

17 std::cout << "\nAvem probleme cu fisierul !"

18 << std::endl;

19 octavian :: iesire();

20 exit (EXIT FAILURE);

21 }

22

23 octavian ::

24 patch_coada_maimuta(citesc ,octavian :: coada_maimuta);

25

26 std:: str ing cuvant;

27 citesc.seekg(0, std:: ios ::beg);

65De la “input f ile stream”, cf. [41, p. 638]. Mai precis, un obiect std::ifstream esteun obiect al clasei std::basic_ifstream<char>.

66De la “output f ile stream”, cf. [22, p. 550].67O adresa de e-mail are forma partea_stanga@partea_dreapta!

147

Page 148: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

28 octavian :: Contoare contor(0,0,0,0,0);

29 while(citesc >> cuvant){

30 unsigned int ciclare = 0;

31 ciclare = octavian :: detect_poz(cuvant ,contor);

32 octavian :: afis_cuvant(cuvant ,contor ,ciclare);

33 }

34

35 std::cout << "\nAm cautat simbolul \""

36 << octavian :: coada_maimuta

37 << "\".\nNumarul de cuvinte citite este "

38 << contor.contor_cuv

39 << ".\ nNumarul de cuvinte ce contin \""

40 << octavian :: coada_maimuta

41 << "\" citite este "

42 << contor.contor_cm

43 << ".\ nNumarul de cuvinte cu \""

44 << octavian :: coada_maimuta

45 << "\" in interior citite este "

46 << contor.contor_cmb

47 << ".\n"

48 << std::endl;

49 octavian :: iesire();

50 #undef INCHID_IN_EROARE

51 return 0;

52 }

Structuri, fluxuri de fisier: caractere.h

1 #ifndef _CARACTERE_

2 #define _CARACTERE_

3 #include <fstream >

4 #include "diverse.h"

5 namespace octavian{

6 typedef char litere;

7 extern litere coada_maimuta;

8 void patch_coada_maimuta( std:: i fstream&,litere);

9 }

10 #endif

Structuri, fluxuri de fisier: caractere.cpp

1 #include "caractere.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

148

Page 149: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

5 #include <fstream >

6 #include <string >

7

8 #undef INCHID_IN_EROARE

9 #define INCHID_IN_EROARE \

10 octavian ::iesire(); \

11 exit (EXIT FAILURE);

12

13 typedef octavian :: litere octalt;

14 octalt octavian :: coada_maimuta =’\100’;

15 void octavian ::

16 patch_coada_maimuta( std:: i fstream& fisier ,

17 octalt litera

18 ){

19 std:: str ing cuvant;

20 fisier >> cuvant;

21 i f (cuvant. s i ze () == 0){

22 std::cout << "\nFisierul este gol!"

23 << std::endl;

24 INCHID_IN_EROARE

25 }

26 i f (cuvant [0] == litera)

27 std::cout << "\nPrimul cuvant "

28 "incepe cu \""

29 << s ta t i c cas t <char >( litera)

30 << "\"!"

31 << std::endl;

32 i f (fisier. eof ()){

33 std::cout << "Avem un singur cuvant , "

34 "si anume \""

35 << cuvant. c s t r ()

36 << "\".\nFisierul s-a incheiat !"

37 << std::endl;

38 INCHID_IN_EROARE

39 }

40 }

Structuri, fluxuri de fisier: contoare.h

1 #ifndef _CONTOARE_

2 #define _CONTOARE_

3 #include < string >

4

5 namespace octavian{

149

Page 150: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

6 struct Contoare{

7 typedef unsigned long numere_naturale_mari;

8 typedef unsigned int numere_naturale;

9 numere_naturale_mari contor_cuv ,

10 contor_cm ,

11 contor_cmb;

12 numere_naturale contor_lucru ,

13 lungime_cuv;

14 Contoare (numere_naturale_mari ,

15 numere_naturale_mari ,

16 numere_naturale_mari ,

17 numere_naturale ,

18 numere_naturale

19 );

20 };

21 Contoare :: numere_naturale_mari

22 detect_poz( std:: str ing &,octavian ::Contoare &);

23 void

24 afis_cuvant( std:: str ing &,

25 octavian :: Contoare &,

26 octavian :: Contoare :: numere_naturale

27 );

28 }

29 #endif

Structuri, fluxuri de fisier: contoare.cpp

1 #include "contoare.h"

2 #include "caractere.h"

3 #include <iostream >

4 #include <iomanip >

5 #include <string >

6

7 typedef

8 octavian :: Contoare :: numere_naturale_mari mare;

9 typedef

10 octavian :: Contoare :: numere_naturale numere;

11

12 /*---

13 Semnificatia datelor:

14 "interior ": nici prima , nici ultima dintre litere

15 - ccontor_cuv: nr. total de cuvinte

16 - ccontor_cm: nr. de cuvinte cu "@"

17 - ccontor_cmb: nr. cuvinte cu "@" in interior

150

Page 151: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 - ccontor_lucru: - 1 + prima pozitie interioara

19 a lui "@" in cuvantul curent

20 - llungime_cuv: lungimea cuvantului curent

21 ---*/

22

23 octavian ::

24 Contoare ::

25 Contoare (mare ccontor_cuv ,

26 mare ccontor_cm ,

27 mare ccontor_cmb ,

28 numere ccontor_lucru ,

29 numere llungime_cuv

30 ) :

31 contor_cuv(ccontor_cuv),

32 contor_cm(ccontor_cm),

33 contor_cmb(ccontor_cmb),

34 contor_lucru(ccontor_lucru),

35 lungime_cuv(llungime_cuv) {}

36

37 mare

38 octavian ::

39 detect_poz( std:: str ing & ccuvant ,

40 octavian :: Contoare & ccontor

41 ){

42 (ccontor.contor_cuv)++;//am citit un cuvant

43 ccontor.lungime_cuv = ccuvant. s i ze ();

44 i f (ccuvant [0] == octavian :: coada_maimuta){

45 (ccontor.contor_cm)++;//"@" e prima litera

46 return 0;

47 }

48 i f (ccuvant[ccontor.lungime_cuv - 1] == octavian ::

49 coada_maimuta

50 ){

51 (ccontor.contor_cm)++;//"@" e ultima litera

52 return 0;

53 }

54 for (numere i = 1;i < ccontor.lungime_cuv - 1; i++){

55 i f (ccuvant[i] == octavian :: coada_maimuta){

56 //incarc contorul doar daca gasesc un ’@ ’:

57 ccontor.contor_lucru = i;

58 (ccontor.contor_cm)++;

59 (ccontor.contor_cmb)++;

60 return 1;

151

Page 152: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

61 }

62 }

63 return 2;

64 }

65 void

66 octavian ::

67 afis_cuvant(std:: str ing & ccuvant ,

68 octavian ::Contoare & ccontor ,

69 numere cciclare

70 ){

71 i f (cciclare == 1)

72 std::cout << "\n-----------\n"

73 "Cuvantul este: \""

74 << ccuvant. c s t r ()

75 << "\".\nEl are lungimea "

76 << s ta t i c cas t < int >(

77 ccontor.lungime_cuv

78 )

79 << ".\nPozitia (prima pozitie a)"

80 " caracterului \""

81 << s ta t i c cas t <char >(

82 octavian :: coada_maimuta

83 )

84 << "\" este "

85 << s ta t i c cas t < int >(

86 (ccontor.contor_lucru) + 1

87 )

88 << ".\n-----------\n"

89 << std::endl;

90 return;

91 }

Program:> In proiectul VS care urmeaza implementam clasele “financiare” octavian:

:Euro si octavian::Lei, respectiv clasele “bancare” octavian::Client sioctavian::Banca. Vom folosi operatorul de conversie68, cu sintaxa operato

r T(), unde numele T desemneaza un tip predefinit ori UDT de date, cuexceptia sirurilor — array —. In plus, T nu poate reprezenta o functie69,cf. [22, p. 342]. Programul din cadrul proiectului converteste obiectele de

68 In limba engleza, conversion operator .69 In limbajul C, functiile sunt un tip derivat [20, pg. 196, 201], iar ın limbajul C++

vorbim despre tipul obiectelor-functie [39, p. 571/557]. Prin obiect-functie — sau functor ,cf. [48, p. 418] — ıntelegem orice instanta a unei clase ce poseda o supraıncarcare aoperatorului de apel [41, p. 515].

152

Page 153: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

tip octavian::Euro sau octavian::Lei ın variabile double cu ajutorul ca-rora instantele clasei octavian::Client, care sunt campuri ale unui obiectoctavian::Banca, vor realiza tranzactii . Mai precis, o banca are doi clienti,fiecare client poseda cate doua conturi, unul ın lei si celalalt ın euro, iartranzactiile facute de clienti ın cadrul bancii presupun conversia ın euro asumei din contul ın lei si transferarea acesteia ın contul ın euro. Evident,banca percepe un comision pe tranzactie si decide rata de schimb leu/euro.

Operatorul de conversie trebuie folosit ın mod judicios, vezi [22, p. 346],data fiind multitudinea de conversii implicite care apar la rularea programe-lor C++. In legatura cu conversiile, se cuvin mentionati operatorii static_cast<T>, const_cast<T> — deja ıntalniti —, respectiv dynamic_cast<T>70 sireinterpret_cast<T> [41, pg. 130, 131, 413].

Introducem ın discutie sabloanele de functii71, cu sintaxa:

1 template<typename Unu ,typename Doi>

2 void octavian :: tranzactie(Unu&,Doi&,double);

3 // specializari:

4 using namespace octavian ;

5 template<typename Unu >

6 void tranzactie(Unu&,Client&,double);

7 /* ---

8 specializarea completa nu se declara in

9 cadrul claselor carora le este "friend"

10 ---*/

11 template<> void tranzactie(Banca&,Client&,double);

Sablonul constituie elementul central al programarii generice, ın cadrulcareia tipurile datelor sunt parametri, vezi [41, p. 327]. Utilitatea unuisablon este evidenta atunci cand avem nevoie de functii, cum ar fi un con-vertor valutar — sau clase — care sa realizeze aceeasi prelucrare pentru omultitudine de tipuri de date. Atunci cand prelucrarea (generala) furnizatade sablon trebuie alterata, putem ıntrebuinta fie specializarile partiale, fiespecializarea completa a sablonului [41, pg. 342, 344]. Exista, ın plus, posi-bilitatea introducerii unor valori predefinite pentru parametrii sablonului,cf. [41, p. 340]. In Visual Studio numai sabloanele de clase beneficiaza deasemenea valori ale parametrilor de tip.

Cand invocam o functie–sablon72, inserand valorile reale ale parametrilorsablonului, are loc instantierea sablonului [22, p. 183]. Verificarile corespon-

70El se ocupa de “recuperarea” tipului unui obiect la run-time [41, p. 407]. In limbajulC#, aceasta idee conduce la reflexie, [1, p. 681].

71 In limba engleza, function templates .72Se folosesc, ın egala masura, si sintagmele sablon de functie sau functie generica, cf.

[18, p. 827].

153

Page 154: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

dentelor de tip73, respectiv conversiile implicite nu se suspenda cand lucramcu functii–sablon, ınsa capata un regim special, vezi [22, pg. 185, 187, 199].

In cadrul proiectelor cu mai multe fisiere, declaratiile si definitiile (imple-mentarile) sabloanelor pot crea o serie de dificultati [41, p. 350 si urm.], [22,p. 198]. In limbajul C++ a fost introdus, ın scopul simplificarii chestiunilor delinkare, cuvantul cheie export [41, ibid.], care este ınsa doar rezervat pentrucompilatorul C++ din VS. Cf. [48, p. 12], ın momentul compilarii, acesta arenevoie de codul sursa al functiei–sablon, nu numai de declaratia acesteia.

Sabloane de functii: program.cpp

1 #include "diverse.h"

2 #include "headerulnostru.h"

3 #include "format_afisare.h"

4 #include "tranzactii.h"

5 #include <iostream >

6 #include <iomanip >

7 #include "sabloane.cpp"

8

9 int main(){

10 system("cls");

11 octavian ::Euro a(23.55 ,’e’);

12 octavian ::Lei b(144.0098,’r’);

13 octavian ::Client c(a,b,"Anghel");

14 octavian ::Euro d(133,’e’);

15 octavian ::Lei e(4358.2, ’r’);

16 octavian ::Client f(d,e,"Alina");

17 octavian ::Client hh(a,e,"Popa");

18 octavian ::Banca RoUnited (c,f,0.26 ,0.13 ,4.82);

19 octavian :: tranzactie(RoUnited ,c,0.07);

20 // octavian :: tranzactie(RoUnited ,hh ,0.07);

21

22 octavian :: iesire_versiunea2();

23 #undef FRAZA_PROVIZORIE_EURO

24 #undef FRAZA_PROVIZORIE_LEI

25 return 0;

26 }

Sabloane de functii: tranzactii.h

1 #ifndef _TRANZACTII_

2 #define _TRANZACTII_

3

73 In limba engleza, type-checking.

154

Page 155: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

4 namespace octavian{

5 typedef unsigned int ui;

6 template<typename Unu , typename Doi >

7 void conversie(Unu&,Doi&,double ,double);

8

9 c la s s Euro{

10 template<typename Unu >

11 fr iend void verificare(Unu&);

12 template<typename Unu >

13 fr iend void afis_verificare(Unu&,ui);

14 template<typename Unu >

15 fr iend void afis_dobanda(Unu&,double ,ui);

16 template<typename Unu >

17 fr iend double stoc_dobanda(Unu&,double);

18 template<typename Unu >

19 fr iend Unu& aplic_dobanda(Unu&,double);

20 template<typename Unu >

21 fr iend Unu& actualizare(Unu&,double);

22 /* ---

23 impiedicam operatiile aritmetice nedorite :

24 ---*/

25 fr iend void operator+(Euro&,double);

26 fr iend void operator+(double ,Euro&);

27 fr iend void operator -(Euro&,double);

28 fr iend void operator -(double ,Euro&);

29 fr iend void operator*(Euro&,double);

30 fr iend void operator*(double ,Euro&);

31 fr iend void operator/(Euro&,double);

32 fr iend void operator/(double ,Euro&);

33 fr iend void operator==(Euro&,Euro&);

34 public :

35 Euro();

36 Euro(double ,char);

37 Euro(const Euro&);

38 Euro& operator=( const Euro&);

39 ∼Euro();

40 private:

41 // operatorul de conversie:

42 operator double();

43 double* suma;

44 char* valuta;

45 };

46

155

Page 156: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

47 c la s s Lei{

48 template<typename Unu >

49 fr iend void verificare(Unu&);

50 template<typename Unu >

51 fr iend void afis_verificare(Unu&,ui);

52 template<typename Unu >

53 fr iend void afis_dobanda(Unu&,double ,ui);

54 template<typename Unu >

55 fr iend double stoc_dobanda(Unu&,double);

56 template<typename Unu >

57 fr iend Unu& aplic_dobanda(Unu&,double);

58 template<typename Unu >

59 fr iend Unu& actualizare(Unu&,double);

60 fr iend void operator+(Lei&,double);

61 fr iend void operator+(double ,Lei&);

62 fr iend void operator -(Lei&,double);

63 fr iend void operator -(double ,Lei&);

64 fr iend void operator*(Lei&,double);

65 fr iend void operator*(double ,Lei&);

66 fr iend void operator/(Lei&,double);

67 fr iend void operator/(double ,Lei&);

68 fr iend void operator==(Lei&,Lei&);

69 public :

70 Lei();

71 Lei(double ,char);

72 Lei(const Lei&);

73 Lei& operator=( const Lei&);

74 ∼Lei();

75 private:

76 operator double();

77 double* suma;

78 char* valuta;

79 };

80

81 c la s s Client{

82 template<typename Unu ,typename Doi >

83 fr iend void tranzactie(Unu&,Doi&,double);

84 /* ---

85 pentru verificarea specializarilor:

86 template <typename Unu >

87 friend void tranzactie(Unu&,Client&,double);

88 ---*/

89 fr iend bool operator==( Client&,Client&);

156

Page 157: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

90 public :

91 Client();

92 Client(Euro ,Lei ,char*);

93 Client(const Client&);

94 Client& operator=( const Client&);

95 ∼Client();

96 private:

97 Euro* conteuro;

98 Lei* contlei;

99 char* nume;

100 };

101

102 c la s s Banca{

103 template<typename Unu ,typename Doi >

104 fr iend void tranzactie(Unu&,Doi&,double);

105 /* ---

106 pentru verificarea specializarilor:

107 template <typename Unu >

108 friend void tranzactie(Unu&,Client&,double);

109 ---*/

110 public :

111 Banca();

112 Banca(Client ,Client ,double ,double ,double);

113 Banca(const Banca&);

114 Banca& operator=( const Banca&);

115 ∼Banca();

116 // securizeaza tranzactiile

117 void actiune(octavian ::Client&);

118 private:

119 Client* clienti;

120 double* dobandaeuro;

121 double* dobandalei;

122 double* ratadeschimb;

123 };

124 }

125 #endif

Sabloane de functii: sabloane.cpp

1 #ifndef _SABLOANE_

2 #define _SABLOANE_

3 #include "tranzactii.h"

4 #include "format_afisare.h"

5 #include <iostream >

157

Page 158: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

6 #include <iomanip >

7

8 // sabloane de functii "friends"

9 template<typename Unu >

10 void

11 octavian ::

12 afis_verificare(Unu& moneda ,octavian ::ui precizie){

13 std::cout << "\n=========\nSuma: "

14 << moneda.suma[0]

15 << "\nValuta: "

16 << moneda.valuta [0]

17 << "\n=========="

18 << octavian ::Afisare (& std::cout ,

19 s ta t i c cas t < int >( precizie )

20 )

21 << std::endl;

22 }

23 template<typename Unu >

24 void

25 octavian ::

26 afis_dobanda(Unu& moneda ,

27 double dobanda ,

28 octavian ::ui precizie

29 ){

30 double lucru = octavian ::

31 stoc_dobanda(moneda ,dobanda);

32 std::cout << "\n===========\n"

33 "Dobanda este: "

34 << lucru

35 << "\n==========="

36 << octavian ::Afisare (& std::cout ,

37 s ta t i c cas t < int >( precizie )

38 )

39 << std::endl;

40 }

41 template<typename Unu >

42 double

43 octavian ::

44 stoc_dobanda(Unu& moneda ,double dobanda){

45 double lucru = dobanda * double(moneda);

46 return lucru;

47 }

48 template<typename Unu >

158

Page 159: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

49 Unu&

50 octavian ::

51 aplic_dobanda(Unu& moneda ,double dobanda){

52 double lucru = double(moneda)

53 + octavian :: stoc_dobanda(moneda ,

54 dobanda

55 );

56 moneda.suma[0] = lucru;

57 return moneda;

58 }

59 template<typename Unu >

60 Unu&

61 octavian ::

62 actualizare(Unu& moneda ,double valoare){

63 double lucru = valoare;

64 double bani = double(moneda);

65 i f (lucru < 0)

66 i f ((bani+lucru) < 0){

67 std::cout << "\n======\n"

68 "Fonduri insuficiente!"

69 "\n======"

70 << std::endl;

71 return moneda;

72 }

73 bani += lucru;

74 moneda.suma[0] = bani;

75 return moneda;

76 }

77 template<typename Unu , typename Doi >

78 void

79 octavian ::

80 conversie(Unu& moneda1 ,

81 Doi& moneda2 ,

82 double rata ,

83 double comision

84 ){

85 //determin cantitatea de bani din cont

86 double lucru = octavian ::

87 stoc_dobanda(moneda1 ,1);

88 //extrag comisionul de tranzactie

89 i f (lucru < comision ){

90 std::cout << "\n======\n"

91 "Comision prea mare!"

159

Page 160: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

92 "\n======"

93 << std::endl;

94 return;

95 }

96 /*in acest moment al tranzactiei ,

97 actualizez contul initial */

98 moneda1 = octavian ::

99 actualizare(moneda1 ,-comision);

100 /*verific cantitatea de bani din cont

101 dupa extragerea comisionului*/

102 lucru = octavian :: stoc_dobanda(moneda1 ,1);

103 //ii aplic sumei din cont rata de schimb

104 lucru *= rata;

105 /*in acest moment al tranzactiei ,

106 adaug cantitatea de bani (convertita)

107 sumei din contul final:

108 actualizez contul final*/

109 moneda2 = octavian :: actualizare(moneda2 ,lucru);

110 /*inchei tranzactia:

111 golesc contul initial */

112 moneda1 = octavian ::

113 actualizare(moneda1 ,

114 - octavian :: stoc_dobanda(moneda1 ,1)

115 );

116 }

117

118 template<typename Unu ,typename Doi>

119 void

120 octavian ::

121 tranzactie(Unu& banca ,Doi& client ,double comision){

122 /*efectuam tranzactii din lei in euro*/

123 banca.actiune(client);

124 std::cout << "\n=======\n"

125 "Buna ziua , domnule/doamna "

126 << client.nume

127 << " !\ nIncepem schimbul valutar ...\n"

128 "Primul cont:\n"

129 << std::endl;

130 octavian :: afis_verificare(client.contlei [0] ,12);

131 std::cout << "\nAl doilea cont:\n"

132 << std::endl;

133 octavian :: afis_verificare(client.conteuro [0] ,12);

134 std::cout << "\nTranzactie...\n"

160

Page 161: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

135 << std::endl;

136 octavian :: conversie(client.contlei [0],

137 client.conteuro [0],

138 banca.ratadeschimb[0],

139 comision

140 );

141 std::cout << "\nIncheiat tranzactie!\n"

142 "Rezultate:\ nPrimul cont:\n"

143 << std::endl;

144 octavian :: afis_verificare(client.contlei [0] ,12);

145 std::cout << "\nAl doilea cont:\n"

146 << std::endl;

147 octavian :: afis_verificare(client.conteuro [0] ,12);

148 }

149 /* ---

150 Pentru verificarea specializarilor ,

151 introduceti urmatorul cod:

152 template <typename Unu ,typename Doi >

153 void octavian :: tranzactie(Unu& banca ,

154 Doi& client ,

155 double comision

156 ){

157 ;

158 }

159 template <typename Unu >

160 void octavian :: tranzactie(Unu& banca ,

161 Client& client ,

162 double comision

163 ){

164 ;

165 }

166 Inlocuiti definitia "activa" (vezi deasupra )

167 a functiei tranzactie cu definitia:

168 template <>

169 void octavian :: tranzactie(Banca& banca ,

170 Client& client ,

171 double comision

172 ){

173 // inserati definitia

174 ;

175 }

176 ---*/

177 #endif

161

Page 162: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Sabloane de functii: diverse.h

1 #ifndef _DIVERSE_

2 #define _DIVERSE_

3

4 #include <cstdlib >

5 #include <cstdio >

6 #include <conio.h>

7

8 namespace octavian{

9 void iesire_versiunea2();

10 }

11

12 #endif

Sabloane de functii: diverse.cpp

1 #include "diverse.h"

2 #include <iostream >

3 #include <iomanip >

4

5 void octavian :: iesire_versiunea2(){

6 for (

7 std:: cin.sync(),

8 std:: cin. c lear (),

9 std::cout << "\nApasati ENTER"

10 " pentru a incheia: "

11 << std::endl ,

12 std:: cin. ignore();;

13 ) return;

14 }

Sabloane de functii: euro.cpp

1 #include "tranzactii.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5

6 #undef FRAZA_PROVIZORIE_EURO

7 #define FRAZA_PROVIZORIE_EURO(q) \

8 std::cout << "Operatie ilegala: " ## q \

9 << std::endl; \

10 octavian :: iesire_versiunea2(); \

11 exit (EXIT FAILURE);

12

162

Page 163: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

13 octavian ::Euro::Euro(){

14 suma = new double[1];

15 suma[0] = double();

16 valuta = new char [1];

17 valuta [0] = ’E’;

18 }

19 octavian ::Euro::Euro(double bani ,char euval){

20 suma = new double[1];

21 suma[0] = bani;

22 valuta = new char [1];

23 valuta [0] = euval;

24 }

25 octavian ::Euro::∼Euro()

26 {

27 delete [] suma;

28 delete [] valuta;

29 }

30 octavian ::Euro::Euro(const octavian ::Euro& euval){

31 suma = new double[1];

32 suma[0] = euval.suma[0];

33 valuta = new char [1];

34 valuta [0] = euval.valuta [0];

35 }

36 octavian ::Euro&

37 octavian ::

38 Euro::operator=( const octavian ::Euro& euval){

39 i f ( th is == &euval) return * th is ;

40 delete [] suma;

41 delete [] valuta;

42 suma = new double[1];

43 suma[0] = euval.suma[0];

44 valuta = new char [1];

45 valuta[0] = euval.valuta [0];

46 return * th is ;

47 }

48 void

49 octavian ::

50 operator+( octavian ::Euro& euval ,double numar){

51 FRAZA_PROVIZORIE_EURO("+ double!")

52 }

53 void

54 octavian ::

55 operator+(double numar ,octavian ::Euro& euval){

163

Page 164: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

56 FRAZA_PROVIZORIE_EURO("double +!")

57 }

58 void

59 octavian ::

60 operator -(double numar ,octavian ::Euro& euval){

61 FRAZA_PROVIZORIE_EURO("double -!")

62 }

63 void

64 octavian ::

65 operator -( octavian ::Euro& euval ,double numar){

66 FRAZA_PROVIZORIE_EURO("- double!")

67 }

68 void

69 octavian ::

70 operator*( octavian ::Euro& euval ,double numar){

71 FRAZA_PROVIZORIE_EURO("* double!")

72 }

73 void

74 octavian ::

75 operator*(double numar ,octavian ::Euro& euval){

76 FRAZA_PROVIZORIE_EURO("double *!")

77 }

78 void

79 octavian ::

80 operator/( octavian ::Euro& euval ,double numar){

81 FRAZA_PROVIZORIE_EURO("/ double!")

82 }

83 void

84 octavian ::

85 operator/(double numar ,octavian ::Euro& euval){

86 FRAZA_PROVIZORIE_EURO("double /!")

87 }

88 void

89 octavian ::

90 operator==( octavian ::Euro& val ,

91 octavian ::Euro& euval

92 ){

93 FRAZA_PROVIZORIE_EURO("== Euro!")

94 }

95 octavian ::Euro::operator double(){

96 return suma[0];

97 }

164

Page 165: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Sabloane de functii: lei.cpp

1 #include "tranzactii.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5

6 #undef FRAZA_PROVIZORIE_LEI

7 #define FRAZA_PROVIZORIE_LEI(q) \

8 std::cout << "Operatie ilegala: " ## q \

9 << std::endl; \

10 octavian :: iesire_versiunea2(); \

11 exit (EXIT FAILURE);

12

13 octavian ::Lei::Lei(){

14 suma = new double[1];

15 suma[0] = double();

16 valuta = new char [1];

17 valuta [0] = ’R’;

18 }

19 octavian ::Lei::Lei(double bani , char euval){

20 suma = new double[1];

21 suma[0] = bani;

22 valuta = new char [1];

23 valuta [0] = euval;

24 }

25 octavian ::Lei::∼Lei(){

26 delete [] suma;

27 delete [] valuta;

28 }

29 octavian ::Lei::Lei(const octavian ::Lei& euval){

30 suma = new double[1];

31 suma[0] = euval.suma[0];

32 valuta = new char [1];

33 valuta [0] = euval.valuta [0];

34 }

35 octavian ::Lei&

36 octavian ::Lei::operator=( const octavian ::Lei& euval){

37 i f ( th is == &euval) return * th is ;

38 delete [] suma;

39 delete [] valuta;

40 suma = new double[1];

41 suma[0] = euval.suma[0];

42 valuta = new char [1];

165

Page 166: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

43 valuta [0] = euval.valuta [0];

44 return * th is ;

45 }

46 void

47 octavian ::

48 operator+( octavian ::Lei& euval ,double numar){

49 FRAZA_PROVIZORIE_LEI("+ double!")

50 }

51 void

52 octavian ::

53 operator+(double numar ,octavian ::Lei& euval){

54 FRAZA_PROVIZORIE_LEI("double +!")

55 }

56 void

57 octavian ::

58 operator -(double numar ,octavian ::Lei& euval){

59 FRAZA_PROVIZORIE_LEI("double -!")

60 }

61 void

62 octavian ::

63 operator -( octavian ::Lei& euval ,double numar){

64 FRAZA_PROVIZORIE_LEI("- double!")

65 }

66 void

67 octavian ::

68 operator*( octavian ::Lei& euval ,double numar){

69 FRAZA_PROVIZORIE_LEI("* double!")

70 }

71 void

72 octavian ::

73 operator*(double numar ,octavian ::Lei& euval){

74 FRAZA_PROVIZORIE_LEI("double *!")

75 }

76 void

77 octavian ::

78 operator/( octavian ::Lei& euval ,double numar){

79 FRAZA_PROVIZORIE_LEI("/ double!")

80 }

81 void

82 octavian ::

83 operator/(double numar ,octavian ::Lei& euval){

84 FRAZA_PROVIZORIE_LEI("double /!")

85 }

166

Page 167: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

86 void

87 octavian ::

88 operator==( octavian ::Lei& val ,

89 octavian ::Lei& euval

90 ){

91 FRAZA_PROVIZORIE_LEI("== Lei!")

92 }

93 octavian ::Lei::operator double(){

94 return suma[0];

95 }

Sabloane de functii: banca.cpp

1 #include "tranzactii.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5

6 octavian ::Banca::Banca(){

7 clienti = new Client [2];

8 clienti [0] = Client();

9 clienti [1] = Client();

10 dobandaeuro = new double[1];

11 dobandaeuro[0] = 0.23;

12 dobandalei = new double[1];

13 dobandalei[0] = 0.18;

14 ratadeschimb = new double[1];

15 ratadeschimb[0] = 4.8;

16 }

17 octavian ::

18 Banca::

19 Banca(Client cclient1 ,

20 Client cclient2 ,

21 double dobeu ,

22 double dobro ,

23 double rasch

24 ){

25 clienti = new Client [2];

26 clienti [0] = cclient1;

27 clienti [1] = cclient2;

28 dobandaeuro = new double[1];

29 dobandaeuro[0] = dobeu;

30 dobandalei = new double[1];

31 dobandalei[0] = dobro;

167

Page 168: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

32 ratadeschimb = new double[1];

33 ratadeschimb[0] = rasch;

34 }

35 octavian ::Banca::Banca(const Banca& bbanca){

36 clienti = new Client [2];

37 clienti [0] = bbanca.clienti [0];

38 clienti [1] = bbanca.clienti [1];

39 dobandaeuro = new double[1];

40 dobandaeuro[0] = bbanca.dobandaeuro[0];

41 dobandalei = new double[1];

42 dobandalei[0] = bbanca.dobandalei[0];

43 ratadeschimb = new double[1];

44 ratadeschimb[0] = bbanca.ratadeschimb[0];

45 }

46 octavian ::Banca&

47 octavian ::

48 Banca::operator=( const Banca& bbanca){

49 i f ( th is == &bbanca) return * th is ;

50 delete [] clienti;

51 delete [] dobandaeuro;

52 delete [] dobandalei;

53 delete [] ratadeschimb;

54 clienti = new Client [2];

55 clienti [0] = bbanca.clienti [0];

56 clienti [1] = bbanca.clienti [1];

57 dobandaeuro = new double[1];

58 dobandaeuro[0] = bbanca.dobandaeuro[0];

59 dobandalei = new double[1];

60 dobandalei[0] = bbanca.dobandalei[0];

61 ratadeschimb = new double[1];

62 ratadeschimb[0] = bbanca.ratadeschimb[0];

63 return * th is ;

64 }

65 octavian ::Banca::∼Banca(){

66 delete [] clienti;

67 delete [] dobandaeuro;

68 delete [] dobandalei;

69 delete [] ratadeschimb;

70 }

71 void

72 octavian ::Banca:: actiune(Client& cclient){

73 octavian :: Client lucru = cclient;

74 i f (( clienti [0] == lucru) == f a l s e )

168

Page 169: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

75 i f ((clienti [1] == lucru) == f a l s e ){

76 std::cout << "\n===========\n"

77 "Domnule/Doamna ,\n"

78 "nu sunteti clientul nostru!\n"

79 "La revedere !\n"

80 "=============="

81 << std::endl;

82 octavian :: iesire_versiunea2();

83 exit (EXIT FAILURE);

84 }

85 }

Sabloane de functii: client.cpp

1 #include "tranzactii.h"

2 #include "diverse.h"

3 #include <iostream >

4 #include <iomanip >

5 #include <cstring >

6 #include <errno.h>

7

8 octavian ::Client::Client(){

9 conteuro = new Euro[1];

10 conteuro [0] = Euro();

11 contlei = new Lei[1];

12 contlei [0] = Lei();

13 int numar_intern = s ta t i c cas t < int >(

14 std:: str len ("Popescu")

15 )

16 + 1 /* + 30 */;

17 nume = new char[numar_intern];

18 strcpy s (nume ,numar_intern ,"Popescu");

19 }

20 octavian ::Client::Client(Euro eu,Lei ro, char* nnume){

21 conteuro = new Euro[1];

22 conteuro [0] = eu;

23 contlei = new Lei[1];

24 contlei [0] = ro;

25 int numar_intern = s ta t i c cas t < int >(

26 std:: str len (nnume)

27 )

28 + 1 /* + 30 */;

29 nume = new char[numar_intern];

30 strcpy s (nume ,numar_intern ,nnume);

169

Page 170: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

31 }

32 octavian ::Client::∼Client(){

33 delete [] conteuro;

34 delete [] contlei;

35 delete [] nume;

36 }

37 octavian ::

38 Client::

39 Client(const octavian ::Client& cclient){

40 conteuro = new Euro[1];

41 conteuro [0] = cclient.conteuro [0];

42 contlei = new Lei [1];

43 contlei [0] = cclient.contlei [0];

44 int numar_intern = s ta t i c cas t < int >(

45 std:: str len (cclient.nume)

46 )

47 + 1 /* + 30 */;

48 nume = new char[numar_intern];

49 strcpy s (nume ,numar_intern ,cclient.nume);

50 }

51 octavian ::Client&

52 octavian ::

53 Client::

54 operator=( const octavian ::Client& cclient){

55 i f ( th is == &cclient) return * th is ;

56 delete [] conteuro ;

57 delete [] contlei;

58 delete [] nume;

59 conteuro = new Euro[1];

60 conteuro [0] = cclient.conteuro [0];

61 contlei = new Lei [1];

62 contlei [0] = cclient.contlei [0];

63 int numar_intern = s ta t i c cas t < int >(

64 std:: str len (cclient.nume)

65 )

66 + 1 /* + 30 */;

67 nume = new char[numar_intern];

68 strcpy s (nume ,numar_intern ,cclient.nume);

69 return * th is ;

70 }

71 bool

72 octavian ::

73 operator==( Client& client1 ,Client& client2){

170

Page 171: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

74 i f (

75 std::strcmp(client1.nume ,client2.nume) != 0

76 )

77 return f a l s e ;

78 return true;

79 }

Program:> In proiectul VS de fata construim o lista simpla. Chestiunea listelor esteuna fundamentala pentru manipularea sirurilor de obiecte. Exemple de listese gasesc ın [20, p. 144], [22, p. 356 si urm.] si [41, pg. 333, 403]. Lista deaici poate fi imaginata ca un lantisor caruia nu i-a fost (ınca) atasat niciunpandantiv. Lista — goala — contine doua adrese, cap si coada, ce cores-pund celor doua mici piese metalice care alcatuiesc ıncuietoarea lantisorului.Obiectele ce urmeaza sa fie atasate listei trebuie “pregatite”; exact la fel cumun pandantiv are nevoie de o toarta pentru a fi agatat de lantisor. Toarta ıncauza este o adresa, numita cheie.

Implementarea functiei octavian::iesire se gaseste la pagina 104.

O lista de obiecte: program.cpp

1 #include "diverse.h"

2 #include "lista1.h"

3 #include <iostream >

4 #include <iomanip >

5

6 int main(){

7 system("cls");

8 /*---

9 Pregatim obiecte pentru

10 introducerea in lista:

11 au toate "adresa standard ".

12 ---*/

13 octavian :: ObiectLista ob;

14 octavian :: ObiectLista ob_unu(23,ob);

15 octavian :: ObiectLista ob_doi(54,ob);

16 octavian :: ObiectLista ob_trei (124,ob);

17 octavian :: ObiectLista ob_patru (32,ob);

18 octavian :: ObiectLista ob_cinci (176,ob);

19 octavian :: Lista lst;

20 std::cout << "\n++++++++"

21 "Incepem lista:"

22 << std::endl;

23 (lst.adaug_la_coada)(ob_unu);

24 (lst.adaug_la_coada)(ob_doi);

171

Page 172: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

25 (lst.adaug_la_coada)(ob_trei);

26 (lst.adaug_la_coada)(ob_patru );

27 (lst.adaug_la_coada)(ob_cinci );

28 std::cout << "\n++++++++"

29 "S-a incheiat lista!"

30 << std::endl;

31 octavian :: listare(lst);

32 /*---

33 Primele doua "ObiectLista" vor fi sterse

34 din lista , iar adresele inmagazinate in

35 ele vor fi "eliberate".

36 ---*/

37 lst.sterg_la_cap();

38 lst.sterg_la_cap();

39 octavian :: listare(lst);

40 octavian :: iesire();

41 return 0;

42 }

O lista de obiecte: lista1.h

1 #ifndef _LISTA1_

2 #define _LISTA1_

3

4 namespace octavian{

5 c la s s ObiectLista{

6 int numar;

7 ObiectLista* cheie;

8 public :

9 ObiectLista();

10 ObiectLista( int ,ObiectLista&);

11 ∼ObiectLista();

12 operator double();

13 void afis_numar() const;

14 void afis_cheie() const;

15 int intorc_numar() const;

16 ObiectLista* intorc_cheie() const ;

17 void sterg_cheie();

18 void scriu_cheie(ObiectLista&);

19 void test_invariant();

20 };

21 c la s s Lista{

22 fr iend void listare(Lista&);

23 ObiectLista* cap;

172

Page 173: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

24 ObiectLista* coada;

25 public :

26 Lista();

27 ∼Lista();

28 void adaug_la_coada(ObiectLista&);

29 void sterg_la_cap();

30 bool e_goala () const;

31 };

32 }

33 #endif

O lista de obiecte: lista1.cpp

1 #include "diverse.h"

2 #include "lista1.h"

3 #include <iostream >

4 #include <iomanip >

5

6 octavian ::

7 ObiectLista:: ObiectLista(){

8 numar = 0; cheie = 0;

9 }

10 octavian ::

11 ObiectLista::

12 ObiectLista( int nnumar ,ObiectLista& objlst) :

13 numar(nnumar), cheie(&objlst) {}

14 void

15 octavian ::

16 ObiectLista:: afis_numar() const{

17 std::cout << "\nNumarul este: "

18 << numar;

19 std::cout. f lush ();

20 }

21 void

22 octavian ::

23 ObiectLista:: afis_cheie() const{

24 std::cout << "\nAdresa este: "

25 << (void*) cheie;

26 std::cout. f lush ();

27 }

28 int

29 octavian ::

30 ObiectLista:: intorc_numar() const{

31 return numar;

173

Page 174: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

32 }

33 octavian :: ObiectLista*

34 octavian :: ObiectLista:: intorc_cheie() const{

35 return cheie;

36 }

37 octavian :: ObiectLista::∼ObiectLista(){

38 numar = 0; cheie = 0;

39 }

40 octavian :: ObiectLista::operator double(){

41 // recuperarea numarului:

42 return numar;

43 }

44 void octavian :: ObiectLista:: sterg_cheie(){

45 cheie = 0;

46 }

47 void

48 octavian ::

49 ObiectLista:: scriu_cheie(ObiectLista& objlst){

50 cheie = &objlst;

51 }

52 void octavian :: ObiectLista:: test_invariant(){

53 /* ---

54 Daca este bine definit ca "obiect din lista",

55 un obiect va avea la campul cheie adresa unei

56 instante ObiectLista construite cu construc -

57 torul fara argumente!

58 ---*/

59 ObiectLista* ob_intern = cheie ->intorc_cheie();

60 i f (ob_intern != 0){

61 pr int f s ("\nObiectul care contine "

62 "numarul %d\nnu este corect "

63 "formatat pentru inserarea "

64 "in lista!\ nInchei ...",

65 numar

66 );

67 octavian :: iesire();

68 exit (EXIT FAILURE);

69 }

70 }

71 octavian ::Lista::Lista(){

72 cap = coada = 0;

73 }

74 octavian ::Lista::∼Lista(){

174

Page 175: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

75 cap = coada = 0;

76 }

77 bool octavian ::Lista:: e_goala () const{

78 return coada == 0 ? true : f a l s e ;

79 }

80 void

81 octavian ::

82 Lista::

83 adaug_la_coada(ObiectLista& objlst){

84 //testez obiectul :

85 objlst.test_invariant();

86 i f (e_goala ()){

87 coada = &objlst;

88 pr int f s ("\nAdaug: %d\n",

89 coada ->intorc_numar()

90 );

91 return;

92 }

93 i f (cap==0){

94 cap = coada;

95 (cap ->scriu_cheie)(objlst);

96 coada = &objlst;

97 pr int f s ("\nAdaug: %d\n",

98 coada ->intorc_numar()

99 );

100 return;

101 }

102 (coada ->scriu_cheie)(objlst);

103 coada = &objlst;

104 pr int f s ("\nAdaug: %d\n",

105 coada ->intorc_numar()

106 );

107 }

108 void octavian ::Lista:: sterg_la_cap(){

109 i f (e_goala ()){

110 pr int f s ("\nNimic de sters!");

111 return;

112 }

113 i f (cap==0){

114 pr int f s ("\nLista are un singur "

115 "element: il sterg...\n"

116 );

117 coada ->sterg_cheie();

175

Page 176: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

118 return;

119 }

120 octavian :: ObiectLista*

121 ob_intern = cap ->intorc_cheie();

122 i f (ob_intern == 0){

123 pr int f s ("\nCiudat ...\n");

124 return;

125 }

126 i f (ob_intern ->intorc_cheie() == 0){

127 pr int f s ("\nSuntem la ultimul element:"

128 " il sterg..."

129 "\nValoarea sa inainte de "

130 "stergere : %d\n",

131 cap ->intorc_numar()

132 );

133 cap ->sterg_cheie();

134 // curat lista:

135 cap = coada = 0;

136 return;

137 }

138 pr int f s ("\nSterg ...\n");

139 cap ->sterg_cheie();

140 cap = ob_intern;

141 pr int f s ("\nCapul: %d\n",cap ->intorc_numar());

142 }

143 void octavian :: listare(Lista& llista){

144 Lista* lis = &llista;

145 i f (lis ->e_goala ()){

146 pr int f s ("\nLista este goala!\ nNimic "

147 "de listat ...\n"

148 );

149 return;

150 }

151 i f (lis ->cap == 0){

152 pr int f s ("\nLista are doar un singur "

153 "obiect!\nIl listam ...\n"

154 );

155 (lis ->coada)->afis_numar();

156 return;

157 }

158 // Obiectele din lista sunt BINE formatate!

159 octavian :: ObiectLista* ob_intern =lis ->cap;

160 for (; ob_intern != lis->coada;

176

Page 177: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

161 ob_intern = ob_intern ->intorc_cheie()

162 ){

163 (ob_intern)->afis_numar();

164 (ob_intern)->afis_cheie();

165 }

166 (lis ->coada)->afis_numar();

167 }

Program:> Reluam proiectul listei anterioare, folosind ınsa mecanismul sabloanelor.

O lista<T> de obiecte: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include "sabloane.h"

5 #include "sabloane.cpp"

6 #include "diverse.h"

7 #include <iostream >

8 #include <iomanip >

9 using namespace octavian ;

10

11 int main(){

12 system("cls");

13 ObiectLista <char > ob;

14 ObiectLista <char > ob_unu(’a’,ob);

15 ObiectLista <char > ob_doi(’w’,ob);

16 ObiectLista <char > ob_trei(’9’,ob);

17 ObiectLista <char > ob_patru (’g’,ob);

18 ObiectLista <char > ob_cinci (’k’,ob);

19 Lista <char > lst;

20 (lst.adaug_la_coada)(ob_unu);

21 (lst.adaug_la_coada)(ob_doi);

22 (lst.adaug_la_coada)(ob_trei);

23 (lst.adaug_la_coada)(ob_patru);

24 (lst.adaug_la_coada)(ob_cinci);

25 lst.listare ();

26 lst.sterg_la_cap();

27 lst.sterg_la_cap();

28 lst.listare ();

29 char ss = char(ob_cinci );

30 pr int f s ("\n%c",ss);

31 iesire();

32 return 0;

33 }

177

Page 178: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

O lista<T> de obiecte: sabloane.h

1 #ifndef _SABLOANE_

2 #define _SABLOANE_

3 #include <iostream >

4 #include <iomanip >

5 namespace octavian{

6 template<typename Tip > c la s s Lista;

7 template<typename Tip > c la s s ObiectLista{

8 fr iend c la s s Lista <Tip >;

9 public :

10 ObiectLista();

11 ObiectLista(const Tip&,ObiectLista <Tip >&);

12 ObiectLista(const ObiectLista <Tip >&);

13 ObiectLista <Tip >&

14 operator=( const ObiectLista <Tip >&);

15 ∼ObiectLista();

16 operator Tip();

17 void afis_numar() const ;

18 void afis_cheie() const ;

19 Tip intorc_numar() const;

20 ObiectLista <Tip >* intorc_cheie() const ;

21 void sterg_cheie();

22 void scriu_cheie(ObiectLista <Tip >&);

23 void test_invariant();

24 private:

25 Tip numar;

26 ObiectLista <Tip >* cheie;

27 };

28 template<typename Tip > c la s s Lista{

29 ObiectLista <Tip >* cap;

30 ObiectLista <Tip >* coada;

31 public :

32 Lista();

33 ∼Lista();

34 void adaug_la_coada(ObiectLista <Tip >&);

35 void sterg_la_cap();

36 bool e_goala () const;

37 void listare () const;

38 };

39 }

40 #endif

178

Page 179: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

O lista<T> de obiecte: sabloane.cpp

1 #ifndef _SABLOANE1_

2 #define _SABLOANE1_

3 #include <iostream >

4 #include <iomanip >

5 #include "sabloane.h"

6 #include "diverse.h"

7 using namespace std;

8 using namespace octavian ;

9

10 #undef CAND_TIP_ESTE_NUMAR

11 #define CAND_TIP_ESTE_NUMAR 1

12 #undef CAND_TIP_ESTE_NUMAR

13

14 template<typename Tip > ObiectLista <Tip >:: ObiectLista()

15 : numar(Tip())

16 {

17 cheie = 0;

18 }

19 template<typename Tip > ObiectLista <Tip >::

20 ObiectLista(const Tip& nnum ,

21 ObiectLista <Tip >& objlst)

22 : numar(nnum)

23 {

24 cheie = &objlst;

25 }

26 template <typename Tip > ObiectLista <Tip >::

27 ObiectLista(const ObiectLista <Tip >& objlst)

28 : numar(objlst.numar)

29 {

30 cheie = objlst.cheie;

31 }

32 template<typename Tip > ObiectLista <Tip >&

33 ObiectLista <Tip >::

34 operator=( const ObiectLista <Tip >& objlst){

35 i f ( th is == &objlst) return * th is ;

36 numar = objlst.numar;

37 return * th is ;

38 }

39 template<typename Tip > ObiectLista <Tip >::∼ObiectLista()

40 {

41 numar = Tip(); cheie = 0;

42 }

179

Page 180: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

43 template<typename Tip > void ObiectLista <Tip >::

44 afis_numar() const {

45 std::cout << "\nNumarul este: "

46 << numar;

47 std::cout. f lush ();

48 }

49 template<typename Tip > void ObiectLista <Tip >::

50 afis_cheie() const {

51 std::cout << "\nAdresa este: "

52 << (void*) cheie;

53 std::cout. f lush ();

54 }

55 template<typename Tip > Tip ObiectLista <Tip >::

56 intorc_numar() const{

57 return numar;

58 }

59 template<typename Tip > void ObiectLista <Tip >::

60 sterg_cheie(){

61 cheie = 0;

62 }

63 template<typename Tip > ObiectLista <Tip >*

64 ObiectLista <Tip >:: intorc_cheie() const{

65 return cheie;

66 }

67 template<typename Tip >

68 ObiectLista <Tip >::operator Tip(){

69 return numar;

70 }

71 template<typename Tip >

72 void ObiectLista <Tip >:: test_invariant(){

73 ObiectLista <Tip >*

74 ob_intern = cheie ->intorc_cheie();

75 i f (ob_intern != 0){

76 pr int f s ("\nObiectul care contine "

77 "numarul "

78 #i fd e f CAND_TIP_ESTE_NUMAR

79 "%d"

80 #endif

81 "\nnu este corect "

82 "formatat pentru inserarea "

83 "in lista!\ nInchei ..."

84 #i fd e f CAND_TIP_ESTE_NUMAR

85 ,

180

Page 181: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

86 numar

87 #endif

88 );

89 octavian ::iesire();

90 exit (EXIT FAILURE);

91 }

92 }

93 template<typename Tip >

94 void ObiectLista <Tip >::

95 scriu_cheie(ObiectLista <Tip >& objlst){

96 cheie = &objlst;

97 }

98 template<typename Tip > Lista <Tip >:: Lista(){

99 cap = 0; coada = 0;

100 }

101 template<typename Tip >

102 Lista <Tip >::∼Lista(){

103 cap = coada = 0;

104 }

105 template<typename Tip >

106 bool octavian ::Lista <Tip >:: e_goala () const{

107 return coada == 0 ? true : f a l s e ;

108 }

109 template<typename Tip >

110 void octavian ::Lista <Tip >::

111 adaug_la_coada(ObiectLista <Tip >& objlst){

112 // testez obiectul :

113 objlst.test_invariant();

114 i f (e_goala ()){

115 coada = &objlst;

116 #i fd e f CAND_TIP_ESTE_NUMAR

117 pr int f s ("\nAdaug: %d\n",

118 coada ->intorc_numar()

119 );

120 #endif

121 return;

122 }

123 i f (cap==0){

124 cap = coada;

125 (cap ->scriu_cheie)(objlst);

126 coada = &objlst;

127 #i fd e f CAND_TIP_ESTE_NUMAR

128 pr int f s ("\nAdaug: %d\n",

181

Page 182: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

129 coada ->intorc_numar()

130 );

131 #endif

132 return;

133 }

134 (coada ->scriu_cheie)(objlst);

135 coada = &objlst;

136 #i fd e f CAND_TIP_ESTE_NUMAR

137 pr int f s ("\nAdaug: %d\n",

138 coada ->intorc_numar()

139 );

140 #endif

141 }

142 template<typename Tip >

143 void octavian ::Lista <Tip >:: sterg_la_cap(){

144 i f (e_goala ()){

145 pr int f s ("\nNimic de sters!");

146 return;

147 }

148 i f (cap==0){

149 pr int f s ("\nLista are un singur "

150 "element: il sterg...\n"

151 );

152 coada ->sterg_cheie();

153 return;

154 }

155 octavian :: ObiectLista <Tip >*

156 ob_intern = cap ->intorc_cheie();

157 i f (ob_intern == 0){

158 pr int f s ("\nCiudat ...\n");

159 return;

160 }

161 i f (ob_intern ->intorc_cheie() == 0){

162 pr int f s ("\nSuntem la ultimul element:"

163 " il sterg..."

164 #i fd e f CAND_TIP_ESTE_NUMAR

165 "\nValoarea sa inainte de "

166 "stergere : %d\n",

167 cap ->intorc_numar()

168 #endif

169 );

170 cap ->sterg_cheie();

171 //curat lista:

182

Page 183: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

172 cap = coada = 0;

173 return;

174 }

175 pr int f s ("\nSterg ...\n");

176 cap ->sterg_cheie();

177 cap = ob_intern;

178 #i fd e f CAND_TIP_ESTE_NUMAR

179 pr int f s ("\nCapul: %d\n",cap ->intorc_numar());

180 #endif

181 }

182 template<typename Tip >

183 void octavian ::Lista <Tip >::

184 listare () const{

185 Lista <Tip >*

186 lis = const cast <Lista <Tip >*>( th is );

187 i f (lis ->e_goala ()){

188 pr int f s ("\nLista este goala!\nNimic "

189 "de listat ...\n"

190 );

191 return;

192 }

193 i f (lis ->cap == 0){

194 pr int f s ("\nLista are doar un singur "

195 "obiect!\nIl listam ...\n"

196 );

197 (lis->coada)->afis_numar();

198 return;

199 }

200 // Obiectele din lista sunt BINE formatate!

201 octavian ::ObiectLista <Tip >* ob_intern =lis ->cap;

202 for (; ob_intern != lis ->coada;

203 ob_intern = ob_intern ->intorc_cheie()

204 ){

205 (ob_intern)->afis_numar();

206 (ob_intern)->afis_cheie();

207 }

208 (lis ->coada)->afis_numar();

209 }

210 #endif

Program:> In anumite situatii, este bine sa “prevenim” compilatorul ca utilizam unoperator–sablon, cf. [41, p. 855].

183

Page 184: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Operatori–sablon: program.cpp

1 #include <cstdio >

2 #include <cstdlib >

3 #include <conio.h>

4 #include <iostream >

5 #include <iomanip >

6 #include "sabloane.h"

7 #include "sabloane.cpp"

8

9 int main(){

10 Numere <double > nn = 23.4;

11 std::cout << nn << std::endl;

12 getch();

13 return 0;

14 }

Operatori–sablon: sabloane.h

1 #ifndef _SABLOANE_

2 #define _SABLOANE_

3

4 using namespace std;

5 template<typename T> c la s s Numere{

6 /* ---

7 Folosim una din declaratiile de mai jos

8 pentru a informa compilatorul ca avem

9 un operator -sablon:

10 ---*/

11 fr iend ostream& operator << <T>(ostream&,Numere&);

12 //friend ostream& operator << <>(ostream&,Numere <T>&);

13 T numar;

14 public :

15 T afis();

16 Numere(T);

17 };

18 #endif

Operatori–sablon: sabloane.cpp

1 #ifndef _SABLOANE1_

2 #define _SABLOANE1_

3 #include <iostream >

4 #include <iomanip >

5 #include "sabloane.h"

6

184

Page 185: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

7 using namespace std;

8 template<typename T>

9 T Numere <T>::afis(){

10 return numar;

11 }

12 template<typename T>

13 Numere <T>:: Numere(T nnt){

14 numar = nnt;

15 }

16 template<typename T>

17 ostream&

18 operator << (ostream& os,Numere <T>& nnum){

19 T sd = nnum.afis();

20 os << sd;

21 os. f lush ();

22 return os;

23 }

24 #endif

Program:> (Intro STL) Cu ajutorul algoritmului find [41, p. 525], depistam daca unnumar ıntreg se gaseste ıntr-un sir dat de numere.

Intro STL, algoritmul find: program.cpp

1 #include <conio.h>

2 #include <cstdlib >

3 #include <cstdio >

4 #include <cstring >

5 #include <iostream >

6 #include <vector >

7 #include <string >

8 #include <algorithm >

9

10 void cautare_numar( std::vector < int >& vect ,

11 int num){

12 std::vector < int >:: i terator

13 p = f ind (vect.begin(),vect.end(),num);

14 i f (p != vect.end())

15 std::cout << "Gasit!"

16 << std::endl;

17 e l se

18 std::cout << "N-am gasit!"

19 << std::endl;

20 }

21

185

Page 186: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

22 int main(){

23 system("cls");

24 std::vector < int > secventa;

25 secventa .push back (12);

26 secventa .push back (34);

27 secventa .push back(-3);

28 secventa .push back(1);

29 secventa .push back (37);

30 std::cout << "Scrieti un numar intreg:"

31 << std::endl;

32 std:: str ing numar;

33 std:: cin >> numar;

34 cautare_numar(secventa , std:: atoi (numar. c s t r ()));

35 getch();

36 return 0;

37 }

Program:> (Intro STL) Fluxurile std::stringstream74 din <sstream> [41, p. 640] seataseaza datelor de tip std::string pentru ca utilizatorul sa poata opera cuacestea din urma ca si cum ele ar fi fluxuri. Cu ajutorul iteratorilor de sensinvers75, ın programul de fata, preluam un rand de cuvinte de la consola siapoi afisam intrarile “de la dreapta la stanga”.

Intro STL, fluxuri la string, iteratori: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include <iostream >

5 #include <sstream >

6 #include <vector >

7 #include <string >

8 using namespace std;

9

10 int main(){

11 system("cls");

12 cout << "Scrieti un rand:"

13 << endl;

14 str ing text;

15 get l ine (cin ,text);

16 stringstream sir(text);

17 vector < string > cuvinte;

74Un stringstream este un std::basic_stringstream<char>, cf. [41, p. 641].75 In limba engleza, reverse iterators [41, pg. 443, 557].

186

Page 187: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

18 str ing cuvant;

19 while(sir >> cuvant)

20 cuvinte.push back(cuvant);

21 cout << "\nElemente stanga - dreapta:"

22 "\n====="

23 << endl;

24 for (vector < string >:: i terator

25 p = cuvinte.begin();

26 p != cuvinte.end();

27 p++

28 )

29 cout << *p << endl;

30 cout << "Elemente dreapta - stanga:"

31 "\n====="

32 << endl;

33 for (vector < string >:: reverse i terator

34 p = cuvinte. rbegin();

35 p != cuvinte.rend();

36 p++

37 )

38 cout << *p << endl;

39 getch();

40 return 0;

41 }

Program:> (Intro STL) Cu ajutorul functiei–membru insert [41, p. 452] a containe-rului76 std::vector<T>, introducem litere ıntr-un cuvant dat.

Intro STL, inserare ıntr-un container: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include <iostream >

5 #include <iomanip >

6 #include <vector >

7 #include <string >

8 using namespace std;

9

10 int main(){

11 system("cls");

12 char cuv[] = "stereotip";

13 vector <char > cuvant;

76 In limba engleza, container [18, p. 912].

187

Page 188: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

14 typedef vector <char >:: i terator numarator;

15 cuvant. assign (cuv ,&cuv[ s i z eo f (cuv) -1]);

16 for (numarator n = cuvant.begin();

17 n != cuvant.end();

18 n++

19 )

20 cout << *n << endl;

21 cout << "====" << endl;

22 vector <char > info;

23 info.push back(’y’);

24 info.push back(’x’);

25 cuvant. insert (cuvant.begin()+4,

26 info.begin(),

27 info.end()

28 );

29 for (numarator n = cuvant.begin();

30 n != cuvant.end();

31 n++

32 )

33 cout << *n;

34 cout << endl;

35 getch();

36 return 0;

37 }

Program:> (Intro STL) Folosim, ın continuare, containerul std::list<T> [41, p. 470]pentru a implementa un “editor de text”, care sa organizeze intrarile subforma de randuri afisate ın consola.

Intro STL, containerul std::list<T>: program.cpp

1 /* ---

2 Copyright:

3 Inspirat de (Closely following)

4 "C++, Special Edition" by B. Stroustrup

5 ---*/

6 #include <cstdlib >

7 #include <cstdio >

8 #include <conio.h>

9 #include <iostream >

10 #include <iomanip >

11 #include <vector >

12 #include <string >

13 #include <list >

14 using namespace std;

188

Page 189: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

15

16 typedef vector <char > linie;

17 // constructia unui iterator :

18 c la s s numarator{

19 public :

20 numarator( l i s t <linie >:: i terator lln ,

21 linie:: i terator ppoz

22 ) : ln(lln), poz(ppoz){}

23 char& operator*(){return *poz;}

24 numarator& operator ++();

25 bool

26 operator==( const numarator& alt) const{

27 return (ln == alt.ln && poz == alt.poz);

28 }

29 bool

30 operator!=( const numarator& alt) const{

31 return !(* th is == alt);

32 }

33 private:

34 l i s t <linie >:: i terator ln;

35 linie:: i terator poz;

36 };

37 numarator&

38 numarator::operator++(){

39 ++poz;

40 i f (poz == (*ln).end()){

41 ++ln;

42 poz=(*ln).begin();

43 }

44 return * th is ;

45 }

46 //un document :

47 struct Document {

48 l i s t <linie > lin;

49 numarator inceput (){

50 return numarator(lin.begin(),

51 (*(lin.begin())).begin()

52 );

53 }

54 numarator sfarsit (){

55 l i s t <linie >:: i terator last =lin.end();

56 --last;

57 return numarator(last ,(* last).end() -1);

189

Page 190: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

58 }

59 };

60 void tipar(Document & doc){

61 for (numarator p = doc.inceput ();

62 p != doc.sfarsit ();

63 ++p

64 )

65 cout << *p;

66 }

67

68 int main(){

69 system("cls");

70 linie unu;

71 unu.push back(’A’);

72 unu.push back(’n’);

73 unu.push back(’a’);

74 unu.push back(’\n’);

75 linie doi;

76 doi.push back(’a’);

77 doi.push back(’r’);

78 doi.push back(’e’);

79 doi.push back(’\n’);

80 linie trei;

81 trei.push back(’m’);

82 trei.push back(’e’);

83 trei.push back(’r’);

84 trei.push back(’e’);

85 trei.push back(’.’);

86 //linie de final:

87 linie patru;

88 patru.push back(’\n’);

89 cout << "Teste:\nAfisare prima linie:"

90 << endl;

91 for (linie:: i terator x = unu.begin();

92 x != unu.end();

93 ++x

94 )

95 cout << *x;

96 cout << "+++" << endl;

97 Document doc;

98 doc.lin.push back(unu);

99 doc.lin.push back(doi);

100 doc.lin.push back(trei);

190

Page 191: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

101 doc.lin.push back(patru);

102 cout << "Incepem documentul:\n======"

103 << endl;

104 tipar(doc);

105 cout << "\n====\ nIncheiat documentul!"

106 << endl;

107 getch();

108 return 0;

109 }

Program:> (Intro STL) Aici implementam o clasa de obiecte–functie si le folosim capredicate [41, p. 515] ıntr-o sortare [41, p. 539].

Intro STL, obiecte–functie, predicate, sortari: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include <iostream >

5 #include <iomanip >

6 #include <vector >

7 #include <string >

8 #include <algorithm >

9 using namespace std;

10

11 // constructia unui obiect -functie:

12 c la s s CuTel{

13 fr iend

14 ostream& operator <<(ostream& os, const CuTel&);

15 public :

16 CuTel() : am_tel(’N’){}

17 exp l i c i t CuTel(char aam_tel) :

18 am_tel(aam_tel){}

19 // operatorul de apel:

20 bool operator()(char aam_tel) const{

21 return (aam_tel == ’D’);

22 }

23 CuTel& operator=( const CuTel& alt){

24 i f ( th is == &alt) return * th is ;

25 am_tel = alt.am_tel;

26 return * th is ;

27 }

28 CuTel(const CuTel& alt) :

29 am_tel(alt.am_tel){}

30 ∼CuTel(){am_tel = char();}

191

Page 192: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

31 char citesc() const {

32 return am_tel;

33 }

34 private:

35 char am_tel;

36 };

37 ostream& operator <<(ostream& os,const CuTel& ct){

38 return (os << ct.am_tel);

39 }

40 struct Inreg{

41 str ing nume;

42 CuTel tel;

43 };

44 ostream& operator << (ostream& os,

45 const Inreg& intrare

46 ){

47 os << "\n====\ nNume abonat:\t"

48 << intrare.nume

49 << "\nAre tel:\t"

50 << intrare.tel;

51 CuTel ss = intrare.tel;

52 // folosim operatorul de apel pt. ss:

53 i f (ss(ss.citesc()))

54 os << "\nAre telefon!";

55 os. f lush ();

56 return os;

57 }

58 //obiect -functie:

59 struct CompNum{

60 bool operator()(const Inreg& unu ,

61 const Inreg& doi) const{

62 return (unu.nume < doi.nume);

63 }

64 };

65

66 int main(){

67 vector <Inreg > lista_tel;

68 CuTel aretel(’D’);

69 Inreg Popescu;

70 Popescu.nume = "Ion Popescu";

71 Popescu.tel = aretel;

72 lista_tel.push back(Popescu);

73 Inreg Ionescu;

192

Page 193: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

74 Ionescu.nume = "Maria Ionescu";

75 Ionescu.tel;

76 lista_tel.push back(Ionescu);

77 Inreg Petrescu;

78 Petrescu .nume = "Camil Petrescu ";

79 Petrescu .tel = aretel;

80 lista_tel.push back(Petrescu);

81 //sortare cu predicatul "CompNum ":

82 sort (lista_tel.begin(),lista_tel.end(),CompNum ());

83 for (vector <Inreg >:: i terator p = lista_tel.begin();

84 p != lista_tel.end();

85 ++p

86 ){

87 cout << *p << endl;

88 }

89 getch();

90 return 0;

91 }

Program:> (Intro IHP 77) Urmatoarea afirmatie, “Ursul Panda e un urs!” [22, p. 395],introduce un nou tip de relatie ıntre clasa Panda si clasa Urs, si anume relatiaeste–un78. Reamintesc tehnica de populare79 a obiectelor unei clase cu sub-obiecte din alte clase, ceea ce conduce la relatiile are–un — vezi pagina 129—. Noul mecanism C++ se numeste derivare80 (a claselor) si permite punereaın practica a unei idei esentiale a OO, mostenirea81. Adica, ursul Panda“mosteneste” toate trasaturile unui urs82.

In proiectul de fata implementam o mostenire public, plecand de la clasade baza83 octavian::Numar si ajungand la clasa derivata octavian::Numar

CuSemn.O problema tehnica ın cadrul mostenirii priveste rescrierea84 functiilor–

membru care pastreaza numele, semnatura si tipul datelor de ıntoarcere (dela clasa de baza85) [41, p. 305], [22, p. 402]. Pentru a evita aceasta dificul-

77Adica, Inheritance — mostenire —, Hierarchies — ierarhii de clase —, Polymorphism— polimorfism —.

78 In limba engleza, is–a relationship, cf. [22, p. 414].79Numita si compunere. In limba engleza, composition [22, p. 415] ori containment [41,

p. 740].80 In limba engleza, (class) derivation [22, pg. 391, 394].81 In limba engleza, inheritance.82 In plus, este “simpatic”. . .83 In limba engleza, base class [22, ibid.].84Ori suprascrierea. In limba engleza, overriding [41, p. 311].85Un exemplu imediat este oferit chiar de. . . ursi! Fie ca este Panda ori brun, orice urs

193

Page 194: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

tate, utilizam functii–membru virtuale — apelate prin pointeri sau referintela o baza public, cf. [22, p. 445] —, ce “stiu” sa o aleaga dintre functi-ile–membru identice ale (obiectului) unei clase derivate, vezi [22, p. 450],pe aceea care apartine ın mod direct clasei obiectului implicat ın executiacurenta86. Tipurile de date cu functii virtuale constituie tipuri polimorfe,vezi [41, p. 312]. Pentru a “tine minte” aceste corespondente clasa derivata –functie-membru, de obicei compilatorul va converti numele functiei virtualeıntr-o intrare ın tabela (tabelul) functiei virtuale — vtbl —, formata dinpointeri la functii, cf. [41, pg. 36, 420].

Alta chestiune interesanta se refera la ordinea executiei constructorilor,respectiv destructorilor pentru obiectele unor clase implicate ın relatii are–un, este–un. La liniile 286–290 din codul fisierului format_afisare.cpp, dela pagina 71, am comentat ordinea apelarii destructorilor ın relatia are–un.Lucrurile stau la fel ın cazul mecanismului derivarii: ıntai se executa des-tructorul clasei derivate, apoi cel al clasei de baza [41, p. 307]. De altminteri,pentru o corecta apelare a lor, destructorii ıntr-o ierarhie sunt virtuali [22,p. 457], [41, p. 319] — ca sa obtinem acest efect, este suficient sa etichetamvirtual destructorul clasei de baza —. Voi introduce destructori virtualiın urmatorul proiect VS. Aici, destructorul clasei derivate va fi sintetizat decompilator.

Fireste, pot fi implementati operatori virtual [22, pg. 480, 481], dar nusi constructori virtuali87 [41, p. 424].

Cuvantul cheie protected desemneaza membrii clasei care sunt inaccesi-bili unui apelant obisnuit ınsa pot fi accesati de catre functiile–membru aleclasei care deriva din clasa ın cauza [41, pg. 305, 402, 406].

Intro IHP, functii virtuale: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include "ierarhie.h"

5 int main(){

6 {// pentru evidentierea destructorilor

7 octavian :: NumarCuSemn a( -1.13);

8 octavian ::Numar b(45);

are gheare, deci admite functia urs::sfasie!86Spunem ca functiile virtuale realizeaza legari dinamice sau legari la executie [18, p.

816]. In limba engleza, dynamic binding [22, p. 446] sau run-time binding [41, p. 724].87Un constructor nu poate fi virtual pentru ca trebuie sa “stie” ce construieste la mo-

mentul compilarii. Putem ınsa “mima” un asemenea comportament din partea obiectelorclasei, introducand o clasa fabrica [41, p. 323], cu functii–membru virtuale care sa seocupe de constructia obiectelor.

194

Page 195: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

9 octavian ::Numar* cautare;

10 cautare = &a;

11 cautare ->citire();

12 a.citire2 ();

13 cautare = &b;

14 cautare ->citire();

15 }

16 getch();

17 return 0;

18 }

Intro IHP, functii virtuale: ierarhie.h

1 #ifndef _IERARHIE_

2 #define _IERARHIE_

3

4 namespace octavian{

5 c la s s Numar{

6 public :

7 Numar();

8 exp l i c i t Numar(double);

9 Numar(const Numar&);

10 Numar& operator=( const Numar&);

11 ∼Numar();

12 double citire_numar() const ;

13 void scriere_numar(double);

14 virtua l void citire() const ;

15 s t a t i c int citesc_contor();

16 protected:

17 void citire_departata() const;

18 private:

19 double numar_real;

20 s t a t i c int contor_distrugere;

21 };

22 c la s s NumarCuSemn : public Numar {

23 public :

24 NumarCuSemn();

25 exp l i c i t NumarCuSemn(double);

26 NumarCuSemn(const NumarCuSemn&);

27 NumarCuSemn& operator=( const NumarCuSemn&);

28 void citire() const ;

29 void citire2 () const;

30 private:

31 bool pozitiv;

195

Page 196: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

32 };

33 }

34 #endif

Intro IHP, functii virtuale: ierarhie.cpp

1 #include "ierarhie.h"

2 #include <conio.h>

3 #include <iostream >

4 #include <iomanip >

5 using namespace octavian ;

6

7 #undef ACTIUNE

8 #define ACTIUNE \

9 pr int f s ("\nSuntem in constructorul de baza!"); \

10 i f (contor_distrugere++ == 100){ \

11 pr int f s ("\n++++++++\n" \

12 "Prea multe obiecte " \

13 "din clasa de baza...\n" \

14 ); \

15 getch(); \

16 exit (EXIT FAILURE); \

17 }

18

19 int Numar:: contor_distrugere = 0;

20 int Numar:: citesc_contor(){

21 return Numar:: contor_distrugere;

22 }

23 Numar::Numar() :

24 numar_real(double()) { ACTIUNE }

25 Numar::Numar(double nnum) :

26 numar_real(nnum) { ACTIUNE }

27 Numar::Numar(const Numar& nnumar) :

28 numar_real(nnumar.numar_real) { ACTIUNE }

29 Numar& Numar::operator=( const Numar& nnumar){

30 i f ( th is == &nnumar) return * th is ;

31 numar_real = nnumar.numar_real;

32 return * th is ;

33 }

34 Numar::∼Numar(){

35 Numar:: contor_distrugere --;

36 pr int f s ("\nSuntem in destructorul clasei de baza!"

37 "\nContor: %d\nTastati o litera: ",

38 Numar:: citesc_contor()

196

Page 197: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

39 );

40 getch();

41 }

42 double Numar:: citire_numar() const {

43 return numar_real;

44 }

45 void Numar:: citire_departata() const{

46 pr int f s ("\nNe gasim intr -o clasa derivata!"

47 "\nData citita este in clasa de baza!"

48 "\nValoarea ei este: %f!",

49 citire_numar()

50 );

51 }

52 void Numar:: citire() const{

53 pr int f s ("\nFolosim o functie virtuala!"

54 "\nSuntem in clasa de baza!"

55 "\nValoarea datei este: %f!",

56 citire_numar()

57 );

58 }

59 void Numar:: scriere_numar(double nnu){

60 numar_real = nnu;

61 }

62 NumarCuSemn:: NumarCuSemn() : Numar(), pozitiv( true) {}

63 NumarCuSemn:: NumarCuSemn(double nnum): Numar(nnum) {

64 i f (nnum < 0)

65 pozitiv = f a l s e ;

66 e l se

67 pozitiv = true;

68 }

69 NumarCuSemn:: NumarCuSemn(const NumarCuSemn& nnumar) :

70 Numar(nnumar.Numar:: citire_numar()) {

71 pozitiv = (nnumar.Numar:: citire_numar() >= 0)

72 ? true : f a l s e ;

73 }

74 NumarCuSemn&

75 NumarCuSemn::operator=( const NumarCuSemn& nnumi){

76 i f ( th is == &nnumi) return * th is ;

77 double numar_intern = nnumi.Numar:: citire_numar();

78 pozitiv = (numar_intern >= 0) ? true : f a l s e ;

79 (* th is ).Numar:: scriere_numar(numar_intern);

80 return * th is ;

81 }

197

Page 198: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

82 void NumarCuSemn::citire() const{

83 pr int f s ("\nFolosim o functie virtuala!"

84 "\nSuntem in clasa derivata !"

85 "\nValoarea datei este: %f!",

86 (* th is ).citire_numar()

87 );

88 }

89 void NumarCuSemn:: citire2 () const{

90 pr int f s ("\nSemnul datei este\"%c\"!",

91 pozitiv == true ? ’+’ : ’-’

92 );

93 Numar:: citire_departata();

94 }

Program:> (Intro IHP) In proiectul de fata, folosim campuri protected. Pe termenlung, utilizarea datelor–membru — si nu functiilor–membru — protected

constituie o eroare de design [41, p. 405], existand posibilitatea coruperii lorvia mostenire. Ideea esentiala a arhitecturii unei ierarhii de clase este ca ba-za ierarhiei sa fie o interfata, adica o clasa avand doar functii–membru, faraconstructor ori destructor, ın timp ce datele sa intervina pe parcurs, dreptcampuri ın clasele derivate. O asemenea abordare apare ın limbajul C#, un-de toate clasele deriva din System.Object, vezi [32, p. 167/166, Chap. 18].Ca ın orice chestiune de design, si acestui model i se poate adresa o critique,vezi [41, pg. 417, 418].

Folosirea campurilor protected tine de ierarhiile clasice de clase [41, p.315], [22, p. 407].

198

Page 199: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Intrare

#index : ui (unsigned int)

#contor distrugere : ui

+<<create>>Intrare()+<<create>>Intrare(ui)+<<create>>Intrare(const Intrare&)+operator=(const Intrare&) : Intrare&

- operator int()+<<destroy>>∼Intrare()+afisare() : void

Nume

#nume intr : char*

#<<create>>Nume()+<<create>>Nume(ui)+<<create>>Nume(ui, char*)+<<create>>Nume(const Nume&)+operator=(const Nume&) : Nume&

+<<destroy>>∼Nume()+salut() : void

+salutdoi() : void

#afisare() : void

Telefon

#tip tel : char*#nr tel : char*

#<<create>>Telefon()+<<create>>Telefon(char*)+<<create>>Telefon(char*, char*)+<<create>>Telefon(const Telefon&)+operator=(const Telefon&) : Telefon&

+<<destroy>>∼Telefon()- operator char*()

NumeSiPrenume

#prenume intr : char*

#<<create>>NumeSiPrenume()#<<create>>NumeSiPrenume(ui)#<<create>>NumeSiPrenume(ui, char*)+<<create>>NumeSiPrenume(ui, char*, char*)+<<create>>NumeSiPrenume(const NumeSiPrenume&)+operator=(const NumeSiPrenume&) : NumeSiPrenume&+<<destroy>>∼NumeSiPrenume()+salutare() : void

IntrTel

- <<create>>IntrTel()- <<create>>IntrTel(ui)- <<create>>IntrTel(ui, char*)- <<create>>IntrTel(ui, char*, char*)- <<create>>IntrTel(ui, char*, char*, char*)+<<create>>IntrTel(ui, char*, char*, char*, char*)- <<create>>IntrTel(const IntrTel&)- operator=(const IntrTel&) : IntrTel&+<<destroy>>∼IntrTel()+afistel() : void

- salutare() : void

199

Page 200: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Intro IHP, destructori virtuali, mostenire multipla: program.cpp

1 #include <cstdlib >

2 #include <cstdio >

3 #include <conio.h>

4 #include "ierarhie.h"

5 using namespace octavian ;

6

7 int main(){

8 {/* ---

9 Punem in evidenta destructorii:

10 activati MODUL_VERIFICARE din

11 fisierul "ierarhie .cpp"!

12 ---*/

13 NumeSiPrenume a(23,"Knut","Hamsun");

14 NumeSiPrenume b(14,"Kurt","Vonnegut ");

15 }

16 getch();

17 system("cls");

18 {

19 IntrTel unu(7,"Khaled","Hosseini ",

20 "mobil","123444444"

21 );

22 unu.afistel ();

23 }

24 getch();

25 return 0;

26 }

Intro IHP, destructori virtuali, mostenire multipla: ierarhie.h

1 #ifndef _IERARHIE_

2 #define _IERARHIE_

3

4 namespace octavian{

5 typedef unsigned int ui;

6 c la s s Intrare{

7 public :

8 Intrare ();

9 exp l i c i t Intrare(ui);

10 Intrare(const Intrare &);

11 Intrare& operator=( const Intrare &);

12 virtua l ∼Intrare ();

13 virtua l void afisare ();

14 protected:

200

Page 201: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

15 ui index;

16 s t a t i c ui contor_distrugere;

17 private:

18 operator int ();

19 };

20

21 void afisare(Intrare&);

22

23 c la s s Nume: public Intrare{

24 public :

25 exp l i c i t Nume(ui);

26 Nume(ui, char*);

27 Nume(const Nume&);

28 Nume& operator=( const Nume&);

29 virtua l ∼Nume();

30 void salut();

31 virtua l void salutdoi ();

32 protected:

33 Nume();

34 char* nume_intr;

35 void afisare ();

36 };

37

38 c la s s NumeSiPrenume: private Nume{

39 public :

40 NumeSiPrenume(ui,char*,char*);

41 NumeSiPrenume(const NumeSiPrenume&);

42 NumeSiPrenume& operator=( const NumeSiPrenume&);

43 virtua l ∼NumeSiPrenume();

44 using octavian ::Nume::salut;

45 // vezi Stroustrup , C++ Special Edition , p. 393

46 virtua l void salutare ();

47 protected:

48 NumeSiPrenume();

49 exp l i c i t NumeSiPrenume(ui);

50 NumeSiPrenume(ui, char*);

51 char* prenume_intr;

52 };

53

54 c la s s Telefon{

55 public :

56 exp l i c i t Telefon(char*);

57 Telefon(char*,char*);

201

Page 202: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

58 Telefon(const Telefon &);

59 Telefon& operator=( const Telefon &);

60 virtua l ∼Telefon ();

61 protected:

62 Telefon ();

63 char* tip_tel;

64 char* nr_tel;

65 private:

66 operator char*();

67 };

68

69 c la s s IntrTel: public NumeSiPrenume ,

70 private Telefon{

71 public :

72 IntrTel(ui,char*,char*,char*,char*);

73 ∼IntrTel ();

74 void afistel ();

75 private:

76 IntrTel ();

77 exp l i c i t IntrTel(ui);

78 IntrTel(ui,char*);

79 IntrTel(ui,char*,char*);

80 IntrTel(ui,char*,char*,char*);

81 IntrTel(const IntrTel &);

82 IntrTel& operator=( const IntrTel &);

83 void salutare ();

84 };

85 }

86 #endif

Intro IHP, destructori virtuali, mostenire multipla: ierarhie.cpp

1 #include "ierarhie.h"

2 #include <conio.h>

3 #include <cstring >

4 #include <iostream >

5 #include <iomanip >

6

7 #undef MODUL_VERIFICARE

8 #define MODUL_VERIFICARE 1

9 #undef MODUL_VERIFICARE

10 #undef NOTATIE_CONVENABILA

11 #define NOTATIE_CONVENABILA int numar_intern;

12 #undef EXPRESIE_CONVENABILA

202

Page 203: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

13 /* ---

14 Atentie la macrourile cu argument :

15 fara spatiu intre "_CONVENABILA" si "(z,q)"!

16 ---*/

17 #define EXPRESIE_CONVENABILA(z,q) \

18 numar_intern = s ta t i c cas t < int >( \

19 std:: str len ( \

20 ## q \

21 ) \

22 ) + 1 /* + 30 */; \

23 z ## = new char[numar_intern]; \

24 strcpy s (z ## , \

25 numar_intern ,\

26 ## q \

27 );

28

29 #undef TESTARE_CONTOR_DISTRUGERE

30 #define TESTARE_CONTOR_DISTRUGERE \

31 i f (octavian :: Intrare :: contor_distrugere++ == 10){ \

32 pr int f s ("\nPrea multe obiecte Intrare ...\n" \

33 "Inchid programul!"); \

34 getch(); \

35 exit (EXIT FAILURE); \

36 }

37

38 octavian ::ui

39 octavian :: Intrare :: contor_distrugere = 0;

40 octavian ::Intrare :: Intrare (){

41 TESTARE_CONTOR_DISTRUGERE

42 index = ui();

43 }

44 octavian ::Intrare :: Intrare(ui iindex){

45 TESTARE_CONTOR_DISTRUGERE

46 index = iindex;

47 }

48 octavian ::Intrare ::∼Intrare (){

49 octavian :: Intrare :: contor_distrugere --;

50 #i fd e f MODUL_VERIFICARE

51 pr int f s ("\nNumarul de obiecte \"Intrare \" "

52 "inca in viata: %d\n",

53 s ta t i c cas t < int >(

54 octavian :: Intrare :: contor_distrugere

55 )

203

Page 204: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

56 );

57 std::cout << "\nSters Intrarea : "

58 << index

59 << std::endl;

60 #endif

61 }

62 octavian ::

63 Intrare ::Intrare(const octavian :: Intrare& intr){

64 TESTARE_CONTOR_DISTRUGERE

65 index = intr.index;

66 }

67 octavian ::Intrare&

68 octavian ::

69 Intrare ::operator=( const octavian :: Intrare& intr){

70 i f ( th is ==&intr) return * th is ;

71 index = intr.index;

72 return * th is ;

73 }

74 void octavian :: Intrare ::afisare (){

75 std::cout << "\n=======\ n"

76 "Intrarea nr. "

77 << index

78 << "\n========\n"

79 << std::endl;

80 }

81 void octavian :: afisare(octavian :: Intrare& intr){

82 intr.afisare ();

83 }

84 octavian ::Nume::Nume()

85 : octavian ::Intrare (){

86 NOTATIE_CONVENABILA

87 EXPRESIE_CONVENABILA(nume_intr ,"fara nume")

88 }

89 octavian ::Nume::Nume(ui iindex)

90 : octavian ::Intrare(iindex){

91 NOTATIE_CONVENABILA

92 EXPRESIE_CONVENABILA(nume_intr ,"fara nume")

93 }

94 octavian ::Nume::Nume(ui iindex , char* nnume)

95 : octavian ::Intrare(iindex){

96 NOTATIE_CONVENABILA

97 EXPRESIE_CONVENABILA(nume_intr ,nnume)

98 }

204

Page 205: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

99 octavian ::Nume::∼Nume(){

100 delete [] nume_intr;

101 #i fd e f MODUL_VERIFICARE

102 std::cout << "\nSters Nume: "

103 << index

104 << std::endl;

105 #endif

106 }

107 octavian ::Nume::Nume(const octavian ::Nume& nnume){

108 index = nnume.index;

109 NOTATIE_CONVENABILA

110 EXPRESIE_CONVENABILA(nume_intr ,nnume.nume_intr)

111 }

112 octavian ::Nume&

113 octavian ::

114 Nume::operator=( const octavian ::Nume& nnume){

115 i f ( th is ==& nnume) return * th is ;

116 index = nnume.index;

117 delete [] nume_intr;

118 NOTATIE_CONVENABILA

119 EXPRESIE_CONVENABILA(nume_intr ,nnume.nume_intr)

120 return * th is ;

121 }

122 void octavian ::Nume::salut(){

123 std::cout << "\nSalut de la nr. "

124 << index

125 << std::endl;

126 }

127 void octavian ::Nume:: salutdoi (){

128 std::cout << "\nSalut din clasa Nume!"

129 << std::endl;

130 }

131 void octavian ::Nume::afisare (){

132 std::cout << "\n=======\n"

133 "Intrarea nr. "

134 << index

135 << "\nNume: "

136 << nume_intr

137 << "\n========"

138 << std::endl;

139 }

140 octavian :: NumeSiPrenume:: NumeSiPrenume()

141 : octavian ::Nume(){

205

Page 206: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

142 NOTATIE_CONVENABILA

143 EXPRESIE_CONVENABILA(prenume_intr ,"Fara prenume!")

144 }

145 octavian :: NumeSiPrenume:: NumeSiPrenume(ui iindex)

146 : octavian ::Nume(iindex){

147 NOTATIE_CONVENABILA

148 EXPRESIE_CONVENABILA(prenume_intr ,"Fara prenume!")

149 }

150 octavian ::

151 NumeSiPrenume:: NumeSiPrenume(ui iindex , char* nnume)

152 : octavian ::Nume(iindex ,nnume){

153 NOTATIE_CONVENABILA

154 EXPRESIE_CONVENABILA(prenume_intr ,"Fara prenume!")

155 }

156 octavian ::

157 NumeSiPrenume::

158 NumeSiPrenume(ui iindex , char* nnume , char* pprenume )

159 : octavian ::Nume(iindex ,nnume){

160 NOTATIE_CONVENABILA

161 EXPRESIE_CONVENABILA(prenume_intr ,pprenume )

162 }

163 octavian :: NumeSiPrenume::∼NumeSiPrenume(){

164 delete [] prenume_intr;

165 #i fd e f MODUL_VERIFICARE

166 std::cout << "\nSters NumeSiPrenume: "

167 << index

168 << std::endl;

169 #endif

170 }

171 octavian ::

172 NumeSiPrenume::

173 NumeSiPrenume(const octavian :: NumeSiPrenume& nnume){

174 index = nnume.index;

175 NOTATIE_CONVENABILA

176 EXPRESIE_CONVENABILA(nume_intr ,nnume.nume_intr)

177 EXPRESIE_CONVENABILA(prenume_intr ,nnume.prenume_intr)

178 }

179 octavian :: NumeSiPrenume&

180 octavian ::

181 NumeSiPrenume::

182 operator=( const octavian :: NumeSiPrenume& nnume){

183 i f ( th is ==& nnume) return * th is ;

184 index = nnume.index;

206

Page 207: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

185 delete [] nume_intr;

186 NOTATIE_CONVENABILA

187 EXPRESIE_CONVENABILA(nume_intr ,nnume.nume_intr)

188 delete [] prenume_intr;

189 EXPRESIE_CONVENABILA(prenume_intr ,nnume.prenume_intr)

190 return * th is ;

191 }

192 void octavian :: NumeSiPrenume:: salutare (){

193 std::cout << "\n=======\n"

194 "Intrarea nr. "

195 << index

196 << "\nNume: "

197 << nume_intr

198 << "\nPrenume : "

199 << prenume_intr

200 << "\nFunctia \"salutdoi \" mostenita:"

201 << std::endl;

202 salutdoi ();

203 std::cout << "\n========";

204 std::cout. f lush ();

205 }

206 octavian ::Telefon :: Telefon (){

207 NOTATIE_CONVENABILA

208 EXPRESIE_CONVENABILA(tip_tel ,"Fara tip tel!")

209 EXPRESIE_CONVENABILA(nr_tel ,"Fara nr tel!")

210 }

211 octavian ::Telefon :: Telefon(char* tel){

212 NOTATIE_CONVENABILA

213 EXPRESIE_CONVENABILA(tip_tel ,"Neprecizat!")

214 EXPRESIE_CONVENABILA(nr_tel ,tel)

215 }

216 octavian ::

217 Telefon ::Telefon(char* ttip_tel ,char* nnr_tel){

218 NOTATIE_CONVENABILA

219 EXPRESIE_CONVENABILA(tip_tel ,ttip_tel )

220 EXPRESIE_CONVENABILA(nr_tel ,nnr_tel)

221 }

222 octavian ::

223 Telefon ::Telefon(const octavian :: Telefon& tel){

224 NOTATIE_CONVENABILA

225 EXPRESIE_CONVENABILA(tip_tel ,tel.tip_tel)

226 EXPRESIE_CONVENABILA(nr_tel ,tel.nr_tel)

227 }

207

Page 208: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

228 octavian ::Telefon&

229 octavian ::

230 Telefon ::

231 operator=( const octavian :: Telefon& tel){

232 i f ( th is ==&tel) return * th is ;

233 delete [] tip_tel;

234 NOTATIE_CONVENABILA

235 EXPRESIE_CONVENABILA(tip_tel ,tel.tip_tel)

236 delete [] nr_tel;

237 EXPRESIE_CONVENABILA(nr_tel ,tel.nr_tel)

238 return * th is ;

239 }

240 octavian ::Telefon ::∼Telefon (){

241 #i fd e f MODUL_VERIFICARE

242 std::cout << "\nSters Telefon: "

243 << tip_tel

244 << " "

245 << nr_tel

246 << std::endl;

247 #endif

248 delete [] tip_tel;

249 delete [] nr_tel;

250 }

251 octavian ::

252 IntrTel ::

253 IntrTel(ui iindex ,char* nnume ,char* pprenume ,

254 char* ttip ,char* ttel

255 ) :

256 octavian :: NumeSiPrenume(iindex ,nnume ,pprenume ),

257 octavian :: Telefon(ttip ,ttel) {}

258 octavian ::IntrTel ::∼IntrTel (){}

259 void octavian :: IntrTel ::salutare (){

260 ( s ta t i c cas t <octavian ::NumeSiPrenume >(* th is )).

261 salutare ();

262 }

263 void octavian :: IntrTel ::afistel (){

264 std::cout << "\n++++++++++";

265 std::cout. f lush ();

266 salutare ();

267 std::cout << "\nFunctia \"salut\" mostenita:";

268 std::cout. f lush ();

269 salut();

270 std::cout << "+++++++++"

208

Page 209: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

271 << std::endl;

272 }

5 Si acum?

Odata ajunsi aici, sa ne tragem rasuflarea! Putem face infinite calatorii. . .Iata cateva directii — si cateva carti, din cele care mi-au placut! —:

mecanismul try – catch de tratare a erorilor (exceptiilor) ın C++ [41, p. 355si urm.]; sabloane de design (design patterns , GOF, etc) [41, p. 709], [34,Cap. 6]; Qt [30]; Boost [5]; MFC [2]; COM, ATL [44, 35]; C++/CLI [17]; C#[32, 45, 1] — [16] este chiar standardul limbajului, adnotat —; Java [19].

Inchei prezentarea acestor note de laborator cu doua proiecte “vizuale”privind convertorul de temperatura (Fahrenheit −→ Celsius) — vezi pagina18 —.

Program:> (Intro Windows C/C++) In Figura 13 se gaseste fereastra de calcul — acce-sibila via meniul Activitati — a programului. Figurile 14, 15 contin iconita(sigla) convertorului ın variantele 32× 32, respectiv 16× 16 pixeli, cf. [31, p.364].

Figura 13

Intro “visual” C/C++: convertor_FC_4.c

1 #include "headerulnostru.h"

209

Page 210: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 14

2

3 // functia main: "entry point"

4 int WINAPI WinMain(HINSTANCE hInstance,

5 HINSTANCE hPrevInstance ,

6 PSTR szCmdLine ,

7 int iCmdShow ){

8

9 s t a t i c TCHAR

10 szNumeleClasei[] = TEXT("MeniulMare"),

11 szTitlulProgramului[] = TEXT("Aplicatie Convertor"),

12 szNumeCutieDialog[] = TEXT("Cutie de dialog:");

13 HWND hwnd;

14 MSG msg;

15 WNDCLASS wndclass;

16

17 // implementam structura WNDCLASS

18 //(clasa ferestrei principale)

19 wndclass . sty le = CSHREDRAW | CSVREDRAW;

20 wndclass .lpfnWndProc = ProcesFereastra;

21 wndclass .cbClsExtra = 0;

22 wndclass .cbWndExtra = 0;

23 wndclass .hInstance = hInstance;

24 //iconita (sigla) programului

25 //daca nu avem iconita folosim instructiunea:

210

Page 211: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

Figura 15

26 //wndclass .hIcon = LoadIcon (NULL ,IDI_APPLICATION);

27 wndclass .hIcon = LoadIcon(

28 hInstance,

29 MAKEINTRESOURCE(IDI_ICON ));

30 wndclass .hCursor = LoadCursor(NULL,IDC_ARROW) ;

31 wndclass .hbrBackground = (HBRUSH) (COLORWINDOW - 3);

32 wndclass .lpszMenuName = szNumeleClasei;

33 wndclass . lpszClassName = szNumeleClasei;

34

35 // inregistram clasa de ferestre

36 i f (!RegisterClass (& wndclass)){

37 MessageBox(

38 NULL,

39 TEXT("Probleme cu inregistrarea clasei!"),

40 szNumeCutieDialog ,

41 MBICONERROR

42 );

43 return 0 ;

44 }

45

46 //cream fereastra:

47 hwnd = CreateWindow(szNumeleClasei ,

48 szTitlulProgramului ,

49 WSOVERLAPPEDWINDOW,

211

Page 212: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

50 CWUSEDEFAULT,

51 CWUSEDEFAULT,

52 CWUSEDEFAULT,

53 CWUSEDEFAULT,

54 NULL,

55 NULL,

56 hInstance,

57 NULL

58 );

59

60 // verificarea crearii ferestrei

61 i f (!hwnd){

62 MessageBox(

63 NULL,

64 TEXT("Nu putem crea clasa!\ nIesim..."),

65 szNumeCutieDialog ,

66 MBICONERROR

67 );

68 return 0;

69 }

70

71 //aratam fereastra:

72 ShowWindow(hwnd ,iCmdShow );

73 UpdateWindow(hwnd) ;

74

75 //bucla de mesaje:

76 while (GetMessage(&msg,NULL,0,0)){

77 TranslateMessage(&msg);

78 DispatchMessage(&msg);

79 }

80 return msg.wParam ;

81 }

Intro “visual” C/C++: headerulnostru.h

1 #ifndef _HEADERULNOSTRU_

2 #define _HEADERULNOSTRU_

3

4 #include <Windows.h>

5 #include "resource.h"

6

7 LRESULT CALLBACK

8 ProcesFereastra(HWND,

9 UINT,

212

Page 213: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

10 WPARAM,

11 LPARAM

12 );

13

14 BOOL CALLBACK

15 ProcesDialogConvertor(HWND,

16 UINT,

17 WPARAM,

18 LPARAM

19 );

20

21 BOOL CALLBACK

22 ProcesDialogInformatie(HWND,

23 UINT,

24 WPARAM,

25 LPARAM

26 );

27

28 #endif

Intro “visual” C/C++: resource.h

1 #define IDI_ICON 101

2 #define IDM_DESPRE 40001

3 #define IDM_CONVERSIE 40002

4 #define IDM_IESIRE 40003

5 #define IDC_EDIT1 40004

6 #define IDC_EDIT2 40005

7 #define IDC_STATIC -1

Intro “visual” C/C++: ajutor.c

1 #include "headerulnostru.h"

2

3 LRESULT CALLBACK

4 ProcesFereastra(HWND hwnd ,

5 UINT message ,

6 WPARAM wParam ,

7 LPARAM lParam

8 ){

9

10 s t a t i c HINSTANCE hInstance;

11

12 switch(message){

13 case WMCREATE:

213

Page 214: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

14 hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;

15 return 0;

16

17 case WMCOMMAND:

18 switch(LOWORD(wParam)){

19 case IDM_DESPRE:

20 DialogBox(hInstance,

21 TEXT("Informatie"),

22 hwnd ,

23 ProcesDialogInformatie

24 );

25 break;

26 case IDM_CONVERSIE:

27 DialogBox(hInstance,

28 TEXT("Caseta"),

29 hwnd ,

30 ProcesDialogConvertor

31 );

32 break;

33 case IDM_IESIRE:

34 SendMessage(hwnd ,WMCLOSE,0,0);

35 break;

36 }//final switch

37 return 0;//final WM_COMMAND

38

39 case WMDESTROY:

40 PostQuitMessage (0);

41 return 0;

42 }//final switch(message)

43

44 return DefWindowProc(hwnd ,message ,wParam ,lParam);

45 }

46

47 BOOL CALLBACK

48 ProcesDialogInformatie(HWND hdlg ,

49 UINT message ,

50 WPARAM wParam ,

51 LPARAM lParam

52 ){

53 switch(message){

54 case WMINITDIALOG:

55 return TRUE;

56

214

Page 215: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

57 case WMCOMMAND:

58 switch (LOWORD(wParam)){

59 case IDOK:

60 case IDCANCEL:

61 EndDialog(hdlg ,FALSE);

62 return TRUE;

63 }// final switch LOWORD(wParam)

64 break;

65 }//final switch(message)

66 return FALSE;

67 }

68

69 BOOL CALLBACK

70 ProcesDialogConvertor(HWND hdlg ,

71 UINT message ,

72 WPARAM wParam ,

73 LPARAM lParam

74 ){

75

76 s t a t i c int numar;

77

78 switch(message){

79 case WMINITDIALOG:

80 return TRUE;

81

82 case WMCOMMAND:

83 switch (LOWORD(wParam)){

84 case IDOK:{

85 BOOL bTran = FALSE;

86 DOUBLE calcul = 0.0;

87 numar = GetDlgItemInt(hdlg ,

88 IDC_EDIT1 ,

89 &bTran ,

90 TRUE

91 );

92 calcul = 0.56 * (numar - 32);

93 numar = ( int ) calcul;

94 SetDlgItemInt(hdlg ,

95 IDC_EDIT2 ,

96 numar ,

97 TRUE

98 );

99 return TRUE;

215

Page 216: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

100 }//final IDOK

101

102 case IDCANCEL:

103 EndDialog(hdlg ,FALSE);

104 return TRUE;

105 }//final switch LOWORD(wParam)

106 break;

107 }//final switch(message)

108 return FALSE;

109 }

Inseram codul de mai jos ıntr-un fisier txt, pe care ıl salvam dreptresurse.rc si ıl introducem ın directorul C:\ProiecteleMele_Cpp\numeleproiectului\numeleproiectului. Apoi, ın Visual Studio, cautam “iconi-ta” Show All Files a ferestrei Solution Explorer. Daca totul functionea-za corect, ın lista din interiorul ferestrei vom remarca fisierul resurse.rc.Pozitionand cursorul pe mica imagine a acestuia, apasam butonul drept almouse-ului si alegem, din fereastra pop-up de optiuni, varinta Include In

Project.

Intro “visual” C/C++: convertor_FC_4.rc

1 #include "resource.h"

2 #include <Windows.h>

3

4 IDI_ICON ICON "convertor_FC_4.ico"

5

6 MENIULMARE MENU DISCARDABLE

7 BEGIN

8 POPUP "Activitati"

9 BEGIN

10 MENUITEM "Despre", IDM_DESPRE

11 MENUITEM "Conversie", IDM_CONVERSIE

12 MENUITEM "Iesire", IDM_IESIRE

13 END

14 END

15 INFORMATIE DIALOG DISCARDABLE 20,20,150,70

16 STYLE DSMODALFRAME | WSPOPUP | WS VISIBLE |

17 WSCAPTION | WSSYSMENU

18 CAPTION "Info: Versiunea 1.1"

19 FONT 10, "MS Sans Serif"

20 BEGIN

21 LTEXT "Autor: Octavian",IDC_STATIC ,10,8,150,8

22 LTEXT "Data: 5 martie 2013",IDC_STATIC ,10,24,150,8

216

Page 217: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

23 LTEXT "Convertor Fahrenheit --> Celsius",IDC_STATICց

(cont.) ,10,40,100,8

24 LTEXT "Formula: C = 0.56 * (F - 32)",IDC_STATICց

(cont.) ,10,56,100,8

25 DEFPUSHBUTTON "Iesire",IDCANCEL,100 ,20 ,30 ,12

26 END

27 CASETA DIALOG DISCARDABLE 20,20,260,70

28 STYLE DSMODALFRAME | WSPOPUP | WS VISIBLE |

29 WSCAPTION | WSSYSMENU

30 CAPTION "Operator de conversie"

31 FONT 10, "MS Sans Serif"

32 BEGIN

33 RTEXT "Temperatura in F:",IDC_STATIC ,36,8,80,8

34 EDITTEXT IDC_EDIT1 ,140,6,61,13

35 RTEXT "Temperatura in C:",IDC_STATIC ,36,24,80,8

36 EDITTEXT IDC_EDIT2 ,140 ,22 ,61 ,13

37 PUSHBUTTON "Executie ",IDOK,60,50,50,14

38 DEFPUSHBUTTON "Renuntare",IDCANCEL,150 ,50 ,50 ,14

39 END

Program:> (Intro C#) Construim un director nou, C:\ProiecteleMele_Cs, dupacare apelam Visual Studio-ul. Alegem New Project, apoi, vezi Figura 2,ın lista Installed Templates, optam pentru Visual C#. In tabelul central,selectam Windows Forms Application. Numele proiectului — ın primul dincampurile albe din partea de jos a ferestrei pop-up New Project — poatefi primul_convertor_cs. Apoi, din fereastra Solution Explorer, folosindbutonul drept al mouse-ului, optam — la fel ca ın cazul proiectelor C++

— pentru varianta Add New Item. Din fereastra de optiuni declansata deaceasta alegere, selectam C# Code File.

Am ajuns unde trebuia! In fereastra dedicata acestui Code File — pro-babil, numele sau este CodeFile1.cs — inseram liniile de cod listate ıncontinuare. Dupa aceea, ınainte de a ıncepe compilarea, stergem fisierulProgram.cs din proiectul VS — adica, ne pozitionam cu cursorul pe mi-ca imagine a acestui item din Solution Explorer si alegem Exclude From

Project din fereastra de optiuni declansata de apasarea pe butonul drept almouse-ului — !

Intro C#: CodFile1.cs

1 // Copyright: Octavian , 2011 -- 2014

2 using System;

3 using System.Windows.Forms;

4 using System.Drawing;

5 namespace convertor_nou{

217

Page 218: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

6 // fereastra mare a programului

7 c la s s MainWindow : Form{

8 private

9 MenuStrip meniuprincipal = new MenuStrip();

10 private

11 ToolStripMenuItem

12 meniuActivitati = new ToolStripMenuItem ();

13 private

14 ToolStripMenuItem

15 meniuActivitatiConversie = new ToolStripMenuItem ();

16 private

17 ToolStripMenuItem

18 meniuActivitatiIesire = new ToolStripMenuItem ();

19 private

20 ToolStripMenuItem

21 meniuDespre = new ToolStripMenuItem ();

22 private

23 ToolStripMenuItem

24 meniuDespreInfo = new ToolStripMenuItem ();

25 public MainWindow() { }

26 public

27 MainWindow( str ing titlu , int inaltime , int latime){

28 Text = titlu;

29 Width = latime;

30 Height = inaltime;

31 CenterToScreen();

32 ConstructiaMeniului();

33 }

34 private void ConstructiaMeniului(){

35 meniuActivitati.Text = "Activit\u0103\u0163i";

36 meniuprincipal.Items.Add(meniuActivitati);

37 meniuDespre.Text = "Despre";

38 meniuprincipal.Items.Add(meniuDespre);

39 // meniul de conversie:

40 meniuActivitatiConversie.Text = "Conversie";

41 meniuActivitati.DropDownItems.

42 Add(meniuActivitatiConversie);

43 meniuActivitatiConversie.Click += (o, s) =>

44 {

45 FereastraConversie fer = new FereastraConversie();

46 fer.Show();

47 };

48 // meniul info:

218

Page 219: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

49 meniuDespreInfo.Text = "Info";

50 meniuDespre.DropDownItems.Add(meniuDespreInfo);

51 meniuDespreInfo.Click += (o, s) =>

52 {

53 FereastraInfo fer = new FereastraInfo();

54 fer.Show();

55 };

56 // meniul iesire:

57 meniuActivitatiIesire.Text = "Ie\u015Fire";

58 meniuActivitati.DropDownItems.

59 Add(meniuActivitatiIesire);

60 meniuActivitatiIesire.

61 Click += (o, s) => Application .Exit();

62 // gruparea meniurilor:

63 Controls .Add( th is .meniuprincipal);

64 MainMenuStrip = th is .meniuprincipal;

65 }

66 }

67 //helper pentru TextBox -uri multilinie:

68 c la s s Ajutor{

69 public

70 void CutieMare( re f TextBox cutie ,

71 bool scroll_uri = f a l s e ){

72 cutie.Multil ine = true;

73 cutie.WordWrap = true;

74 i f (scroll_uri == true)

75 cutie.ScrollBars = ScrollBars.Vertical ;

76 }

77 }

78 //partea de conversie:

79 c la s s FereastraConversie : Form{

80 public TextBox txtFahr = new TextBox();

81 public TextBox txtCels = new TextBox();

82 public FereastraConversie(){

83 FormBorderStyle = FormBorderStyle.FixedDialog;

84 MinimizeBox = f a l s e ;

85 MaximizeBox = f a l s e ;

86 CenterToParent ();

87 ShowInTaskbar = f a l s e ;

88 Text = "Conversia";

89 Width = 400;

90 Height = 200;

91 ConstructiaFerestreiConversie();

219

Page 220: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

92 }

93 private void ConstructiaFerestreiConversie(){

94 //TexBox -ul cu Fahrenheit:

95 Ajutor ajut = new Ajutor();

96 ajut.CutieMare( re f txtFahr);

97 txtFahr.Width = 200;

98 txtFahr.Height = 100;

99 txtFahr.Location = new Point(25, 25);

100 txtFahr.Text = "Fahrenheit: Cite\u015Fte -m\u0103!"

101 + Environment.NewLine

102 + "\u015Eterge\u0163i acest text ,"

103 + Environment.NewLine

104 + "apoi scrie\u0163i aici temperatura \u00EEn F,"

105 + Environment.NewLine

106 + "dup\u0103 care da\u0163i \"dublu click\" "

107 + Environment.NewLine

108 + "cu mouse -ul (tot \u00EEn aceast\u0103 cutie).";

109 //TextBox -ul cu Celsius:

110 txtCels.Width = 120;

111 txtCels.Text = "Celsius: ";

112 txtCels.Left = txtFahr.Left + 220;

113 txtCels.Top = txtFahr.Top;

114 // introducerea acestor controale

115 //in fereastra de conversie:

116 Controls .AddRange(new Control []{txtFahr ,

117 txtCels });

118 //contor de input cu greseli:

119 int contor = 0;

120 // evenimentul central al aplicatiei:

121 txtFahr.MouseDoubleClick += (o, s) =>

122 {

123 //logica aplicatiei de conversie:

124 try{

125 th is .Width = 400;

126 txtFahr.Width = 200;

127 str ing preiau_date = txtFahr.Text;

128 double intern_calcul = Double.Parse(preiau_date);

129 // daca gresesc odata , contorul devine 1.

130 // Nefiind 3, daca scriu corect (este a doua incercare ,

131 // practic ...) contorul nu se reseteaza , deci , in

132 //viitor , nu voi mai putea gresi decat de 2 ori ,

133 // ceea ce nu este corect ...

134 // Regula de aur: daca , dupa o greseala , introduc

220

Page 221: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

135 // datele corect , atunci greseala se anuleaza ... :)))

136 contor = 0;

137 double celsius = 0.56 * (intern_calcul - 32);

138 str ing afisare_rezultat = celsius.ToString();

139 txtCels.Left = txtFahr.Left + 220;

140 txtCels.Width = 120;

141 txtCels.Text = "Celsius: " + afisare_rezultat;

142 }

143 catch{

144 contor ++;

145 i f (contor == 3){

146 txtFahr.Width = 130;

147 txtFahr.

148 Text = "Ierta\u0163i -m\u0103 , dar cred c\u0103"

149 + Environment.NewLine

150 + "v-a\u0163i plictisit...";

151 str ing data_de_azi = DateTime.Now.ToString();

152 txtCels.Left = txtFahr.Left + 150;

153 txtCels.Width = 180;

154 txtCels.Text = "Suntem \u00EEn: " + data_de_azi;

155 contor = 0;

156 th is .Width = 450;

157 }

158 e l se {

159 th is .Width = 400;

160 txtCels.Width = 120;

161 txtCels.Text = "Celsius: ";

162 txtFahr.Width = 200;

163 txtFahr.

164 Text = "A\u0163i gre\u015Fit :((("

165 + Environment.NewLine

166 + "la introducerea datelor."

167 + Environment.NewLine

168 + "Se mai \u00EEnt\u00E2mpl\u0103!"

169 + Environment.NewLine

170 + "\u015Eterge\u0163i totul \u015Fi :)))"

171 + Environment.NewLine

172 + "relua\u0163i introducerea datelor ...";

173 txtCels.Left = txtFahr.Left + 220;

174 }

175 }

176 };

177 }

221

Page 222: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

178 }

179 //partea de info:

180 c la s s FereastraInfo : Form{

181 public TextBox txtVers = new TextBox();

182 public TextBox txtAut = new TextBox();

183 public TextBox txtCopyr = new TextBox();

184 public TextBox txtData = new TextBox();

185 public TextBox txtTransformare = new TextBox();

186 public TextBox txtFormula = new TextBox();

187 public FereastraInfo(){

188 FormBorderStyle = FormBorderStyle.FixedDialog;

189 MinimizeBox = f a l s e ;

190 MaximizeBox = f a l s e ;

191 CenterToParent ();

192 ShowInTaskbar = f a l s e ;

193 Text = "Informa\u0163ii";

194 Width = 290;

195 Height = 320;

196 ConstructiaFerestreiInfo();

197 }

198 private void ConstructiaFerestreiInfo(){

199 int ecartament = 50;

200 int sus = 25;

201 TextBox[] sir = new TextBox[] {txtTransformare ,

202 txtFormula ,

203 txtVers ,

204 txtData ,

205 txtAut ,

206 txtCopyr };

207 Ajutor ajut = new Ajutor();

208 ajut.CutieMare( re f txtVers , true);

209 txtVers.

210 Text = "Versiune: 2.0"

211 + Environment.NewLine

212 + "Realizat\u0103 \u00EEn C#, platforma: .NET 4.0"

213 + Environment.NewLine

214 + "Prima versiune : Win32 API , COM";

215 txtData.Text = "Data lans\u0103rii : 31 iulie 2011";

216 txtAut.Text = "Autor: Octavian ";

217 txtCopyr .Text = "Drepturi de autor: DAL";

218 ajut.CutieMare( re f txtTransformare);

219 txtTransformare.Text = "Sensul de transformare:"

220 + Environment.NewLine

222

Page 223: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

221 + "Fahrenheit ==> Celsius";

222 ajut.CutieMare( re f txtFormula);

223 txtFormula.Text = "Formula de calcul:"

224 + Environment.NewLine

225 + "C = 0.56 * (F - 32)";

226 foreach (TextBox cutie in sir){

227 cutie.Location = new Point(25, sus);

228 cutie.Width = 230;

229 cutie.Height = 40;

230 i f (cutie.Multil ine == true)

231 sus += ecartament;

232 e l se

233 sus += ( int )(0.6 * ecartament);

234 }

235 Controls .AddRange(sir);

236 }

237 }

238 // punctul de intrare:

239 c la s s Program{

240 s t a t i c void Main( str ing [] args ){

241 Application .

242 Run(new MainWindow("Convertor", 300, 450));

243 }

244 }

245 }

Surse bibliografice

[1] Albahari, J.;Albahari, B., C# in a nutshell. The definitive reference,

Fourth edition, O’Reilly, Beijing, 2010

[2] Archer, T.; Whitechapel, A., Visual C++.NET Bible, Wiley Publishing,

Inc., Indiana, 2002

[3] ASCII,

http://en.wikipedia.org/wiki/ASCII

[4] Fisiere batch,

http://en.wikipedia.org/wiki/Batch_file

[5] Boost,

http://www.boost.org/

223

Page 224: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

[6] Ben­Gan, I., Microsoft SQL Server 2008. T­SQL fundamentals, Mi­

crosoft Press, Redmond, 2009

[7] Microsoft C,

http://msdn.microsoft.com/en-us/library/02y9a5ye.aspx

[8] Linia de comanda ın C,

http://msdn.microsoft.com/en-us/library/b4b6wz4t.aspx

http://msdn.microsoft.com/en-us/library/a1y7w461.aspx

[9] Catrina, O.; Cojocaru, I., Turbo C++, Ed. Teora, Bucuresti, 1993

[10] Consola ın Windows,

http://msdn.microsoft.com/en-us/library/ms682087.aspx

[11] Convertoare on-line,

http://www.wbuf.noaa.gov/tempfc.htm

http://chemistry.about.com/library/weekly/

bltempconvert.htm

[12] CRT,

http://msdn.microsoft.com/en-us/library/634ca0c2.aspx

[13] Deaconu, A., Programarea ın limbajele C/C++ si aplicatii, Ed. Al­

bastra, Cluj­Napoca, 2007

[14] Fotache, M., SQL. Dialecte DB2, Oracle, PostgreSQL si SQL Server,

Editia a II­a revazuta si adaugita, Ed. Polirom, Bucuresti, 2009

[15] Goodrich, M.T.; Tamassia, R.; Mount, D., Data structures and algo­

rithms in C++. Second edition, J. Wiley & Sons, New York, 2011

[16] Hejlsberg, A.; Torgersen, M.; Wiltamuth, S.; Golde, P., The C# pro­

gramming language. Fourth edition, Addison­Wesley, Upper Saddle

River, NJ, 2011

[17] Hogenson, G., Foundations of C++/CLI. The Visual C++ language for

.NET 3.5, Apress, Berkeley, CA, 2008

[18] Jamsa, K.; Klander, L., Totul despre C si C++, Ed. Teora, Bucuresti,

2007

224

Page 225: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

[19] Keogh, J., Java fara mistere, Ed. Rosetti Educational, Bucuresti, 2004

[20] Kernighan, B.W.; Ritchie, D.M., The C programming language. Sec­

ond edition, Prentice Hall, Englewood Cliffs, NJ, 1988. Erata cartii se

gaseste la adresa:

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

[21] Kpathsea,

http://www.tug.org/svn/texlive/trunk/Build

/source/texk/kpathsea/

[22] Lippman, S.B., C++ primer. 2nd edition, reprinted with corrections,

Addison­Wesley, Reading, Mass., 1992

[23] Lippman, S.B., Essential C++, Addison­Wesley, Reading, Mass., 2000.

Erata cartii se gaseste la adresa:

http://ptgmedia.pearsoncmg.com/images/0201485184/errata

/errata.pdf

[24] Meyers, S., Effective STL. 50 specific ways to improve your use of the

standard template library, Fifth printing, Addison­Wesley, Boston,

2005

[25] MiKTEX,

http://www.miktex.org

[26] MSDN,

http://www.msdn.microsoft.com

[27] Mustafa, O.G., Note de TEX, DAL, 2009. On-line la adresa:

https://www.dropbox.com/s/n1mm0um79a14fme/knuth.pdf

[28] Mustafa, O.G., Curbe si suprafete, DAL, 2009. On-line la adresa:

https://www.dropbox.com/sh/gi3yyjt1rsq58vl/6R_nE49U9j

[29] Windows NT,

http://en.wikipedia.org/wiki/Windows_NT

[30] Qt,

http://qt.nokia.com/products/

225

Page 226: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

[31] Petzold, C., Programming Windows. Fifth edition, Microsoft Press,

Redmond, 1998

[32] Petzold, C., .NET Book Zero. What the C or C++ programmer needs

to know about C# and the .NET framework, 2007. On-line la adresa:

http://www.charlespetzold.com/dotnet/index.html

[33] POSIX,

http://en.wikipedia.org/wiki/POSIX

[34] Preda, M.C.; Mirea, A.M.; Preda, D.L.; Teodorescu­Mihai, C., Intro­

ducere ın programarea orientata­obiect. Concepte fundamentale din

perspectiva ingineriei software, Ed. Polirom, Bucuresti, 2010

[35] Richter, J.; Nasarre, C., Windows via C/C++, Microsoft Press, Red­

mond, 2008

[36] The Rule of Three,

http://drdobbs.com/cpp/184401400

http://www.artima.com/cppsource/bigtwo.html

http://www.artima.com/cppsource/bigtwo2.html

http://www.artima.com/cppsource/bigtwo3.html

[37] SEH,

http://msdn.microsoft.com/en-us/library/ms680657.aspx

[38] signal,

http://msdn.microsoft.com/en-us/library/xdkz3x12.aspx

[39] Standardul C++,

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011

/n3242.pdf

[40] Stroustrup, Bjarne,

http://en.wikipedia.org/wiki/Bjarne_Stroustrup

[41] Stroustrup, B., The C++ programming language. Special edition,

Addison­Wesley, New York, 1997. Seventh printing, 2003. Erata cartii

se gaseste la adresa:

http://www2.research.att.com/~bs/3rd_printing20.html

226

Page 227: Note de laborator: C++ - · PDF file13 #undef LA_REVEDERE 14 #define LA_REVEDERE \ 15 MessageBox(NULL, \ ... Un alt comentariu trebuie facut ˆın ˆıncheierea acestei sec¸tiuni.

[42] Stroustrup, B., Programming: principles and practice using C++, Third

printing, Addison­Wesley, Upper Saddle River, NJ, 2010

[43] TEXnicCenter,

http://www.texniccenter.org/

[44] Troelsen, A., Developer’s workshop to COM and ATL 3.0, Wordware

Publish., Inc., Plano, Texas, 2000

[45] Troelsen, A., Pro C# 2010 and the .NET 4 platform, Fifth edition,

Apress, New York, 2010

[46] TUG,

http://www.tug.org/

[47] TEX Live,

http://www.tug.org/texlive/

[48] Vandevoorde, D.; Josuttis, N.M., C++ templates. The complete guide,

Second printing, Addison­Wesley, Boston, 2003

[49] Visual C++ 2010 Express,

http://www.microsoft.com/visualstudio/en-us/products/

2010-editions/visual-cpp-express

[50] Windows SDK,

http://www.microsoft.com/download/en/

details.aspx?displaylang=en&id=8279

227