Șiruri în C++: char[], std::string și getline
Învață să citești linii cu spații în C++ folosind char[] și std::string. Înțelege terminatorul nul, lungimea, capacitatea și citirea după un număr.
În acest material
Un șir de caractere păstrează simbolurile unui text în ordine. Într-un tablou clasic char[], sfârșitul textului este marcat prin caracterul nul \0. Într-un std::string, obiectul gestionează lungimea și spațiul necesar. În ambele variante poți accesa un caracter prin indice.
Ai nevoie de caractere și coduri. Folosim indici de la zero și linii ASCII fără caractere nule în interior. Dacă textul are lungimea n, caracterele lui sunt pe pozițiile 0 până la n - 1. Pentru un text gol nu există niciun caracter de prelucrat.
Lungimea nu este capacitatea
Declarația char s[6] = "mere"; rezervă șase elemente. Primele patru conțin literele, poziția 4 conține \0, iar poziția rămasă este tot inițializată cu zero. Lungimea textului este 4, deși tabloul are capacitatea 6.
Un text de n caractere cere cel puțin n + 1 poziții într-un tablou clasic.
Funcția std::strlen, declarată în <cstring>, numără caracterele până la primul terminator, fără să îl includă. Are nevoie de un șir terminat corect. Nu o apela pe un tablou despre care nu știi dacă are \0 în interiorul capacității. Metoda s.size() a unui std::string întoarce lungimea memorată în obiect.
sizeof(s) măsoară dimensiunea obiectului în octeți, nu lungimea textului. Pentru tabloul local de șase caractere dă 6; pentru std::string nu îți spune câte caractere are textul. Nici trimiterea tabloului unei funcții nu păstrează automat informația despre capacitate.
Cuvânt sau linie întreagă?
Citirea cin >> s este potrivită când enunțul cere un singur cuvânt fără spații. Citirea unei linii trebuie să păstreze și spațiile dintre cuvinte. Pentru tablouri folosim cin.getline(s, capacitate), iar pentru std::string, std::getline(cin, s).
Ambele variante consumă delimitatorul de sfârșit de linie, fără să îl adauge în text. Pentru tabloul clasic, capacitatea include locul pentru terminator. Astfel, char s[201] poate păstra cel mult 200 de caractere utile. Dacă linia depășește limita, citirea clasică semnalează eroare; nu presupune că restul intrării a dispărut.
Citirea unui număr urmat de text
Programul primește pe prima linie un număr de identificare între 0 și 1000. Pe linia următoare primește cel mult 200 de caractere ASCII imprimabile, inclusiv spații. Afișează numărul, lungimea textului, apoi textul între paranteze drepte, pe trei linii.
Varianta cu tablou clasic char[]
După citirea numărului, eliminăm restul primei linii, inclusiv \n. Abia apoi citim linia textului. Această ordine păstrează inclusiv o linie goală și spațiile de la începutul textului.
#include <iostream>
#include <cstring>
#include <limits>
int main() {
int id = 0;
std::cin >> id;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
char s[201]{};
std::cin.getline(s, 201);
std::cout << id << '\n' << std::strlen(s) << '\n';
std::cout << '[' << s << "]\n";
return 0;
}
Varianta cu std::string
Contractul de intrare și ieșirea sunt identice. Se schimbă declarația, apelul pentru citirea liniei și obținerea lungimii. ignore are același rol în ambele programe.
#include <iostream>
#include <string>
#include <limits>
int main() {
int id = 0;
std::cin >> id;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string s;
std::getline(std::cin, s);
std::cout << id << '\n' << s.size() << '\n';
std::cout << '[' << s << "]\n";
return 0;
}
Pentru prima linie 7 și a doua linie ana are mere, ieșirea este 7, apoi 12, apoi [ana are mere]. Dacă a doua linie este goală, lungimea este zero și ultima linie este []. Parantezele fac vizibile limitele textului, mai ales când acesta începe sau se termină cu spații.
De ce nu folosim mereu std::ws?
Expresia std::getline(std::cin >> std::ws, s) elimină caracterele albe dinaintea textului. Poate fi utilă într-un alt enunț, dar aici ar pierde spațiile inițiale și ar sări peste liniile goale. Alegem citirea după formatul exact al datelor, nu după o formulă memorată.
Citirea, măsurarea prin strlen și afișarea au în total timp O(n). std::string::size() nu parcurge textul. Tabloul rezervă 201 caractere indiferent de lungimea efectivă; reprezentarea dinamică folosește spațiu proporțional cu textul. Limita și absența caracterelor nule fac parte din enunț, nu sunt verificate de aceste programe demonstrative.
Exersează
- Câte poziții sunt necesare pentru textul
algo25într-un tablou clasic? - Ce lungime are
"a b"? - Ce se întâmplă dacă omitem
ignoredupă citirea numărului? - De ce
sizeofnu înlocuieștestrlen?
Răspunsuri: cel puțin 7; lungimea este 3, inclusiv spațiul; următoarea citire poate consuma doar sfârșitul primei linii și obține text gol; capacitatea obiectului și lungimea textului sunt informații diferite.
Continuă cu operații pe șiruri.
Un pas mai departe
Se încarcă progresul…