You are on page 1of 11

InfoAcademy Adonis Butufei

6 TABLOURI SI SIRURI DE CARACTERE

CUPRINS
6 Tipuri compuse de date...............................................................................................................................2
6.1 Variabile de tip tablou (array)..............................................................................................................2
6.1.1 Declararea tablourilor..................................................................................................................2
6.1.2 Initializarea tablourilor................................................................................................................2
6.1.3 Accesarea elementelor.................................................................................................................4
6.1.4 Tablouri cu mai multe dimensiuni...............................................................................................5
6.2 Siruri de caractere................................................................................................................................6
6.2.1 Operatii cu siruri de caractere......................................................................................................7
6.2.1.1 Determinarea lungimii unui string.......................................................................................7
6.2.1.2 Copierea sirurilor de caractere.............................................................................................7
6.2.1.3 Concatenarea sirurilor de caractere......................................................................................8
6.2.1.4 Compararea sirurilor de caractere........................................................................................9
6.3 Sumar................................................................................................................................................10
6.4 Intrebari si exercitii...........................................................................................................................11
6.5 Bibliografie........................................................................................................................................11

1
InfoAcademy Adonis Butufei

6 TABLOURI SI SIRURI DE CARACTERE


In capitolele anterioare am discutat despre tipurile de variabile simple suportate de C++. In acest capitol
vom discuta despre tipuri complexe de date folosite in programele practice:
Tipuri compuse de date: tablouri si siruri de caractere.

6.1 Variabile de tip tablou (array)


In activitatile curente folosim clasamente si statistici pentru o gama variata de activitati: rezultate scolare,
sportive, evolutia preturilor etc. In aceste cazuri lucram cu valori care apartin aceleiasi categorii de
elemente. De exemplu, in cazul rezultatelor la examenele de admitere avem o lista care contine numele
participantilor, nota la fiecare proba si media. Pentru a determina candidatii admisi, lista se sorteaza
descrescator dupa media notelor.

Pentru a scrie programe care sa lucreze cu acest tip de date avem nevoie sa folosim tipul de date numit
tablou. Acest tip de date este o colectie secventiala de locatii de memorie de acelasi tip. Fiecare locatie se
numeste element.

6.1.1 Declararea tablourilor


Pentru declararea tablourilor specificam tipul elementelor, numele si, intre paranteze drepte, dimensiunea.

Exemplu:
int tablou[3];

In acest exemplu am declarat un tablou de trei elemente de tip intreg.

6.1.2 Initializarea tablourilor


Initializarea se poate realiza specificand valorile la declarare.
Exemplu:
int tablou[5] = { 1, 2, 3, 4, 5 };

In acest exemplu am initialzat un tablou de 5 elementete intregi.

tablou[0] tablou[1] tablou[2] tablou[3] tablou[4]


tablou 1 2 3 4 5
int

Observatii:
• Se poate omite dimensiunea tabloului la declarare daca se initializeaza toate elementele. In exemplul
de mai jos se initializeaza un tablou de 5 elemente.
int tablou[] = {1, 2, 3, 4, 5};

2
InfoAcademy Adonis Butufei

• Daca numarul de elemente folosite pentru initializare depaseste dimensiunea tabloului se obtine o
eroare de compilare:
int tablou[3] = { 1, 2, 3, 4};

• In cazul in care sunt mai putine valori pentru initializare, ele vor fi folosite pentru initializarea primelor
elemente din tablou. Dupa ce s-au folosit toate valorile, elementele ramase vor fi initializate cu 0:
int tablou[3] = { 1, 2} ;// tablou[2] are valoarea 0.

• Pentru initializarea tuturor elementelor cu 0 este suficient sa folosim o singura valoare 0 in dreapta
egalului:
int tablou[3] = {0}; // echivalent cu tablou[3] = { 0, 0, 0};

Important
• La declarare compilatorul rezerva memorie pentru toate elementele tabloului si este singurul morment
cand se pot specifica valori pentru mai mult de un element.
int tablou[3] = {1,2,3};
tablou[3] = {4,5}; // generaza eroare de compilare

• Nu se poate face atribuire de la un tablou la altul1.


int tablou1[3] = {2,4,5};
int tablou2[3] = tablou1; // genereaza eroare de compilare

• Pentru tablouri nu pot fi folositi operatorii relationali = = , != , > etc.


int tablou1[3] = {2,4,5};
int tablou2[3] = {2,4,5};
if(tablou1 == tablou2) // nu realizeaza compararea tablourilor2
{
cout << "tablouri egale\n";
}

• Dimensiunea tabloului nu este continuta in tablou si trebuie gestionata de programator.

1 Daca dorim copierea elementelor unui tablou in alt tablou este necesara folosirea buclelor si prelucrarea individuala a
elementelor.
2 Practic se compara adresele de memorie ale celor doua tablouri (vom discuta aceasta in lectia urmatoare), deoarece adresele
sunt diferite rezultatul este altul decat cel asteptat.
3
InfoAcademy Adonis Butufei

6.1.3 Accesarea elementelor


Accesarea elementelor unui tablou se face folosind o variabila intreaga numita index care reprezinta
offsetul fata de inceputul tabloului. Indexul porneste de la zero. Folosind exemplul anterior, primul
element este tablou[0], al doilea este tablou [1] iar ultimul este tablou[2].
Exemplu:
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: const int SIZE = 3;
7: int tablou[SIZE];
8:
9: for(int i = 0; i < SIZE; i++)
10: {
11: cout << "tablou[" << i << "]=";
12: cin >> tablou[i];
13: }
14:
15: for(int i= 0; i < SIZE; i++)
16: {
17: cout << i <<": " << tablou[i] << "\n";
18: }
19: return 0;
20: }

In acest tablou am initializat elementele unui vector de elemente intregi si am afisat valorile pe ecran.
In linia 6 am declarat o constanta care reprezinta dimensiunea tabloului. Aceasta se foloseste pentru
declararea tabloului in linia 7 si pentru conditiile de limita din bucle in liniile 9 si 15.
Valorile tabloului sunt citite de la tastatura (liniile 9 – 13) si afisate pe ecran (liniile 15 – 18).

Important
• Deoarece indexul tablourilor porneste de la 0, valoarea indexului corespunzator ultimului element este
SIZE -1.
• Pentru ca programele sa functioneze corect este important ca indexul sa fie intotdeauna valid adica sa
apartina intervalului [0 SIZE).
• In compilatorul nu verifica aceasta conditie si este responsabilitatea programatorului sa se asigure ca
acest index este corect.

4
InfoAcademy Adonis Butufei

6.1.4 Tablouri cu mai multe dimensiuni


Exista probleme care se pot rezolva mai usor folosind tablouri cu mai multe dimensiuni. De exemplu
pentru a rezolva un sistem de 2 ecuatii cu 2 necunoscute trebuie sa folosim tablouri de doua linii si doua
coloane care contin valorile coeficientilor.

Declararea tablourilor cu mai multe dimensiuni se face asemanator cu declararea tablourilor cu o singura
dimensiune. In plus, pentru fiecare dimensiune se mai adauga o pereche de paranteze drepte.
Exemplu de declarare a unei matrici de 2 x 2 elemente:
double matrice[2] [2];

Initializarea tuturor elementelor cu 0 se realizeaza folosind o singura valoare in dreapta operatorului =.


Exemplu:
double matrice [2][2] = {0.0};

0 1
matrice 0 0.0 0.0
1 0.0 0.0

matrice[0][1]

Modul de lucru cu tablouri cu mai multe dimensiuni este prezentat in exemplul de mai jos.
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: const int SIZE1 = 2;
7: const int SIZE2 = 3;
8:
9: // Declarare si initializare
10: int matrice [SIZE1][SIZE2] = { {1,2,3} , {4,5,6} };
11:
12: for(int i = 0; i < SIZE1; i++)
13: {
14: for(int j = 0; j < SIZE2; j++)
15: {
16: cout << "matrice[" << i << "][" << j << "]=";
17: cout << matrice[i][j] << "\n";
18: }
5
InfoAcademy Adonis Butufei

19: }
20: return 0;
21: }

Initializarea tabloului este realizata in linia 10 . Pentru accesarea elementelor am folosit doua bucle,
fiecare pentru o dimensiune a tabloului. In linia 17 se acceseaza valorile corespunzatoare indecsilor.

6.2 Siruri de caractere


Sirurile de caractere sunt un tip special de tablouri care contin coduri ASCII folosite pentru lucrul cu
mesaje de tip text. Au fost preluate din C si le intalnim frecvent in multe programe.
Exemplu:
char mesaj [] = "Hello World!";

Spre deosebire tablourile prezentate anterior, sirurile de caractere contin pe ultima pozitie caracterul de
control '\0', care reprezinta terminatorul sirului. Acest caracter este introdus automat de compilator,
insa este necesar ca tabloul sa aiba alocat spatiu pentru el.
In urmatorul exemplu obtinem eroare de compilare deoarece mesajul are 12 caractere si compilatorul nu
mai are spatiu pentru terminator.
char mesaj[12] = "Hello World!"; // Tabloul trebuie sa aiba 13
// caractere.

Din acest motiv, pentru mesajele care nu se modifica pe parcursul executiei programului este
recomandabila prima varianta de declarare, deoarece dimensiunea tabloului se calculeaza automat.
Terminatorul sirului nu este printabil si orice caracter printabil3 pozitionat dupa acest caracter nu este
afisat.
Exemplu:
#include <iostream>
using namespace std;

int main()
{
char mesaj [] = "Hello\0 World!";
cout << mesaj << "\n";
return 0;
}

In acest exempul pe ecran va fi afisat numai mesajul Hello.

3 Caracterele printabile sunt caractere care se afiseaza pe ecran si au fost prezentate in capitolul 3.
6
InfoAcademy Adonis Butufei

6.2.1 Operatii cu siruri de caractere


Modificarea variabilelor simple se face prin atribuire. Pentru modificarea variabilelor de tip tablou este
necesara scrierea unor functii. In cazul sirurilor de caractere, pentru copierea, concatenarea, determinarea
lungimii sirurilor etc, se folosesc functii specifice declarate in headerul cstring.

6.2.1.1 Determinarea lungimii unui string


Se face cu functia strlen. Aceasta functie returneaza doar numarul de caractere al mesajului,
terminatorul sirurului nu este luat in calcul.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char mesaj [] = "Hello World!";
cout << mesaj << " are " << strlen(mesaj) << " caractere.\n";
return 0;
}

In acest exemplu am inclus headerul cstring pentru a putea apela functia strlen. Mesajul din acest
exemplu are 12 caractere.
Important
Atunci cand calculam spatiul necesar pentru un tablou trebuie sa incrementam valoarea returnata de
strlen pentru a obtine spatiul necesar pentru terminator.

6.2.1.2 Copierea sirurilor de caractere


In cazul variabilelor simple pentru schimbarea valorii este suficient sa folosim operatorul =. In cazul
sirurilor de caractere este necesar sa copiem fiecare caracter si pentru asta folosim functiile strcpy.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char mesaj1 [] = "Hello World!";
char mesaj2 [50];
strcpy(mesaj2, mesaj1);
cout << mesaj1 << "\n" << mesaj2;

7
InfoAcademy Adonis Butufei

return 0;
}

In acest exemplu, dupa apelul functiei strcpy, ambele variabile vor contine acelasi mesaj.

Important
Variabila destinatie trebuie sa aiba suficient spatiu pentru a putea copia tot mesajul inclusiv terminatorul
de caractere.
Daca vrem sa copiem numai primele n caractere putem folosi functia strncpy, ca in exemplul urmator:
1: #include <iostream>
2: #include <cstring>
3: using namespace std;
4: int main()
5: {
6: char mesaj1 [] = "Hello World!";
7: char mesaj2 [6];
8: strncpy(mesaj2, mesaj1, 5);
9: mesaj2[5] = '\0';
10: cout << mesaj1 << "\n" << mesaj2;
11: return 0;
12: }

In acest exemplu am copiat doar primele 5 caractere din mesaj1. Este important de remarcat adaugarea
terminatorului in linia 9. Acesta este necesar deoarece dupa copierea primelor 5 caractere din variabila
mesaj1 sirul trebuie sa aiba terminatorul setat corect.

6.2.1.3 Concatenarea sirurilor de caractere


Exista situatii frecvente in care avem nevoie sa combinam continutul a doua siruri de caractere. Aceasta
se realizeaza cu ajutorul functiei strcat.
Exemplu:
1: #include <iostream>
2: #include <cstring>
3: using namespace std;
4: int main()
5: {
6: char nume [] = "Popescu";
7: char prenume [] = "Vasile";
8: char id [60] = {'\0'};
9: strcpy(id,nume);
10: strcat(id,".");
11: strcat(id,prenume);
12: cout << nume << "\n";

8
InfoAcademy Adonis Butufei

13: cout << prenume << "\n";


14: cout << id << "\n";
15: return 0;
16: }

In acest exemplu am format un identificator de persoana format din Nume.Prenume.


In linia 12 am copiat numele, apoi am adaugat caracterul '.' pentru a separa numele de prenume. La final
am adaugat prenumele.
Important
Sirul destinatie trebuie sa aiba suficient spatiu pentru copierea tuturor caracterelor plus terminatorul de sir.

6.2.1.4 Compararea sirurilor de caractere


Deoarece sirurile de caractere sunt un tip de date compus, pentru comparare se foloseste functia strcmp
(nu operatorul = = ). Aceasta functie compara caracter cu caracter elementele celor doua siruri si
returneaza 0 daca sirurile au aceleasi caractere, o valoare pozitiva daca primul caracter care difera are
valoare mai mare, o valoare negativa in caz contrar.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char inventator [] = "Edison";
char raspuns [30];

cout << "Cine a inventat becul cu incandescenta?\n";


cin >> raspuns;

if(0 == strcmp(inventator, raspuns))


{
cout << "Corect\n";
}
else
{
cout << "Incorect\n";
}
return 0;
}

9
InfoAcademy Adonis Butufei

Important
Compararea sirurilor de caractere este case sensitive, adica literele mari sunt considerate diferite de cele
mici: A != a. Pentru ca doua siruri de caractere sa fie egale trebuie sa contina acelasi tip de litere.

6.3 Sumar
• Tabloul (array) reprezinta o serie de date de acelasi tip plasate in locatii succesive de memorie.
• Fiecare dintre aceste locatii de memorie se poate accesa prin incrementarea unui index atasat numelui
tabloului.
• Indexul porneste de la 0.
• Declararea unui tablou: tip numeTablou[elemente]
• Initializarea: tip numeTablou[] = {element1, element2, element3}
• Accesarea elementelor: numeTablou[index]
• Valoarea indexului corespunzatoare ultimului element este: dimensiunea tabloului (numarul de
elemente) – 1.
• Pentru anumite probleme se pot folosi tablouri cu 2 sau mai multe dimensiuni.
• Pentru tablourile cu mai mult de 2 dimensiuni trebuie tinut cont de memoria consumata.
• Declarare: tip nume[elemente1][elemente1]
• Un tip particular de tablou este sirul de caractere.
• In acest caz elementele tabloului sunt codurile ASCII folosite pentru mesaje de tip text.
• Declarare si initializare: char mesaj [] = "Hello World!";
• Sirurile de caractere se termina cu un caracter de control '\0'. Atentie la alocarea spatiului pentru acest
terminator!
• Deoarece sirurile de caractere sunt un tip de date compus modificarea lor se face cu ajutorul unor
functii.
• In C++ aceste functii sunt implementate in fisierul cstring:
strlen() - lungimea sirului (fara terminator)
strcpy() - copiere
strncpy() – copierea primelor n caractere
strcat() - concatenare
strcmp() - comparare

10
InfoAcademy Adonis Butufei

6.4 Intrebari si exercitii


1. Urmatoarea linie de cod este incorecta. Care este greseala?
int test [4] = {1,2,3,4,5};

2. Cum se declara un tablou de tip double care are trei dimensiuni si poate contine 4 elemente pentru
prima dimensiune, 5 elemente pentru a doua dimensiune si 10 elemente pentru a treia dimensiune?

3. Care este indexul pentru primul element al unui tablou?

4. Care este indexul ultimului element al tabloului de mai jos?


int m [5];

5. Care este valoarea celui de-al treilea element al urmatorului tablou?


int pos [4] = {1,2};

6. Cum se initializeaza toate elementele unui tablou cu o anumita valoare?

7. Sa se scrie un program care calculeaza determinantul4 unei matrici de doua linii si doua coloane.

8. Sa se scrie un program care citeste de la tastatura un mesaj de maxim 20 de caractere (dimensiunea


sirului) si afiseaza lungimea sirului de caractere.

9. Sa se scrie un program care citeste de la tastatura numele, prenumele si calculeaza adresa de email
dupa urmatoarea formula prenume.nume@mailserver.com.

6.5 Bibliografie
• C++ Without Fear, Second Edition, Prentice Hall, Brian Overland, Cap 7.
• Practical C++ Programming, Second Edition, O'Reilly, Steve Oualline, Cap 5, 12.

4 Determinantul este produsul elementelor de pe diagonala principala (cu indecsii egali) minus produsul
elementelor de pe diagonala secundara.
11

You might also like