Curs C++ | Sectiunea 27 – Strings (Noi functionalitati)
Substring
💡 Toate operatiile de pana acum au fost realizate pe intregul string. Cu toate acestea, avem optiunea de a le procesa intr-un mod mai precis, selectand doar partile ce sunt relevante pentru noi. O parte dintr-un string poarta numele de substring.
✂️ Daca ne dorim sa cream un nou string ce contine o anumita parte dintr-un string (sau chiar tot), putem folosi o noua metoda numita substr, avand sintaxa urmatoare:
Orice substring este definit de urmatoarele doua coordonate:
- substring_start_position = locul in care substring-ul incepe
- length_of_substring = dimensiunea substring-ului
📝 Atentie, caracterele intr-un string, ca si in orice sir, sunt numerotate incepand cu pozitia 0. Astfel ca un string ce contine n caractere, va avea ultimul element pe pozitia n-1.
Ambii parametrii au valori default, astfel ca putem folosi metoda intr-o forma mai adaptabil:
- str.substr(0,2) = descrie un substring ce incepe cu prima pozitie si se termina cu a treia pozitie (inclusiv)
- str.substr(1,0) = descrie un substring ce incepe cu a doua pozitie si se termina cu ultimul element (inclusiv); putem spune deci ca valoarea default a parametrului length_of_substring acopera toate caracterele ramase in sir
- str.substr() = reprezinta o copie a intregului string (substring_start_positon avand valoarea default 0)
❗ Trebuie sa fiti foarte atenti la acest proces deaorece este unul foarte precis. Nu putem defini un substring ce nu incape total in string-ul original. Acest lucru va duce la respingerea instructiunii, proces ce poarta numele de exceptie. Vom discuta despre ele in curand 😉 .
Dimensiunea unui string
📏 Fiecare string are o lungime, chiar si un string gol (ce nu contine niciun caracter) are lungimea zero. In exemplul nostru cu sortarea am presupus ca transmitem noi dimensiunea string-ului, putem insa sa facem acest lucru automat.
💡 Informatia ne este furnizata de doua metode gemene. Numele lor este diferit dar comportamentul este identic. Putem chiar spune ca aceste functii sunt sinonime. Sintaxa este urmatoarea:
Ambele metode returneaza o valoare egala cu numarul de caractere curente stocate in string. Mai mult, orice substring returnat are la randul lui propriile metode precum substr sau size/length. Putem sa inlantuim aceste metode dar trebuie sa fim atenti.
Mai multe despre comparare
Nu, inca nu am terminat 🙂 . Mai avem ceva de spus despre compararea string-urilor acum ca avem si notiunea de substring-uri. Metoda folosita in sectiunea trecuta ne permite sa comparam si substring-uri. Prototipul metodei arata in felul urmator:
Incepem cu prima varianta care este mai simpla:
Incercam acum si a doua varianta ce presupune sa luam un substring din fiecare string furnizat pentru comparare.
Cautarea unui string in alt string
Uneori se poate sa nu avem nevoie doar sa extragem un substring, dar si sa cautam un anumit substring intr-un string, ceea ce este un proces mai complex.
🕵️ Norocul nostru este ca avem deja o metoda implementata pentru aceasta nevoie. Daca eram in C acum ar fi trebuit sa cream noi o functie de cautare, in schimb C++ si string-urile ne pun la dispozitie metoda find. Sintaxa este urmatoarea:
Pentru ambele variante, parametrul start_here are ca valoare default 0, astfel ca daca il omitem, cautarea va fi realizata de la inceputul string-ului.
❗ Rezultatul returnat indica la prima locatie unde string-ul cautat incepe ori unde caracterul cautat este localizat. In cazul in care cautarea esueaza, ambele metode returneaza o valoare speciala string::npos (vom discuta in curand despre aceasta conventie sintactica). Pentru moment, pune spune ca indica finalul string-ului.
Cat de mare este un string de fapt?
Am spus anterior ca putem extrage informatii despre lungimea unui string folosind una din metodele size/length, insa aceasta informatie este doar partial adevarata. Stim cate caractere sunt momentan stocate in string, dar nu stim nimic despre memoria ocupata de buffer-ul alocat pentru acest string.
📚 De fiecare data cand extindem un string, spre exemplu prin concatenare, noul continut este plasat in buffere. Daca bufferele sunt suficient de mari, atunci nu avem nevoie sa le extindem. Cand bufferele sunt pline insa, acestea sunt realocate pentru a stoca noul continut. Acest proces este complet transparent si in general, se intampla fara stirea noastra.
Desigur, putem sa controlam acest proces daca ne propunem. Ni se ofera cateva moduri in care putem verifica cum functioneaza aceste buffere. Mai intai verificam dimensiunea curenta a buffer-ului, folosind o noua metoda numita capacity.
Rezulatul va fi mereu mai mare sau egal cu dimensiunea string-ului.
Orice string poate creste dar exista, bineinteles, o limita, fiind o valoare definita in implementarea lor. Ca sa o accesam folosim o alta metoda numita max_size. Sa va asteptati ca rezultatul sa fie o valoare mare, foarte mare.
📝 Valoarea max_size, este comuna pentru toate string-urile din program. Veti observa mai departe in urmatorul program in care folosim noile metode invatate.
Cum putem sa controlam dimensiunea unui string?
💡 Facem acest lucru folosind o alta functie membru numita reserve. Functioneaza in ambele sensuri, poate atat micsora buffer-ul dar il poate si extinde. Aceasta necesita un parametru de tip int in care este specificata dimensiunea dorita.
❗ Un lucru important este faptul ca ceea este stocat in string, continutul, nu este modificat, fiind imun la efectul functiei reserve.
🚧 Mai mult, nu vom putea fi atat de stricti cu realocarea memoriei, poate pe cat ne-am dori. Este posibil sa rotunjeasca valoarea parametrului la una corespunzatoare pentru a putea stoca in continuare continutul.
Cu o mica modificare a functiei anterioare, vom observa ca desi am solicitat o dimensiune 0 a string-ului, acest lucru nu se va intampla cum ne-am astepta.
Cum controlam continutul unui string?
🫗 Functiile de care vom discuta au posibilitatea sa modifice alocarea de memorie, fiind un efect secundar. Vom incerca mai intai sa golim un string, sa stergem complet toate caracterele stocate in interior. Poate fi echivalent cu asignarea unui string gol unui string, insa metoda folosita este putin mai rapida. Metoda folosita poarta numele de clear.
📐 Schimbarea dimensiunii continului string-ului se realizeaza priin metoda resize. Exista o varianta standard ce are nevoie de un singur parametru de tip int prin care se specifica noua dimensiune dorita. In cazul in care dimensiunea este mai mica decat dimensiunea curenta, sring-ul va fi trunchiat.
Daca noua dimensiune este mai mare insa, string-ul va fi extins. Avem de asemenea si o varianta supraincarcata(overloaded) a metodei in care putem specifica, printr-un al doilea parametru, un caracter cu care sa fie umplut restul continutului (caracterul null ‘\0‘ este valoarea default a parametrului).
🫙 Exista posibilitatea si sa verificam daca un string este gol (daca nu contine niciun caracter). Avem varianta clasica in care il comparam cu un string gol sau folosim o metoda, procesul fiind mai eficient. Metoda este numita empty, necesita un singur parametru si returnaza o valoare de tip bool, specifica celor doua stari posibile.
Parcurgerea unui string
Ne-am referit pana acum la string-uri ca fiind un tot, dar acest lucru nu inseamna ca nu putem accesa fiecare caracter in parte. Desi am spus ca un string nu este un array, ii putem trata continutul ca si cum ar fi un sir real.
Cel mai simplu mod de a-l parcurge este, asa cum am spus, sa-l tratam ca un sir. Siruile pana acum le-am parcurs folosind instructiunea for, asa ca nici aici nu va fi ceva diferit. Vom incerca spre exemplu sa afisam fiecare caracter pe o linie separata.
Voi puteti sa incercati sa va jucati mai mult cu aceste notiuni. Spre exemplu, ca un mic exercitiu, ar fi sa modificati literele mari in litere mici si invers. Ca un mic hint, ganditi-va la tabelul ASCII 😉 .
Aici se termina si aceasta sectiune. Toate metodele folosite si multe altele le puteti gasi si pe pagina oficiala. Pentru intrebari suplimentare, aveti sectinea contact.
➡ Sectiunea anterioara:Curs C++ | Sectiunea 26 – Strings (Bazele)
➡ Sectiunea urmatoare:Curs C++ | Sectiunea 28 – Strings (Last Words)

