Clasa sablon string



Clasa sablon string

Clasa string se bazeaza pe definirea unui sablon:

template<class charT, class traits = char_traits<charT>,

class Allocator = allocator<charT> >

class basic_string {...};

Aici charT reprezinta tipul stocat in sir. Parametrul traits reprezinta o clasa care defineste proprietatile necesare pentru ca un tip sa poata fi reprezentat ca sir. De exemplu, ar trebui sa posede o metoda length() care sa returneze lungimea unui sir reprezentat ca un tablou de tip charT. Sfarsitul unui astfel de tablou este indicat de valoarea charT(0), care este generalizarea caracterului nul. (Expresia charT(0) este o conversie de tip a lui 0 la tipul charT. Poate fi chiar un 0, ca pentru tipul char, sau mai general, este un obiect creat de un constructor charT.) Clasa mai include metode de comparare a valorilor, si asa mai departe. Parametrul Allocator reprezinta o clasa care gestioneaza memoria ce se aloca sirului. Sablonul prestabilit allocator<charT> utilizeaza new si delete in maniera obisnuita.



Exista doua specializari predefinite:

typedef basic_string<char> string; 39246xlh35tqu5h

typedef basic_string<wchar_t> wstring;

Aceste specializari utilizeaza, la randul lor urmatoarele specializari:

char_traits<char>

allocator<char>

char_traits<wchar_t> lq246x9335tqqu

allocator<wchar_t>

Puteti crea o clasa string si pentru alt tip, nu numai pentru char sau wchar_t, definind o clasa traits si utilizand sablonul basic_string.

Treisprezece tipuri si o constanta

Sablonul basic_string defineste cateva tipuri care vor fi folosite ulterior in definitiile metodelor:

typedef traits traits_type;

typedef typename traits::char_type value_type;

typedef Allocator allocator_type;

typedef typename Allocator::size_type size_type;

typedef typename Allocator::difference_type difference_type;

typedef typename Allocator::reference reference;

typedef typename Allocator::const_reference const_reference;

typedef typename Allocator::pointer pointer;

typedef typename Allocator::const_pointer const_pointer;

Observati ca traits este un parametru sablon care va corespunde unui tip specific, cum ar fi char_traits<char>; traits_type va deveni un typedef pentru acel tip specific. Notatia

typedef typename traits::char_type value_type;

inseamna ca char_type este un nume tip definit in clasa reprezentata de traits. Cuvantul cheie typename este folosit pentru a-i spune compilatorului ca expresia traits::char_type este un tip. Pentru specializarea sirului, de exemplu, value_type va fi char.

size_type este folosit ca si size_of, numai ca returneaza dimensiunea sirului in termenii tipului stocat. Pentru specializarea sirului, va fi in char, deci in acest caz size_type este acelasi lucru cu size_of. Este un tip fara semn.

difference_type este utilizat pentru a masura distanta dintre doua elemente ale sirului, din nou folosind unitati corespunzand marimii unui singur element. In mod normal, este un tip cu semn derivat din tipul care sta la baza lui size_type.

Pentru specializarea char, pointer va fi de tip char *, iar reference va fi de tip char &. Totusi, daca creati o specializare pentru un tip definit de dumneavoastra, atunci aceste tipuri (pointer si reference) pot sa se refere la clase care au aceleasi proprietati de baza ca si pointerii si referintele normale.

Pentru ca algoritmii STL sa functioneze cu siruri, sablonul defineste si cateva tipuri de iteratori:

typedef (modeleaza un iterator cu acces aleator) iterator;

typedef (modeleaza un iterator cu acces aleator) const_iterator;

typedef std::reverse_iterator<iterator> reverse_iterator;

typedef reverse_iterator<const_iterator> const_reverse_iterator;

Sablonul mai defineste o constanta statica:

static const size_type npos = -1;

Deoarece size_type este fara semn, atribuirea unei valori -1 duce de fapt la atribuirea celei mai mari valori fara semn lui npos. Aceasta este cu 1 mai mare decat indexul maxim posibil al unui tablou.

Datele, constructorii si celelalte

Constructorii pot fi descrisi in functie de efectele pe care le au. Deoarece sectiunile private ale unei clase pot fi dependente de implementare, aceste efecte trebuie sa fie descrise in functie de informatiile disponibile ca parti ale interfetei publice. Tabelul F.1 prezinta cateva metode ale caror valori returnate pot fi folosite pentru a descrie efectele constructorilor si ale altor metode. Observati ca o mare parte din terminologie deriva din STL.

Tabelul F.1 Unele metode string legate de date.

Metoda Returneaza

begin() Un iterator la primul caracter din sir (este disponibil si in versiune const,

care returneaza un iterator const).

end() Un iterator care este valoarea dincolo-de-sfarsit (disponibil si in versiune

const).

rbegin() Un iterator invers care este valoarea dincolo-de-sfarsit (disponibil si in versiune const).

rend() Un iterator invers care indica primul caracter (disponibil si in versiune

const).

size() Numarul elementelor din sir, egal cu distanta dintre begin() si end().

length() La fel cu size().

capacity() Numarul de elemente alocate in sir.

max_size() Dimensiunea maxima permisa pentru sir.

data() Un pointer de tip const charT* la primul element al unui tablou ale carui

prime size() elemente sunt egale cu elementele corespunzatoare ale sirului

controlat de *this. Pointerul nu este obligatoriu valid, daca obiectul sir a fost

el insusi modificat.

c_str() Un pointer de tip const charT* la primul element al unui tablou ale carui

prime size() elemente sunt egale cu elementele corespunzatoare ale sirului

controlat de *this si al carui element urmator este caracterul charT(0)

(marcajul de sfarsit de sir al tipului charT). Pointerul nu este obligatoriu

valid, daca obiectul sir a fost el insusi modificat.

get_allocator()O copie a obiectului alocator utilizat pentru alocarea memoriei necesare

sirului.

Fiti atent la diferentele existente intre begin(), rend(), data() si c_str(). Toate sunt legate de primul caracter din sir, dar in moduri diferite. Astfel, metodele begin() si rend() returneaza iteratori, care sunt generalizari ale pointerilor, asa cum am vazut in discutia despre STL din Capitolul 15. In particular, begin() returneaza un model de iterator de inaintare, iar rend() o copie a unui iterator invers. Amandoi se refera la sirul gestionat de obiectul string. (Deoarece clasa string foloseste alocarea dinamica a memoriei, continutul efectiv al sirului nu se afla in interiorul obiectului, deci vom folosi termenul gestiune pentru a descrie relatia dintre obiect si sir.) Puteti folosi metodele care returneaza iteratori cu algoritmii bazati pe iteratori ai STL. De exemplu, puteti folosi functia STL transform() pentru a transforma elementele unui sir in litere mari:

string cuvant;

cin >> cuvant;

transform(cuvant.begin(), cuvant.end(), toupper);

Pe de alta parte, metodele data() si c_str() returneaza pointeri normali. In plus, acesti pointeri indica primul element al unui tablou care pastreaza caracterele sirului. Acest tablou, poate fi, dar nu neaparat, o copie a sirului original gestionat de obiectul string. (Reprezentarea interna utilizata de obiectul string poate fi un tablou, dar nu neaparat.) Deoarece pointerii returnati ar putea indica chiar datele originale, sunt const, deci nu pot fi folositi pentru modificarea datelor. De asemenea, pointerii nu sunt neaparat valizi dupa modificarea sirului; acest lucru reflecta din nou faptul ca pointerii ar putea indica datele originale. Diferenta dintre data() si c_str() este ca tabloul indicat de c_str() se termina cu caracterul nul (sau echivalentul sau), in timp ce data() contine numai caracterele continute efectiv de sir. Prin urmare, metoda c_str() poate fi utilizata, de exemplu, ca argument al unei functii care cere un sir in stil C:

string fisier(“tofu.man”);

ofstream outFile(fisier.c_str());

Analog, data() si size() pot fi folosite in functii care primesc ca argumente un pointer la un element al unui tablou si o valoare care reprezinta numarul de elemente de procesat:

string vampir(“Oh, dragul meu, nu infige tarusul!”);

int vlad = byte_check(vampir.data(), vampir.size());

O anumita implementare poate reprezenta sirul unui obiect string ca un sir in stil C alocat dinamic si sa implementeze iteratorul de inaintare ca pointer char *. In acest caz, implementarea poate alege ca begin(), data() si c_str() sa returneze acelasi pointer. Dar la fel de legitim (daca nu la fel de usor), pot returna referinte la trei obiecte diferite.

Tabelul F.2 listeaza cei sase constructori si destructorul clasei sablon basic_string. Observati ca toti constructorii au un argument de forma:

const Allocator & a = Allocator()

Va reamintiti ca termenul Allocator este numele parametrului sablon pentru clasa alocatoare care gestioneaza memoria. Termenul Allocator() reprezinta constructorul prestabilit al acelei clase. Prin urmare, constructorii folosesc versiunea prestabilita a obiectului alocator, dar va ofera optiunea de a folosi orice alta versiune a acestuia. Sa examinam constructorii pe rand.

Tabelul F.2 Constructori string.

Prototipuri pentru constructori si destructor

explicit basic_string(const Allocator& a = Allocator());

basic_string(const charT* s, const Allocator& a = Allocator());

basic_string(const basic_string& str, size_type pos = 0,

size_type n = npos, const Allocator& a = Allocator());

basic_string(const charT* s, size_type n,

const Allocator& a = Allocator());

basic_string(size_type n, charT c,

const Allocator& a = Allocator());

template<class InputIterator>

basic_string(InputIterator begin, InputIterator end,

const Allocator& a = Allocator());

~basic_string();

Constructorul prestabilit

Acesta este constructorul prestabilit:

explicit basic_string(const Allocator& a = Allocator());

In mod normal, veti folosi argumentul prestabilit si veti utiliza acest constructor pentru a crea siruri vide:

string boaba;

wstring teorie;

Urmatoarele relatii se pastreaza dupa apelul constructorului:

  • Metoda data() returneaza un pointer diferit de cel nul la care se poate aduna 0.

  • Metoda size() returneaza 0.

  • Valoarea returnata de capacity() nu este specificata.

Sa presupunem ca atribuiti valoarea returnata de data() pointerului sir. Atunci, prima conditie spune ca sir + 0 este valid, de unde rezulta ca expresia sir[0] este valida.

Constructor care foloseste un tablou

Urmatorul constructor va permite sa initializati un obiect string cu un sir in stil C; sau mai general, va permite sa initializati o specializare charT dintr-un tablou de valori charT:

basic_string(const charT* s, const Allocator& a = Allocator());

Pentru a determina cate caractere se copiaza, constructorul aplica metoda traits::length() la tabloul indicat de pointerul s. (Pointerul s nu poate fi pointerul nul.) De exemplu, instructiunea

string toast(“In sanatatea ta, baiete.”);

initializeaza obiectul toast utilizand sirul de caractere indicat. In cazul tipului char metoda traits::length() va folosi caracterul nul pentru a determina cate caractere se copiaza. Urmatoarele relatii se pastreaza dupa apelul constructorului:

  • Metoda data() returneaza un pointer la primul element al unei copii a tabloului s.

  • Metoda size() returneaza o valoare egala cu traits::length().

  • Metoda capacity() returneaza o valoare cel putin egala cu size().

Constructor care foloseste o parte dintr-un tablou

Urmatorul constructor va permite sa initializati un obiect string cu o portiune a unui sir in stil C; sau, mai general, va permite sa initializati o specializare charT dintr-o portiune a unui tablou de valori charT:

basic_string(const charT* s, size_type n,

const Allocator& a = Allocator());

Acest constructor copiaza un total de n caractere din tabloul indicat de s in obiectul construit. Copierea nu se opreste daca s are mai putin de n caractere. Daca n este mai mare decat lungimea lui s, atunci constructorul va interpreta continutul memoriei de dupa sir ca si cand ar contine valori de tip charT.

Constructorul cere ca s sa nu fie pointer nul iar n < npos. (Amintiti-va ca npos este o constanta statica a clasei egala cu numarul maxim posibil de elemente dintr-un sir.) Daca n este egal cu npos, constructorul arunca o exceptie out_of_range. (Deoarece n este de tip size_type iar npos este valoarea maxima size_type, n nu poate fi mai mare decat npos.)

In rest, dupa apelul constructorului, se pastreaza urmatoarele relatii:

  • Metoda data() returneaza un pointer la primul element al unei copii a tabloului s.

  • Metoda size() returneaza n.

  • Metoda capacity() returneaza o valoare cel putin la fel de mare ca si size().

Constructorul de copiere

Constructorul de copiere furnizeaza cateva argumente cu valori prestabilite:

basic_string(const basic_string& str, size_type pos = 0,

size_type n = npos, const Allocator& a = Allocator());

Apelul doar cu un argument basic_string initializeaza noul obiect cu sirul argument:

string mel(“Sunt bine!”);

string ida(mel);

Aici ida primeste o copie a sirului gestionat de mel.

Argumentul optional pos specifica locatia in sirul sursa din care incepe copierea:

string tel(“Da telefon acasa.”);

string el(tel, 3);

Numerotarea incepe cu 0, deci pozitia 3 este caracterul t. Prin urmare, el este initializat cu “telefon acasa.”.

Urmatorul argument optional n specifica numarul maxim de caractere care se copiaza. Prin urmare,

string tel(“Da telefon acasa.”);

string tl(tel, 3, 7);

va initializa tl cu sirul “telefon”. Totusi, acest constructor nu va copia dincolo de sfarsitul sirului sursa; de exemplu,

string tl(tel, 3, 200)

se va opri dupa ce se copiaza punctul. Deci constructorul copiaza un numar de caractere egal cu minimul dintre n si str.size() - pos.

Acest constructor cere ca pos <= str.size(), adica pozitia initiala de la care se incepe copierea sa fie in interiorul sirului sursa; in caz contrar va arunca o exceptie out_of_range. Daca copy_len reprezinta minimul dintre n si str.size() – pos, dupa apelul constructorului, se pastreaza urmatoarele relatii:

  • Metoda data() returneaza un pointer la copia a copy_len elemente din sirul str, incepand cu elementul din pozitia pos din str.

  • Metoda size() returneaza copy_len.

  • Metoda capacity() returneaza o valoare cel putin la fel de mare ca si size().

Constructor care foloseste n copii ale unui caracter

Constructorul urmator creeaza un obiect string care este alcatuit din n caractere consecutive care au valoarea identica c:

basic_string(size_type n, charT c,

const Allocator& a = Allocator());

Constructorul cere ca n < npos. Daca n este egal cu npos, constructorul arunca o exceptie out_of_range. Urmatoarele relatii se pastreaza dupa apelul constructorului:

  • Metoda data() returneaza un pointer la primul element al unui sir de n elemente, fiecare setat la c.

  • Metoda size() returneaza n.

  • Metoda capacity() returneaza o valoare cel putin la fel de mare ca si size().

Constructor care foloseste un interval

Ultimul constructor foloseste un interval definit de iteratori in stilul STL:

template<class InputIterator>

basic_string(InputIterator begin, InputIterator end,

const Allocator& a = Allocator());

Iteratorul begin indica elementul din sursa de unde incepe copierea, iar end indica locatia imediat urmatoare ultimului caracter de copiat.

Aceasta forma o puteti folosi cu tablouri, siruri, sau containere STL:

char cole[40] = “Batranul rege Cole era un suflet vesel.”;

string titlu(cole + 9, cole + 13);

vector<char> intrare;

char car;

while (cin.get(car) && car != ‘\n’)

intrare.push_back(car);

string str_intrare(intrare.begin(), intrare.end());

In primul exemplu, InputIterator este evaluat la tipul const char *. In al doilea, InputIterator este evaluat la tipul vector<char>::iterator.

Urmatoarele relatii se pastreaza dupa apelul constructorului:

  • Metoda data() returneaza un pointer la primul element al sirului format prin copierea elementelor din intervalul [begin, end).

  • Metoda size() returneaza distanta dintre begin si end. (Distanta este masurata in unitati egale cu dimensiunea tipului de date obtinut la dereferentierea iteratorului.)

  • Metoda capacity() returneaza o valoare cel putin la fel de mare ca si size().

Metode pentru memorie

Mai multe metode se ocupa cu memoria; de exemplu, stergerea continutului din memorie, redimensionarea unui sir, ajustarea capacitatii unui sir. Tabelul F.3 va prezinta cateva metode legate de memorie.

Tabelul F.3 Cateva metode legate de memorie.

Metoda Efect

void resize(size_type n) Arunca exceptie out_of_range daca n >

npos. Altfel modifica dimensiunea sirului la n,

prin trunchiere la sfarsit, daca n < size(),

sau prin umplerea cu caractere charT(0),

daca n > size().

void resize(size_type n, charT c) Arunca exceptie out_of_range daca n >

npos. Altfel modifica dimensiunea sirului la n,

prin trunchiere la sfarsit, daca n < size(),

sau prin umplerea cu caractere c, daca n >

size().

void reserve(size_type res_arg = 0)Seteaza capacity() la o valoare mai mare sau

egala cu res_arg. Deoarece in acest fel sirul

este alocat din nou, sunt golite referintele,

pointerii si iteratorii spre sir anteriori.

void clear() Sterge toate caracterele din sir.

bool empty() const Returneaza true daca size() == 0.

Accesul la siruri

Exista patru metode pentru accesul individual la caractere, doua care utilizeaza operatorul [] si doua care folosesc metoda at():

reference operator[](size_type pos);

const_reference operator[](size_type pos) const;

reference at(size_type n);

const_reference at(size_type n) const;

Prima metoda operator[]() va permite sa accesati un element individual al unui sir prin notatia de tablou; poate fi folosita pentru a obtine sau modifica valoarea. A doua metoda operator[]() poate fi folosita cu obiecte const si nu poate modifica valoarea, ci doar sa o obtina:

string cuvant(“crama”);

cout << cuvant[0]; // afiseaza c

cuvant[2] = ‘i’; // suprascrie a cu i

const aparat(“usturoi”);

cout << aparat[2]; // afiseaza t

Metoda at() asigura un acces similar, dar indexul este furnizat ca argument de functie:

string cuvant(“crama”);

cout << cuvant.at(0); // afiseaza c

O alta diferenta (in afara de sintaxa) este ca metodele at() efectueaza verificari de limite, iar daca pos >= size() arunca o exceptie out_of_range. Observati ca pos este de tip size_type, care este fara semn, deci pos nu poate fi negativ. Metodele operator[]() nu fac verificari, deci comportamentul in cazul in care pos >= size() este nedefinit, exceptand versiunea const care returneaza echivalentul caracterului nul daca pos == size().

Prin urmare aveti de ales intre siguranta (utilizand at() si testand exceptii) si viteza de executie (utilizand notatia tablou).

Mai exista o functie care returneaza un sir nou care este un subsir al sirului original:

basic_string substr(size_type pos = 0, size_type n = npos) const;

Returneaza un sir care este o copie a sirului care incepe la pozitia pos si are n caractere sau se termina la sfarsitul sirului. De exemplu, instructiunea urmatoare initializeaza animal cu “magar”:

string mesaj(“Poate ca magarul va invata sa cante.”);

string animal(mesaj.substr(9, 7));

Atribuirea de baza

Sunt trei metode de atribuire supraincarcate:

basic_string& operator=(const basic_string& str);

basic_string& operator=(const charT* s);

basic_string& operator=(charT c);

Prima atribuie un obiect string la altul, a doua atribuie un sir in stil C la un obiect string, iar a treia atribuie un singur caracter la un obiect string. Prin urmare, sunt posibile urmatoarele operatii:

string nume (“George Wash”);

string pres, bip, sursa;

pres = nume;

bip = “Road Runner”;

sursa = ‘X’;

Cautarea in sir

Clasa string dispune de sase functii de cautare, fiecare avand patru prototipuri. Le vom descrie pe scurt.

Familia find()

Iata prototipurile find():

size_type find(const basic_string& str, size_type pos = 0) const;

size_type find(const charT *s, size_type pos = 0) const;

size_type find(const charT *s, size_type pos, size_type n) const;

size_type find(charT c, size_type pos = 0) const;

Primul membru returneaza pozitia de la inceputul primei aparitii a subsirului str in obiectul apelant; cautarea incepand de la pozitia pos. Daca subsirul nu este gasit, metoda returneaza npos.

string lung(“Si cu asta basta”);

string scurt(“asta”);

size_type loc1 = lung.find(scurt); // seteaza loc1 la 6

size_type loc2 = lung.find(scurt, loc1 + 1); // seteaza loc2 la 12

Deoarece a doua cautare incepe de la pozitia 7 (s din asta), prima aparitie a asta pe care o gaseste este la sfarsitul sirului. Pentru a testa esecul, utilizati valoarea string::npos:

if (loc1 == string::npos)

cout << “Nu s-a gasit\n”;

A doua metoda face acelasi lucru, numai ca foloseste ca subsir un tablou de caractere, nu un obiect string:

size_type loc3 = lung.find(“cu”); // seteaza loc3 la 3

A treia metoda face acelasi lucru ca si a doua, numai ca foloseste doar primele n caractere ale sirului s. Produce acelasi efect cu utilizarea constructorului basic_string(const charT* s, size_type n) si folosirea rezultatului acestuia ca argument pentru prima forma a lui find(). De exemplu, in urmatorul cod este cautat subsirul “bas”:

size_type loc4 = lung.find(“basca”, 3); // seteaza loc4 la 11

A patra metoda face acelasi lucru ca si prima, numai ca foloseste un singur caracter ca subsir, nu un obiect string:

size_type loc5 = lung.find(‘a’); // seteaza loc5 la 6

Familia rfind()

Metodele rfind() au urmatoarele prototipuri:

size_type rfind(const basic_string& str, size_type pos = npos)

const;

size_type rfind(const charT *s, size_type pos = npos) const;

size_type rfind(const charT *s, size_type pos, size_type n) const;

size_type rfind(charT c, size_type pos = npos) const;

Aceste metode functioneaza analog cu metodele find(), dar gasesc ultima aparitie a unui sir sau a unui caracter care incepe la sau inainte de pozitia pos. Daca subsirul nu este gasit se returneaza npos.

string lung(“Si cu asta basta”);

string scurt(“asta”);

size_type loc1 = lung.rfind(scurt); // seteaza loc1 la 12

size_type loc2 = lung.rfind(scurt, loc1 - 1);// seteaza loc2 la 6

Familia find_first_of()

Metodele find_first_of() au urmatoarele prototipuri:

size_type find_first_of(const basic_string& str,

size_type pos = 0) const;

size_type find_first_of(const charT *s, size_type pos,

size_type n) const;

size_type find_first_of(const charT *s, size_type pos = 0) const;

size_type find_first_of(charT c, size_type pos = 0) const;

Aceste metode functioneaza analog cu metodele find(), dar in loc sa caute pentru o potrivire a intregului subsir, ele cauta prima potrivire a oricarui caracter din subsir.

string lung(“Si cu asta basta”);

string scurt(“alba”);

size_type loc1 = lung.find_first_of(scurt); // seteaza loc1 la 6

size_type loc2 = lung.find_first_of(“acut”); // seteaza loc2 la 3

Prima aparitie a oricarui caracter din alba in lung este a in asta. Prima aparitie a oricarui din cele patru caractere din acut in lung este c in cu.

Familia find_last_of()

Metodele find_last_of() au urmatoarele prototipuri:

size_type find_last_of(const basic_string& str,

size_type pos = npos) const;

size_type find_last_of(const charT *s, size_type pos, size_type n)

const;

size_type find_last_of(const charT *s, size_type pos = npos)

const;

size_type find_last_of(charT c, size_type pos = npos) const;

Aceste metode functioneaza analog cu metodele rfind(), dar in loc sa caute pentru o potrivire a intregului subsir, ele cauta ultima potrivire a oricarui caracter din subsir.

string lung(“Si cu asta basta”);

string scurt(“asta”);

size_type loc1 = lung.find_last_of(scurt); // seteaza loc1 la 15

size_type loc2 = lung.find_last_of(“troc”); // seteaza loc2 la 14

Ultima aparitie a oricarui caracter din asta in lung este a in basta. Ultima aparitie a oricarui din cele patru caractere din troc in lung este t in basta.

Familia find_first_not_of()

Metodele find_first_not_of() au urmatoarele prototipuri:

size_type find_first_not_of(const basic_string& str,

size_type pos = 0) const;

size_type find_first_not_of(const charT *s, size_type pos,

size_type n) const;

size_type find_first_not_of(const charT *s, size_type pos = 0)

const;

size_type find_first_not_of(charT c, size_type pos = 0) const;

Aceste metode functioneaza analog cu metodele find_first_of(), doar ca ele cauta prima aparitie a oricarui caracter care nu face parte din subsir.

string lung(“Si cu asta basta”);

string scurt(“Sac”);

size_type loc1 = lung.find_first_not_of(scurt);//seteaza loc1 la 1

size_type loc2 = lung.find_first_not_of(Sica);// seteaza loc2 la 2

i din Si este primul caracter din lung care nu apare in Sac. Primul spatiu din sirul lung este primul caracter care nu este in Sica.

Familia find_last_not_of()

Metodele find_last_not_of() au urmatoarele prototipuri:

size_type find_last_not_of(const basic_string& str,

size_type pos = npos) const;

size_type find_last_not_of(const charT *s, size_type pos,

size_type n) const;

size_type find_last_not_of(const charT *s, size_type pos = npos)

const;

size_type find_last_not_of(charT c, size_type pos = npos) const;

Aceste metode functioneaza analog cu metodele find_last_of(), doar ca ele cauta ultima aparitie a oricarui caracter care nu face parte din subsir.

string lung(“Si cu asta basta”);

string scurt(“asta”);

size_type loc1 = lung.find_last_not_of(scurt);

// seteaza loc1 la 11

size_type loc2 = lung.find_last_not_of(scurt, 10);

// seteaza loc2 la 10

b in basta este ultimul caracter din lung care nu face parte din scurt. Ultimul spatiu din sirul lung este ultimul caracter care nu este din scurt, gasit pana la pozitia 10.

Metode si functii de comparare

Clasa string ofera metode si functii pentru compararea a doua siruri. In primul rand, iata prototipurile:

int compare(const basic_string& str) const;

int compare(size_type pos1, size_type n1,

const basic_string& str) const;

int compare(size_type pos1, size_type n1,

const basic_string& str,

size_type pos2, size_type n2) const;

int compare(const charT* s) const;

int compare(size_type pos1, size_type n1,

const charT *s, size_type n2 = npos) const;

Aceste metode utilizeaza o metoda traits::compare() care este definita pentru tipul de caractere folosit de sir. Prima metoda returneaza o valoare mai mica decat 0 daca primul sir este inaintea celui de-al doilea in ordinea data de traits::compare(). Returneaza 0 daca sirurile sunt identice, si o valoare mai mare ca 0 daca primul sir il urmeaza pe al doilea. Daca doua siruri sunt identice pana la sfarsitul sirului mai scurt, atunci acesta il precede pe cel mai lung.

string s1(“clopotel”);

string s2(“clopot”);

string s3(“dangat”);

int a13 = s1.compare(s3); // a13 < 0

int a12 = s1.compare(s2); // a12 > 0

A doua metoda se aseamana cu prima, doar ca utilizeaza doar n1 caractere incepand cu pozitia pos1 din primul sir, pentru a efectua comparatia.

string s1(“clopotel”);

string s2(“clopot”);

int a2 = s1.compare(0, 6, s2); // a2 = 0

A treia metoda se aseamana cu prima, doar ca utilizeaza doar n1 caractere incepand cu pozitia pos1 din primul sir si n2 caractere incepand cu pozitia pos2 din al doilea sir pentru a efectua comparatia. De exemplu, urmatorul cod compara bust din robust cu bust din arbust:

string st1(“mistret robust”);

string st2(“iubea un arbust”);

int a3 = st1.compare(10, 4, st2, 11, 4); //a3 este 0

A patra metoda este ca si prima, numai ca utilizeaza un tablou in loc de un obiect string pentru al doilea sir.

A cincea metoda este ca si a treia, numai ca utilizeaza un tablou in loc de un obiect string pentru al doilea sir.

Functiile de comparare care nu sunt membre sunt operatori relationali supraincarcati:

operator==()

operator<()

operator<=()

operator>()

operator>=()

operator!=()

Fiecare operator este supraincarcat astfel incat sa poata compara un obiect string cu un obiect string, un obiect string cu un sir tablou si un sir tablou cu un obiect string. Toti sunt definiti in functie de metoda compare(), deci ofera o modalitate de notare mai comoda a comparatiilor care se realizeaza.

Modificatori de siruri

Clasa string ofera mai multe metode pentru modificarea sirurilor. Cele mai multe prezinta versiuni supraincarcate pentru a putea fi folosite cu obiecte string, cu tablouri, cu caractere individuale si intervale de iteratori.

Concatenare si adaugare

Puteti adauga un sir la altul utilizand operatorul supraincarcat += sau folosind metoda append(). Toate arunca o exceptie length_error daca rezultatul este mai mare decat dimensiunea maxima a unui sir. Operatorii += va permit sa adaugati un obiect string, un tablou sau un caracter individual la un alt string:

basic_string& operator+=(const basic_string& str);

basic_string& operator+=(const charT* s);

basic_string& operator+=(charT c);

Metodele append() de asemenea va permit sa adaugati un obiect string, un tablou sau un caracter individual la un alt string. In plus, va permit sa adaugati o parte a unui obiect string, specificand o pozitie initiala si numarul de caractere din sir care se vor adauga sau precizand un interval. Puteti adauga o parte a unui sir precizand cate caractere ale sirului se vor folosi. Versiunea care adauga un caracter va permite sa precizati de cate ori se va copia acel caracter.

basic_string& append(const basic_string& str);

basic_string& append(const basic_string& str, size_type pos,

size_type n);

template<class InputIterator>

basic_string& append(InputIterator first, InputIterator last);

basic_string& append(const charT *s);

basic_string& append(const charT *s, size_type n);

basic_string& append(size_type n, charT c); // adauga n copii ale

// lui c

Iata cateva exemple:

string test(“Teo”);

test.append(“rie”); // test este “Teorie”

test.append(3, ‘!’); // test este “Teorie!!!”

Functia operator+() este supraincarcata astfel incat sa permita concatenarea a doua siruri. Functia supraincarcata nu modifica sirurile, ci creeaza un nou sir care este alcatuit dintr-un sir adaugat la celalalt. Functiile aditive nu sunt functii membre si va permit sa adaugati un obiect string la un obiect string, un tablou la un obiect string, un obiect string la un tablou, un caracter la un obiect string si un obiect string la un caracter. Iata cateva exemple:

string st1(“alb”);

string st2(“astru”);

string st3 = st1 + “ume”; // st3 este “albume”

string st4 = ‘c’ + st2; // st4 este “castru”

string st5 = st1 + st2; // st5 este “albastru”

Alte atribuiri

Pe langa operatorul de atribuire de baza, clasa string contine si metodele assign() care va permit sa atribuiti un sir intreg, o parte dintr-un sir sau o secventa de caractere identice la un obiect string.

basic_string& assign(const basic_string& str);

basic_string& assign(const basic_string& str, size_type pos,

size_type n);

basic_string& assign(const charT* s, size_type n);

basic_string& assign(const charT* s);

basic_string& assign(size_type n, charT c); // atribuie n copii

// ale lui c

template<class InputIterator>

basic_string& assign(InputIterator first, InputIterator last);

Iata cateva exemple:

string test;

string chestii(“usi turnante pentru rate”);

test.assign(chestii, 1, 5); // test este “si tu”

test.assign(6, ‘#’); // test este “######”

Metode de inserare

Metodele insert() va permit sa inserati un obiect string, un tablou, un caracter, sau mai multe caractere intr-un obiect string. Metodele sunt similare cu metodele append(), dar preiau un argument suplimentar care indica pozitia in care se va insera noul material. Acest argument poate fi o pozitie sau un iterator. Materialul este inserat inaintea punctului de insertie. Cateva dintre metode returneaza o referinta la sirul rezultat. Daca pos1 este dincolo de sfarsitul sirului tinta iar pos2 este dincolo de sfarsitul sirului de inserat, metoda va arunca o exceptie out_of_range. Daca sirul rezultat are o lungime mai mare decat dimensiunea maxima, metoda arunca o exceptie length_error.

basic_string& insert(size_type pos1, const basic_string& str);

basic_string& insert(size_type pos1, const basic_string& str,

size_type pos2, size_type n);

basic_string& insert(size_type pos, const charT* s, size_type n);

basic_string& insert(size_type pos, const charT* s);

basic_string& insert(size_type pos, size_type n, charT c);

iterator insert(iterator p, charT c = charT());

void insert(iterator p, size_type n, charT c);

template<class InputIterator>

void insert(iterator p, InputIterator first,

InputIterator last);

De exemplu, urmatorul cod insereaza sirul “fost ” inainte de b in bancher:

string st3("Acel bancher.");

st3.insert(5, "fost ");

Atunci, codul care urmeaza insereaza sirul “ a valsat” (fara !, care ar fi al zecelea caracter), chiar inainte de punctul de la sfarsitul sirului “Acel fost bancher.”

st3.insert(st3.size() - 1, " a valsat!", 9);

Metode de stergere

Metodele erase() sterg caractere din sir. Iata prototipurile:

basic_string& erase(size_type pos = 0, size_type n = npos);

iterator erase(iterator position);

iterator erase(iterator first, iterator last);

Prima forma sterge n caractere de la pozitia pos spre sfarsit, sau toate caracterele pana la sfarsit. A doua sterge caracterul indicat de iterator si returneaza un iterator la urmatorul element, sau daca nu mai exista elemente returneaza end(). A treia sterge caracterele din interval (first, last; adica il sterge pe first dar nu si pe last). Metoda returneaza un iterator la elementul care urmeaza dupa ultimul element sters.

Metode de inlocuire

Variatele metode replace() identifica o parte din sir care trebuie inlocuita si identifica si inlocuitorul. Partea care se inlocuieste poate fi identificata prin pozitie initiala si un numar de caractere sau printr-un interval de iteratori. Inlocuitorul poate fi un obiect string, un tablou sau un caracter duplicat de mai multe ori. Obiectele string sau tablourile inlocuitoare pot fi modificate indicand o portiune anume, prin pozitie si numar, doar prin numar sau un interval de iteratori.

basic_string& replace(size_type pos1, size_type n1,

const basic_string& str);

basic_string& replace(size_type pos1, size_type n1,

const basic_string& str, size_type pos2, size_type n2);

basic_string& replace(size_type pos, size_type n1, const charT* s,

size_type n2);

basic_string& replace(size_type pos, size_type n1,

const charT* s);

basic_string& replace(size_type pos, size_type n1, size_type n2,

charT c);

basic_string& replace(iterator i1, iterator i2,

const basic_string& str);

basic_string& replace(iterator i1, iterator i2, const charT* s,

size_type n);

basic_string& replace(iterator i1, iterator i2, const charT* s);

basic_string& replace(iterator i1, iterator i2,

size_type n, charT c);

template<class InputIterator>

basic_string& replace(iterator i1, iterator i2,

InputIterator j1, InputIterator j2);

Iata un exemplu:

string test(“Pe bulevard o iei la dreapta si ajungi.”);

test.replace(21, 7, ”stanga”); // inlocuieste dreapta cu stanga

Alte metode de modificare: copy() si swap()

Metoda copy() copiaza un obiect string, sau doar o parte a sa intr-un tablou:

size_type copy(charT* s, size_type n, size_type pos = 0) const;

Aici s indica tabloul de destinatie, n indica numarul de caractere ce se copiaza iar pos indica pozitia din obiectul string din care incepe copierea. Copierea continua pana la al n-lea caracter sau pana la ultimul caracter din obiectul string. Functia returneaza numarul de caractere copiate. Metoda nu adauga caracterul nul si verificarea dimensiunii tabloului cade in sarcina programatorului.

Atentie

Metoda copy() nu verifica daca tabloul de destinatie este destul de mare pentru a pastra copia si nici nu adauga caracterul nul.

Metoda swap() schimba continutul a doua obiecte string utilizand un algoritm in timp constant:

void swap(basic_string<charT, traits, Allocator>&);

Intrari si iesiri

Clasa string supraincarca operatorul << pentru a afisa obiecte string. Returneaza o referinta la obiectul istream pentru ca iesirea sa poata fi concatenata:

string pretentie(“Clasa string are multe caracteristici.”);

cout << pretentie << endl;

Clasa string supraincarca operatorul >> pentru a putea introduce informatii in obiecte string:

string cine;

cin >> cine;

Intrarea se opreste la EOF, la citirea numarului maxim de caractere permise intr-un sir sau la un caracter alb. (Definitia caracterului alb depinde de setul de caractere si de tipul reprezentat de charT.)

Exista doua functii getline(). Prima are prototipul:

template<class charT, class traits, class Allocator>

basic_istream<charT, traits>&

getline(basic_istream <charT, traits>& is,

basic_string<charT, traits, Allocator>& str, charT delim);

Aceasta citeste caractere din fluxul de intrare is in sirul str pana intalneste caracterul de delimitare delim, ocupa spatiul maxim permis pentru un sir sau intalneste EOF. Caracterul delim este citit (scos din fluxul de intrare), dar nu este stocat. A doua versiune nu are al treilea argument si foloseste in locul lui delim caracterul linie noua (sau generalizarea acestuia):

string str1, str2;

getline(cin, str1); // citeste pana la sfarsitul liniei

getline(cin, str2, ‘.’); // citeste pana la punct