Ce sunt șirurile de caractere?
Cum declarăm, citim și afișăm șiruri de caractere în C++ pentru BAC.
char[] versus string -- de ce folosim char[] la BAC
La BAC-ul la informatică, șirurile de caractere se declară întotdeauna cu char[], nu cu string. Dacă folosești string, poți pierde puncte.
#include <iostream>
#include <cstring>
using namespace std;Aceasta este singura librărie pentru șiruri pe care o folosim. Nu includem <string> sau <cctype>.
Declararea unui șir -- ce dimensiune dăm?
Dimensiunea șirului trebuie gândită în funcție de enunț:
Dacă enunțul spune "cel mult N caractere", declari char s[N+1] (plus 1 pentru \0). De exemplu, "cel mult 20 de caractere" => char s[21].
Dacă șirul se modifică prin adăugare de caractere, trebuie să te gândești cât de mare poate deveni. De exemplu, dacă adaugi - între fiecare pereche de cuvinte dintr-un text de 100 de caractere, rezultatul poate crește cu până la 3 * (nr_cuvinte - 1) caractere -- deci ai nevoie de mai mult.
Dacă nu știi exact cât de mare va fi șirul, folosește 256 ca valoare sigură pentru texte scurte sau 1001 pentru texte mai lungi.
char s[101]; // dacă enunțul spune "cel mult 100 de caractere"
char s[256]; // valoare sigură când nu ai o limită clarăȘirul auxiliar t
Șirul auxiliar t are de obicei aceeași dimensiune ca s, sau mai mare dacă rezultatul final poate fi mai lung:
char s[201]; // text de cel mult 200 de caractere
char t[201]; // auxiliar de aceeași dimensiune -- dacă nu adaugi caractere
char t[400]; // auxiliar mai mare -- dacă rezultatul poate fi aproape dublu, aducem și șirul s la aceeași valoare.Caracterul nul \0
Un șir de caractere în C++ se termină cu caracterul special \0 (caracterul nul). El nu e vizibil, dar este prezent și semnalează sfârșitul șirului.
char s[21] = "bac"; // în memorie: b a c \0
// s[0]='b', s[1]='a', s[2]='c', s[3]='\0'Greșeli frecvente
Nu poți atribui direct un șir cu = după declarare:
char s[21];
s = "bac"; // GREȘIT -- eroare de compilare!
strcpy(s, "bac"); // CORECTNu poți compara șiruri cu ==:
if (s == t) // GREȘIT -- compară adrese, nu conținut!
if (strcmp(s, t)==0) // CORECTCitirea unui șir: cin >> și cin.getline
Există două moduri de citire a unui șir, și trebuie să știi exact când să folosești fiecare.
cin >> s (fără spații)
char s[N+1]; // N = lungimea maximă din enunț
cin >> s;Citește caractere până la primul spațiu, tab sau enter. Spațiile nu sunt incluse în șir.
Exemplu: dacă introduci informatica cpp, s va conține doar informatica.
Când folosești: când citești un singur cuvânt.
cin.getline(s, N+1) (cu spații)
char s[N+1]; // N = lungimea maximă din enunț
cin.getline(s, N+1);Citește o linie întreagă, inclusiv spațiile, până la enter. Enter-ul nu e inclus în șir.
Când folosești: când citești un text cu mai multe cuvinte separate prin spații.
Notă: Al doilea parametru al getline trebuie să fie dimensiunea bufferului declarat, nu o altă valoare.Problema clasică: mix de cin >> și getline
Dacă citești un număr cu cin >> n și apoi un șir cu cin.getline, trebuie să "consumi" enter-ul rămas:
int n;
char s[N+1];
cin >> n;
cin.ignore(); // consumă enter-ul rămas
cin.getline(s, N+1);Fără cin.ignore(), getline va citi un șir gol.
Afișarea unui șir
cout << s; // afișează tot șirul până la \0
cout << s[i]; // afișează un singur caracterAccesul la un caracter
char s[21] = "bac";
cout << s[0]; // b
cout << s[1]; // a
cout << s[2]; // c
// s[3] = '\0' (sfârșitul șirului)Parcurgerea unui șir
char s[N+1];
cin >> s;
for (int i = 0; i < strlen(s); i++) {
cout << s[i] << " ";
}Sau varianta clasică BAC cu while:
int i = 0;
while (s[i] != '\0') {
cout << s[i];
i++;
}strlen -- lungimea unui șir
#include <cstring>strlen(s) returnează numărul de caractere din șir, fără a număra caracterul \0.
char s[256] = "bac";
cout << strlen(s); // afișează 3Atenție la folosirea strlen în for
// Varianta corectă dar mai lentă:
for (int i = 0; i < strlen(s); i++) { ... }
// Varianta mai eficientă:
int n = strlen(s);
for (int i = 0; i < n; i++) { ... }În prima variantă, strlen e apelată la fiecare iterație. La BAC ambele sunt acceptate.
strlen și tipul returnat
La BAC declarăm întotdeauna:
int n = strlen(s);Și folosim n în loc de strlen(s) în bucle.
Greșeli frecvente
char s[256] = "bac";
cout << sizeof(s); // 256 -- dimensiunea bufferului, NU lungimea șirului!
cout << strlen(s); // 3 -- lungimea realăNu confunda sizeof cu strlen!
Șir gol
char s[256] = "";
cout << strlen(s); // 0
// s[0] = '\0' direct