De ce contează?
Gândește-te la un cuvânt scris pe o bandă de pătrățele: fiecare pătrățel ține exact o literă, iar pătrățelele sunt numerotate de la 0. Asta este un string — un șir de caractere așezate unul după altul, fiecare cu poziția lui.
Ce este un string?
Un string este o secvență de caractere stocate în ordine. În C++ ai tipul
string din biblioteca standard, care se comportă ca un vector de char, dar
cu un mare avantaj: își gestionează singur lungimea și memoria.
Spre deosebire de char s[100], unde tu decizi dimensiunea și ai grijă de
terminatorul '\0', un string crește și scade automat și știe mereu câte
caractere are.
Un string indexat se comportă fix ca un vector: s[0] e primul caracter,
s[s.size() - 1] e ultimul. Indecșii merg de la 0 la size() - 1.
Cum arată în memorie
Fie s = "info". Caracterele stau pe poziții consecutive:
| s | i | n | f | o |
| index | 0 | 1 | 2 | 3 |
Lungimea este s.size() (sau echivalent s.length()) — aici 4. Nu există
caracter pe poziția 4; accesul acolo este în afara șirului.
Citire și afișare
Sunt două moduri de citire, și e important să nu le confunzi:
#include <iostream>
#include <string>
using namespace std;
int main() {
string cuvant;
cin >> cuvant; // citeste pana la primul spatiu
cout << cuvant << "\n"; // afiseaza cuvantul citit
string linie;
getline(cin, linie); // citeste toata linia, cu spatii
cout << linie << "\n";
return 0;
}De ce contează diferența? cin >> cuvant se oprește la primul spațiu, deci
pentru intrarea mihai pop citește doar mihai. Dacă vrei numele complet, ai
nevoie de getline.
Capcana clasică: după cin >> n, un getline(cin, s) imediat citește linia
goală rămasă (Enterul de după număr). Soluție: consumă restul liniei cu
cin.ignore() înainte de getline.
Operații de bază
string suportă lucruri pe care char[] nu le face direct:
#include <iostream>
#include <string>
using namespace std;
int main() {
string a = "info", b = "matica";
string c = a + b; // concatenare -> "informatica"
cout << c << "\n"; // informatica
cout << c.size() << "\n"; // 11
c[0] = 'I'; // modifici un caracter
cout << c << "\n"; // Informatica
if (a < b) cout << "a inainte\n"; // comparatie lexicografica
return 0;
}Adunarea (+) lipește două șiruri, comparația (<, ==) se face
lexicografic (ca în dicționar), iar c[i] îți dă acces direct la fiecare
caracter ca la un vector.
Complexitate
| Operație | Timp |
|---|---|
s[i] (acces) | O(1) |
s.size() | O(1) |
a + b (concatenare) | O(lungimea rezultatului) |
comparație a < b | O(lungimea minimă) |
s.size() întoarce un tip fără semn (size_t). Într-un for cu scădere,
s.size() - 1 pe un șir gol devine un număr uriaș, nu -1. Vezi capcana.
Greșeli frecvente de concurs:
- Confuzia
'a'cu"a": ghilimele simple = un singurchar; ghilimele duble = string.s = 'a';nu compilează cum crezi. size()fără semn:for (int i = 0; i <= s.size() - 1; i++)pe șir gol iterează miliarde de pași. Folosește(int)s.size()sau testeazăi < s.size().- Citire amestecată
cin >>cugetlinefărăcin.ignore(). - Acces în afara șirului:
s[s.size()]nu e caracter valid.
Recapitulare
- Un
stringe un șir de caractere indexabil de la0lasize() - 1, care își gestionează singur memoria. cin >>citește un cuvânt;getline(cin, s)citește toată linia, cu spații.- Suportă concatenare (
+), comparație lexicografică și acces directs[i].