elemente de bază ale programării .net (continuare)mapetrii/fisiere/vc/curs3.pdf · generarea...

20
Programare Windows I – Visual C++ Curs 3 1 Elemente de bază ale programării .NET (continuare) Moştenirea în modul gestionat În modul gestionat moștenirea este asemănătoară modului negestionat. Declararea unei clase derivate: ref class clasaDeBaza{ //. . . }; ref class clasaDerivata:public clasaDeBaza{ //. . . }; Observaţie: Clasele gestionate pot moşteni doar clase gestionate. Construirea obiectelor derivate: clasaDerivata(lista argumente ):clasaDeBaza(lista argumente 1){ //. . . }; În constructorul clasei derivate se foloseşte o listă de iniţializare a membrilor pentru a apela constructorul clasei de bază. Observaţie: Pentru ca o clasă derivată să aibă acces la membrii unei clase de bază trebuie ca în clasa de bază aceştia să fie declaraţi public sau protected. Definirea în clasa de bază a funcţiilor ce trebuie suprascrise în clasele derivate se face prin declararea acestora de tip virtual. ref class clasaDeBaza{ . . . virtual tipReturnat numeFunctie(lista argumente); . . . }; Pentru ca o funcţie declarată în clasa de bază să fie obligatoriu suprascrisă în clasele derivate trebuie ca declarată pur virtuală (virtuală + se adaugă =0 la final):

Upload: others

Post on 16-Sep-2019

28 views

Category:

Documents


0 download

TRANSCRIPT

Programare Windows I – Visual C++ Curs 3

1

Elemente de bază ale programării .NET (continuare)

Moştenirea în modul gestionat

În modul gestionat moștenirea este asemănătoară modului negestionat. Declararea unei clase derivate: ref class clasaDeBaza{ //. . . }; ref class clasaDerivata:public clasaDeBaza{ //. . . }; Observaţie: Clasele gestionate pot moşteni doar clase gestionate. Construirea obiectelor derivate: clasaDerivata(lista argumente ):clasaDeBaza(lista argumente 1){

//. . . };

În constructorul clasei derivate se foloseşte o listă de iniţializare a membrilor pentru a apela constructorul clasei de bază. Observaţie: Pentru ca o clasă derivată să aibă acces la membrii unei clase de bază trebuie ca în clasa de bază aceştia să fie declaraţi public sau protected.

Definirea în clasa de bază a funcţiilor ce trebuie suprascrise în clasele derivate se face prin declararea acestora de tip virtual. ref class clasaDeBaza{ . . . virtual tipReturnat numeFunctie(lista argumente); . . . };

Pentru ca o funcţie declarată în clasa de bază să fie obligatoriu suprascrisă în clasele derivate trebuie ca declarată pur virtuală (virtuală + se adaugă =0 la final):

Programare Windows I – Visual C++ Curs 3

2

ref class clasaDeBaza{ . . . virtual tipReturnat numeFunctie(lista argumente)=0; . . .

}; Exemplu: ref class clasaDeBaza abstract{ int a; public: clasaDeBaza(int a){this->a=a;} virtual void scrie()=0; }; ref class clasaDerivata:public clasaDeBaza{ int b; public: clasaDerivata(int a,int b):clasaDeBaza(a){ this->b=b; } virtual void scrie() override{ Console::WriteLine("Clasa derivata"); } }; int main(array<System::String ^> ^args) { clasaDerivata cd(3,4); return 0; } Observaţie: Pentru clasele gestionate, la suprascriere folosim override.

O interfaţă este o clasă în care toate funcţiile sunt pur virtuale. Interfeţele sunt utile pentru a defini funcţionalitatea diferitelor clase. Prin convenţie, numele interfeţelor încep cu litera I, astfel difereţiindu-se mai uşor de clase. După ce a fost definită, o interfaţă se poate implementa în orice clasă care acceptă funcţionalitatea definită în interfaţă. Sintaxa pentru implementarea unei interfeţe este aceeaşi cu cea folosită pentru extinderea unei clase de bază. Pentru ca o clasă să nu poată fi moştenită, trebuie declarată folosind sealed: ref class clasaInchisa sealed{ // }; Observaţie: Codul de mai jos va genera o eroare. ref class clasaDerivata1:public clasaInchisa{//eroare };

Programare Windows I – Visual C++ Curs 3

3

Utilizarea clasei Math

Clasa Math pune la dispoziție constante și metode statice pentru lucrul cu expresii

matematice (trigonometrice, logaritmice etc.). Această clasă face parte din spațiul de nume System și este o clasă finală (nu poate fi moștenită).

Printre metodele clasei regăsim:

Nume Descriere

Abs(expresie) Întoarce valoarea absolută pentru argumentul primit ce poate fi de

tipul: Decimal, Double, Int16, Int32, Int64, IntSbyte, Single

Acos Corespunde funcției arccos.

Asin Corespunde funcției arcsin.

Atan Corespunde funcției arctg.

Atan2(val1,val2) Întoarce unghiul a cărui tangentă este egală cu raportul dintre val1 și

val2.

Cos Corespunde funcției cosinus.

Cosh Corespunde funcției cosinus hiperbolic.

Exp Corespunde funcției exponențiale cu baza e.

Floor Întoarce cel mai mare întreg mai mic sau egal cu argumentul primit,

care poate fi de tipul Decimal sau Double.

Log(Double) Corespunde funcției ln.

Log(Double, Double)

Corespunde funcției logaritm cu baza specificată.

Log10 Corespunde funcției lg (logaritm cu baza 10).

Max(val1,val2) Întoarce maximul dintre valorile primite, care pot fi de tipul: Byte,

Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64

Min(val1,val2) Întoarce minimul dintre valorile primite, care pot fi de tipul: Byte,

Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64

Pow(val1,val2) Corespunde funcției putere (val1-baza, val2-exponentul)

Round(expresie) Intoarce valoarea întreagă cea mai apropiată de expresie.

Programare Windows I – Visual C++ Curs 3

4

Expresie poate avea tipul: Decimal, Double.

Round(expresie,nr) Face rotunjirea pentru expresie la nr zecimale. Expresie poate avea

tipul: Decimal, Double.

Sign(expresie) Întoarce o valoare care indică semnul pentru expresie, ce poate fi de

tipul: Byte, Decimal, Double, Int16, Int32, Int64, SByte, Single

Sin Corespunde funcției sinus.

Sinh Corespunde funcției sinus hiperbolic.

Sqrt Corespunde funcției radical.

Tan Corespunde funcției tangentă.

Tanh Corespunde funcției tangentă hiperbolică.

Truncate(expresie) Calculează partea întreagă pentru expresie. Expresie poate avea tipul:

Decimal, Double.

Ca și constante de clasă avem:

Nume Descriere

E Constanta e.

PI Constanta π.

Exemplu: #include "stdafx.h" using namespace System; ref class Punct{ String^ nume; int x,y; public: Punct(String^ nume,int x,int y){ this->nume=nume; this->x=x; this->y=y; }

Programare Windows I – Visual C++ Curs 3

5

property int X{ int get(){ return x; } void set(int x){ this->x=x; } } property int Y{ int get(){ return y; } void set(int y){ this->y=y; } } property String^ Text{ String^ get(){ return nume; } void set(String^ nume){ this->nume=nume; } } double distanta(int x,int y){ return Math::Sqrt(Math::Pow(this->x-x,2)+Math::Pow(this->y-y,2)); } double distanta(Punct^ P){ return distanta(P->X,P->Y); } }; void main() { Punct P1("A",0,0); Punct^ P2=gcnew Punct("B",4,4); Punct^ P3=gcnew Punct("C",4,0); double a,b,c,perimetru,semiperimetru,arie,unghi; a=P1.distanta(P2); b=P2->distanta(P3); c=P1.distanta(P3); perimetru=a+b+c; Console::WriteLine("Perimetrul triunghiului {0}{1}{2} este: {3}",P1.Text,P2->Text,P3->Text,perimetru); semiperimetru=perimetru/2; arie=semiperimetru*(semiperimetru-a)*(semiperimetru-b)*(semiperimetru-c); arie=Math::Sqrt(arie); Console::WriteLine("Aria triunghiului {0}{1}{2} este: {3}",P1.Text,P2->Text,P3->Text,arie); Console::WriteLine("Raza cercului circumscris triunghiului {0}{1}{2} este: {3}",P1.Text,P2->Text,P3->Text,a*b*c/(4*arie));

Programare Windows I – Visual C++ Curs 3

6

Console::WriteLine("Raza cercului inscris triunghiului {0}{1}{2} este: {3}",P1.Text,P2->Text,P3->Text,arie/semiperimetru); unghi=Math::Atan2(P2->Y-P1.Y,P2->X-P1.X); unghi-=Math::Atan2(P3->Y-P1.Y,P3->X-P1.X); Console::WriteLine("Unghiul {0} are {1} grade.",P1.Text,unghi/Math::PI*180);//unghi orientat Console::WriteLine("sin({0})={1}",P1.Text,Math::Sin(unghi)); } Perimetrul triunghiului ABC este: 13,6568542494924 Aria triunghiului ABC este: 8 Raza cercului circumscris triunghiului ABC este: 2,82842712474619 Raza cercului inscris triunghiului ABC este: 1,17157287525381 Unghiul A are 45 grade. sin(A)=0,707106781186547 Press any key to continue . . . Generarea numerelor aleatoare

Pentru generarea numerelor aleatoare se va folosi clasa Random din spațiul de

nume System. Un reprezentant al clasei Random reprezintă un generator de numere pseudo-aleatoare, care produce o secvenţă de numere care îndeplinesc anumite cerinţe statistice. Generarea numerelor nu este complet aleatorie deoarece ele sunt rezultatul unui algoritm matematic ce are la bază o valoare de start. Pentru aceeași valoare de start se vor obține aceleași serii de valori. O metodă de a obține serii diferite de valori generate este aceea de a considera valoarea de start dependentă de timp.

Observație: Este de preferat crearea unei singure instanțe a clasei Random pentru

generarea mai multor numere în detrimentul generării numerelor cu mai multe instanțe ale clasei.

Constructorii clasei sunt Random() - algoritmul de generare are valoarea de start dependentă de timp. Random(Int32) - algoritmul de generare are valoarea de start dependentă de

valoarea primită ca argument.

Metode ale clasei Nume Descriere

Next() Întoarce un număr aleatoriu nenegativ

Next(Int32) Întoarce un număr aleatoriu nenegativ mai mic decât valoarea specificată.

Programare Windows I – Visual C++ Curs 3

7

Next(Int32, Int32) Întoarce un număr aleatoriu din intervalul specificat.

NextDouble Întoarce un număr aleatoriu cuprins între 0.0 și 1.0.

Exemplu: int x,y; Random^ r=gcnew Random(); Console::WriteLine("Un numar intreg: {0}",r->Next()); x=20; y=50; Console::WriteLine("Un numar intreg din intervalul {0}..{1}: {2}",x,y,r->Next(20,50)); Console::WriteLine("Un numar de tip double din intervalul (0,1): {0}",r->NextDouble()); Console::WriteLine("Un numar de tip double din intervalul ({0},{1}): {2}",x,y,x+r->NextDouble()*(y-x));

În exemplul următor vom utiliza generatorul de numere aleatoare pentru a determina valoarea aproximativă a numărului PI. Pentru aceasta ne vom folosi de faptul că daca avem un patrat de latura 2 și un cerc înscris în acesta, probabilitatea ca un punct al pătratului să fie în interiorul cercului este PI/4 (aria cercului/aria pătratului). Exemplu:

#include "stdafx.h" using namespace System; double valoare_aproximativa_PI(int N){//nr de incercari if(N<=0)return 0; int inInterior=0; double x,y; Random^ r=gcnew Random(); for(int i=0;i<N;i++){ x=-1+r->NextDouble()*2; y=-1+r->NextDouble()*2; if(Math::Sqrt(x*x+y*y)<=1)inInterior++; } return 4.0*inInterior/N; } void main() { for(int i=1;i<=8;i++) Console::WriteLine("Pentru {0} incercari, valoarea aproximativa a numarului PI este {1}",Math::Pow(10,i),valoare_aproximativa_PI(Math::Pow(10,i))); }

Programare Windows I – Visual C++ Curs 3

8

Pentru 10 incercari, valoarea aproximativa a numarului PI este 3,6 Pentru 100 incercari, valoarea aproximativa a numarului PI este 3,04 Pentru 1000 incercari, valoarea aproximativa a numarului PI este 3,188 Pentru 10000 incercari, valoarea aproximativa a numarului PI este 3,1596 Pentru 100000 incercari, valoarea aproximativa a numarului PI este 3,14148 Pentru 1000000 incercari, valoarea aproximativa a numarului PI este 3,14152 Pentru 10000000 incercari, valoarea aproximativa a numarului PI este 3,142048 Pentru 100000000 incercari, valoarea aproximativa a numarului PI este 3,14151328 Press any key to continue . . . Conversia între tipuri de date

Conversia între diverse tipuri de date se poate face în mai multe moduri, funcție de tipurile date. Pentru tipurile native conversia se poate face automat, ca în exemplul de mai jos

int i=123.45;//conversie automata /* va genera avertisment de tipul warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data*/ i=(int)67.89; //operatorul cast face conversia fără a mai genera avertisment double d=3/2;//conversie automata (d=1)

bool b=0;//conversie automata (b=false) Același lucru nu se întâmplă în cazul altor tipuri (la care operatorul "=" nu este

suprascris). Exemplu:

ref class Animal{ public: virtual void scrie(){ Console::WriteLine("Sunt din clasa Animal"); } }; ref class Pisica:public Animal{ String^ nume; public: Pisica(String^ nume){ this->nume=nume; } virtual void scrie()override{ Console::WriteLine("Sunt din clasa Pisica si ma cheama {0}.",nume); } };

Programare Windows I – Visual C++ Curs 3

9

ref class Pasare:public Animal{ String^ nume; public: Pasare(String^ nume){ this->nume=nume; } virtual void scrie()override{ Console::WriteLine("Sunt din clasa Pasare si ma cheama {0}.",nume); } }; . . . Animal animal; Pisica cat("Tom"); animal=cat;//eroare 'operator =' function is unavailable in 'Animal'

Pentru conversii se poate folosi și clasa Convert, din spațiul de nume System. Aceasta pune la dispoziție o serie de metode al căror nume este de tipul "Convert::To...". Este utilă mai ales atunci când se dorește convertirea unui text (String) la o valoare numerică.

Exemplu:

int i double d; bool b; String^ text="16.5"; i=Convert::ToInt32(text);//eroare i=Convert::ToInt32("123");//corect d=Convert::ToDouble(text);//corect b=Convert::ToBoolean(text);//eroare b=Convert::ToBoolean("true");//corect Dacă erorile nu sunt captate, se va afișa un mesaj de tipul:

Programare Windows I – Visual C++ Curs 3

10

Dacă trebuie să facem conversii între date de tip pointer (gestionat sau nativ) se

poate folosi operatorul dynamic_cast< >. Acesta poate fi utilizat și pentru determinarea tipului unui pointer.

Exemplu:

Animal^ animal= gcnew Animal; Pisica^ pisica=gcnew Pisica("Sylvester"); Pasare^ pasare=gcnew Pasare("Twetty"); animal=pasare;//corect, clasa Pasare mosteneste clasa Animal pisica=(Pisica^)pasare;//eroare, intre clasele Pisica si Pasare nu exista legatura

pisica=dynamic_cast<Pisica^>(pasare);//corect, daca nu se poate face conversia pisica devine nullptr

În funcția de mai jos folosim operatorul dynamic_cast pentru stabilirea tipului

argumentului. Exemplu:

int da_numar_picioare(Animal^ animal){ Pisica^ p1=dynamic_cast<Pisica^>(animal);//aici testam tipul if(p1!=nullptr)return 4;//argumentului (determinam daca este de un tip anume) Pasare^ p2=dynamic_cast<Pasare^>(animal); if(p2!=nullptr)return 2; return -1; }

Folosirea colecțiilor de elemente

Pentru folosirea colecțiilor de elemente se pot utiliza tablourile unidimensionale sau multidimensionale precum și clase special create pentru manipularea colecțiilor de elemente. Aceste clase se găsesc în spațiile de nume System::Collections sau System::Collections::Generic.

Important: Tablourile native se pot utiliza doar pentru tipurile native. Exemplu:

int a[10],t[10]={0}; Punct puncte[10];//error C2728: 'Punct' : a native array cannot

contain this managed type

Programare Windows I – Visual C++ Curs 3

11

Pentru tipuri gestionate, pentru tablouri cu dimensiune fixă putem folosi tipul array.

Sintaxa: array<[tip1[, dimensiune]>^ var = gcnew array<tip1[,dimensiune]>(val1[,val2...])

Exemplu:

#define NR_RANDURI 3 #define NR_COLOANE 2 int a[10];//tablou unidimensional cu 10 elemente for(int i=0;i<10;i++) a[i]=i; double b[3][5];//tablou cu 2 dimensiuni (3 linii, 5 coloane) for(int i=0;i<3;i++) for(int j=0;j<5;j++) b[i][j]=i; //tablou unidimensional - tip gestionat array<Punct^>^ linie = gcnew array<Punct^>(NR_COLOANE); for(int i=0;i<NR_COLOANE;i++) linie[i]=gcnew Punct(i,2*i); //tablou cu 2 dimensiuni- tip gestionat array<Punct^,2 >^ matrice = gcnew array<Punct^,2>(NR_RANDURI,NR_COLOANE); for(int i=0;i<NR_RANDURI;i++) for(int j=0;j<NR_COLOANE;j++) matrice[i,j]=gcnew Punct(i,j); linie[2]=gcnew Punct(3,2);//eroare, exceptie de tip 'System.IndexOutOfRangeException' Array::Resize(linie,linie->Length+1);//linie are acum dimensiunea mai mare cu o unitate

linie[2]=gcnew Punct(3,2);//corect În exemplul de mai sus am folosit proprietatea Length pentru a citi dimensiunea

tabloului și metoda Resize pentru a modifica dimensiunea acestuia. Elementele unui tablou pot fi și de tip negestionat, ca în exemplul următor: Exemplu:

class A{//clasa nativa int x; public: A(int x){ this->x=x; } };

. . .

Programare Windows I – Visual C++ Curs 3

12

array<A*>^ lista=gcnew array<A*>(5); for(int i=0;i<5;i++) lista[i]=new A(i);

Pentru lucrul cu tablouri "dinamice" (dimensiune variabilă) putem folosi clasa

List<T> din spațiul de nume System::Collections::Generic. Elementele listei pot fi accesate prin index. Clasa pune la dispoziție metode pentru căutare, sortare și manipulare a listelor.

Un constructor al clasei este List<T>()

care crează o nouă instanță a clasei (o listă goală). Numărul total de elemente ce poate fi reținut fără redimensionare poate fi

controlat prin intermediul proprietății Capacity. Nu este obligatorie redimensionarea, aceasta făcându-se automat. Proprietatea Count permite citirea numărului de elemente din listă iar proprietatea Index permite accesul la elementul de pe poziția specificată.

Printre metodele clasei regăsim:

Nume Descriere

Add Adaugă un obiect la sfârșitul listei.

AddRange Adaugă o colecție de obiecte la sfârșitul listei.

Clear Elimină toate elementele listei.

IndexOf(T) Intoarce indexul elementului specificat (dacă acesta există în listă).

Insert Adaugă un element cu indexul specificat.

Remove Elimină din listă primul element care coincide cu cel specificat

RemoveAt Elimină elementul de pe poziția specificată.

Reverse() Așează elementele listei în ordine inversă .

Reverse(Int32, Int32) Schimbă ordinea elementelor din intervalul specificat.

Sort(Comparison<T>) Sortează elementele listei folosind s the elements in the entire

List<T> using the specified System::Comparison<T>.

ToArray Copie elementele listei într-un tablou.

Observație: Elementele unei liste pot fi de tipul nullptr și se accepta duplicate.

Programare Windows I – Visual C++ Curs 3

13

Pentru parcurgerea elementelor unei liste se poate folosi o formă specială a instrucțiunii for și anume for each ( a se vedea în exemplul de mai jos motoda diferenta din clasa Multime ).

Exemplu:

#include "stdafx.h" using namespace System; using namespace System::Collections::Generic;//adaugat pentru a lucra cu liste ref class Punct{ . . . ;//a fost definita anterior }; ref class Multime{ String^ nume; List<Punct^>^ elemente; public: Multime(String^ nume){ this->nume=nume; this->elemente=gcnew List<Punct^>();//lista goala cu elemente de tip Punct } property String^ Nume{ String^ get(){ return nume; } void set(String^ nume){ this->nume=nume; } } property int NrElemente{ int get(){ return elemente->Count;//numarul de elemente din lista } } property List<Punct^>^ Elemente{ List<Punct^>^ get(){ return elemente; } void set(List<Punct^>^ elemente){ this->elemente=elemente; } } void adauga(Punct^ P){ elemente->Add(P);//adaugam un element la final }

Programare Windows I – Visual C++ Curs 3

14

void adauga(Punct^ P,int index){ try{ elemente->Insert(index,P);//adaugam un element cu indexul index } catch(Exception^){ elemente->Add(P); } } void scrie(){ String^ text=nume+"={"; if(NrElemente>0){ text+=elemente[0]->Text; for(int i=1;i<NrElemente;i++) text+=","+elemente[i]->Text; } text+="}"; Console::WriteLine(text); } void inverseazaElemente(){ elemente->Reverse(); } static Multime^ reuniune(Multime^M1,Multime^M2){ Multime^ M=gcnew Multime(M1->Nume+"U"+M2->Nume); M->Elemente->AddRange(M1->Elemente); //daca am fi pus in locul instructiunii de mai sus //M->Elemente=M1->Elemente; //instructiunea urmatoare ar fi adaugat elementele si listei multimii M1 M->Elemente->AddRange(M2->Elemente); return M; } static Multime^ diferenta(Multime^M1,Multime^M2){ Multime^ M=gcnew Multime(M1->Nume+"/"+M2->Nume); M->Elemente->AddRange(M1->Elemente); for each(Punct^ P in M2->Elemente) M->Elemente->Remove(P); return M; } bool contine(Punct^ P){ return elemente->IndexOf(P)>=0; } void elimina_duplicate(){ for(int i=0;i<elemente->Count;i++) for(int j=i+1;j<elemente->Count;j++) if(elemente[j]==elemente[i]){ elemente->RemoveAt(j); j--; } } static int ascendent_dupa_X(Punct^ P1,Punct^ P2){ return P1->X-P2->X; } static int descendent_dupa_X(Punct^ P1,Punct^ P2){ return -ascendent_dupa_X(P1,P2); }

Programare Windows I – Visual C++ Curs 3

15

static int ascendent_dupa_nume(Punct^ P1,Punct^ P2){ return String::Compare(P1->Text,P2->Text); } /*Pentru a folosi meroda Sort este important ca functia sa fie statica*/ void sorteaza(int tip){ switch(tip){ case 1://crescator dupa X elemente->Sort(gcnew Comparison<Punct^>(ascendent_dupa_X)); break; case 2://descrescator dupa X elemente->Sort(gcnew Comparison<Punct^>(descendent_dupa_X)); break; case 3://crescator dupa nume elemente->Sort(gcnew Comparison<Punct^>(ascendent_dupa_nume)); break; } } }; void main() { Multime^ A=gcnew Multime("A"); Multime^ B=gcnew Multime("B"); Multime^ C; Punct ^a,^b,^c,^d,^e,^f,^g,^h,^i,^j; a=gcnew Punct("a",4,0); b=gcnew Punct("b",2,3); c=gcnew Punct("c",5,0); d=gcnew Punct("d",6,9); e=gcnew Punct("e",1,3); f=gcnew Punct("f",4,9); g=gcnew Punct("g",2,1); h=gcnew Punct("h",7,6); i=gcnew Punct("i",1,3); j=gcnew Punct("j",9,2); Console::WriteLine(A->Elemente->Capacity);//citim valoarea pentru Capacity (initial este 0) A->adauga(a); Console::WriteLine(A->Elemente->Capacity);//citim valoarea pentru Capacity (valoarea a crescut automat cand s-a adaugat elementul) A->adauga(b,3); A->adauga(c,0); A->adauga(h); A->adauga(d); A->adauga(a); B->adauga(a); B->adauga(e); B->adauga(f);

Programare Windows I – Visual C++ Curs 3

16

B->adauga(b); B->adauga(h); B->adauga(i); B->adauga(j); A->scrie(); B->scrie(); C=Multime::reuniune(A,B); C->scrie(); C=Multime::diferenta(A,B); C->scrie(); C->elimina_duplicate(); C->scrie(); Console::WriteLine(A->contine(j)); A->scrie(); A->sorteaza(1); A->scrie(); A->sorteaza(2); A->scrie(); A->sorteaza(3); A->scrie(); }

Observație: Pentru lucrul cu liste de elemente cu tipuri diferite (nu au un tip de bază comun) se poate folosi clasa ArrayList din spațiul de nume System::Collection. Elementele acestei clase se utilizează în mod asemănător.

Lucrul cu șiruri de caractere

Pentru lucrul cu șiruri de caractre vom folosi clasa String din spațiul de nume System. Ca și constructori putem folosi:

String(Char*) - crează o instanță a clasei String pe baza unui pointer către un tablou ce conține caractere Unicode

String(array<Char>) - crează o instanță a clasei String pe baza unui tablou ce conține caractere Unicode

Odată create, instanțele clasei String pun la dispoziție proprietatea Length pentru citirea lungimii șirului de caractere și operatorul [...] pentru citirea codului elementului de pe o poziție specificată. Pentru concatenarea șirurilor de caractere se poate folosi operatorul "+" sau metoda Concat. O copie (clonă) a unei instanțe din clasa String se poate obține folosind metoda Clone.

Exemplu: String^ s="abcdefghij"; char c1[10]={'a','b','c','d','e'};

Programare Windows I – Visual C++ Curs 3

17

char* c2="fghij"; wchar_t c3[10]={'1','2','3',300}; String^ s1=gcnew String(c1); String^ s2=gcnew String(c2); String^ s3=gcnew String(c3); int nr=0; for(int i=0;i<s->Length;i++) nr+=s[i]; Console::WriteLine("Suma codurilor caracterelor sirului {0} este {1}",s,nr); Console::WriteLine(s1+s2);//s1+s2 este echivalent cu String::Concat(s1,s2) Metode ale clasei String:

metoda Compare - folosită pentru compararea a două șiruri de caractere (are la bază ordinea lexicografică)

Exemplu: String^ s1="123"; String^ s2="121"; String::Compare(s1,s2);//1 String::Compare("a","ab");//-1 String::Compare("ab","ab");//0 String::Compare("abc","ab");//1 String::Compare("Ab","ab");//1 String::Compare("Ab","ab",true);//0-true, pentru a nu mai fi case sensitive

metodele EndsWith și StartsWith - folosite pentru a testa dacă un șir de caractere se termina sau începe cu o valoare data (pentru comparare se poate folosi enumerarea StringComparison)

Exemplu: String^ s1="123"; String^ s2="abcd"; s1->EndsWith("23");//true s2->StartsWith(s1);//false s2->EndsWith("acd");//false s2->EndsWith("cd");//true s2->EndsWith("Cd");//false s2->EndsWith("Cd",System::StringComparison::OrdinalIgnoreCase);//true

metoda Equals - folosită pentru a testa dacă avem egalitate între două șiruri de caractere (pentru comparare se poate folosi enumerarea StringComparison)

Programare Windows I – Visual C++ Curs 3

18

Exemplu: String^ s1="ABC"; String^ s2="abcd"; s2->Equals(s1);//false String::Equals(s1+"D",s2);//false String::Equals(s1+"D",s2,System::StringComparison::OrdinalIgnoreCase); //true

metoda IndexOf - folosită pentru a determina într-un șir de caractere indexul primei apariții a valorii specificate (pentru comparare se poate folosi enumerarea StringComparison)

Exemplu: String^ s1="ABCA"; String^ s2="abcd"; s1->IndexOf('B');//1 s2->IndexOf("cd");//2 s1->IndexOf("E");//-1 s2->IndexOf("Cd");//-1 s2->IndexOf("Cd",System::StringComparison::OrdinalIgnoreCase);//2

metoda LastIndexOf - se folosește la fel ca metoda IndexOf doar că dă indexul ultimei apariții a valorii specificate (pentru comparare se poate folosi enumerarea StringComparison)

Exemplu: String^ s1="ABCA"; s1->LastIndexOf('A');//3

metoda Insert - se folosește pentru a insera într-un șir valoarea specificată, în poziția specificată

Exemplu: String^ s1="ABCA"; String^ s2="abcd"; s1->Insert(2,s2);//"ABabcdCA" s1->Insert(10,"123");//eroare, nu există pozitia cu indexul 10

metoda Remove - se folosește pentru a elimina caractere dintr-un șir de caractere Exemplu: String^ s1="ABCD"; s1->Remove(1);//"A"- elimină tot de la poziția dată s1->Remove(1,2);//"AD"- elimină numărul specificat de caractere, începând cu poziția dată

Programare Windows I – Visual C++ Curs 3

19

metoda Replace - înlocuiește textul căutat (dacă este găsit) cu cel specificat

Exemplu: String^ s1="ABCA"; String^ s2="abcd"; s1->Replace('A','5');//"5BC5" s1->Replace('a','5');//"ABCA" s1->Replace("BC","123");//"A123A" s1->Replace("Bc","123");//"ABCA"

metoda Split - crează un tablou de șiruri de caractere pe baza separatorului dat

Exemplu: String^ s1="A/B/CD"; array<String^>^ s2=s1->Split('/'); s2[0];//"A" s2[1];//"B" s2[2];//"CD"

metoda Substring - returnează un subșir al șirului dat

Exemplu: String^ s1="ABCD"; s1->Substring(1);//"BCD"- întoarce tot, începând cu poziția dată s1->Substring(1,2);//"BC"- întoarce numărul specificat de caractere, începând cu poziția dată

metodele ToLower respectiv ToUpper pot fi folosite pentru a scrie un șir folosind caractere "mari" sau " mici".

Exemplu: String^ s1="AbCd"; s1->ToLower();//"abcd" s1->ToUpper();//"ABCD"

pentru eliminarea spațiilor dintr-un șir de caractere se pot utiliza metodele Trim, TrimEnd sau TrimStart .

Exemplu: s1=" AB CD E "; Console::WriteLine("|"+s1+"|"); Console::WriteLine("|"+s1->TrimStart()+"|"); Console::WriteLine("|"+s1->Trim()+"|"); Console::WriteLine("|"+s1->TrimEnd()+"|");

Programare Windows I – Visual C++ Curs 3

20

| AB CD E | |AB CD E | |AB CD E| | AB CD E| Press any key to continue . . .

Observații: 1) Pentru a testa dacă un șir este Null sau gol(empty) se pot folosi metodele

IsNullOrEmpty și IsNullOrWhiteSpace 2) Este permisă utilizarea operatorilor == sau !=

Exemplu: "abc"=="Abc";//false "abc"!="Abc";//true