Șiruri de caractere la atestatul de informatică
Citirea unui text cu getline, parcurgerea până la terminator, numărarea cuvintelor cu flag, filtrarea caracterelor și compararea cu strcmp — cu problemele de atestat în care apar.
Subiectele cu text par variate, dar se reduc la patru tehnici. Cele mai multe puncte se pierd nu pe logică, ci pe două detalii tehnice: cum citești textul și cât de mare declari șirul.
Citirea unui text
char s[201];
cin.getline(s, 201); // de la tastatura
f.getline(s, 201); // dintr-un fisier
getline, nu >>. Operatorul >> se oprește la primul spațiu, deci ai prelua doar primul
cuvânt — iar la problemele care numără cuvinte ai obține mereu 1. getline ia tot rândul, cu
spații și semne de punctuație.
Dimensiunea e cu unu mai mare decât maximul din enunț. „Cel mult 200 de caractere" înseamnă
char s[201]: mai trebuie un loc pentru terminatorul '\0', pe care C++ îl adaugă automat la
final. Cu char s[200] scrii în afara șirului la un text de exact 200 de caractere.
Parcurgerea merge până la terminator, deci nu ai nevoie de lungime:
for (int i = 0; s[i] != '\0'; i++) { /* ... */ }
Tehnica 1 — Numărarea cuvintelor cu flag
Ideea tentantă „numărul de cuvinte = numărul de spații + 1" e greșită imediat ce textul începe sau se termină cu spațiu — exact ce testează enunțurile.
Metoda corectă numără tranzițiile de la separator la literă:
int nr = 0;
bool inCuvant = false;
for (int i = 0; s[i] != '\0'; i++)
if (s[i] != ' ') {
if (!inCuvant) nr++; // tocmai am intrat intr-un cuvant nou
inCuvant = true;
} else {
inCuvant = false;
}
Flagul reține unde te afli. Incrementarea se face doar la intrarea într-un cuvânt; literele
următoare nu mai numără nimic, pentru că flagul e deja true.
Metoda tratează automat toate cazurile-limită: spații la început, spații la final, spații multiple, text gol.
Probleme: numărarea cuvintelor · afișarea cuvintelor pe linii distincte
Separatori multipli. Când cuvintele se despart prin spații și virgule, scrie o funcție
esteSeparator(char c). Dacă enunțul adaugă alt semn, modifici o singură linie.Și atenție: trecerea pe rând nou se face doar la ieșirea dintr-un cuvânt (
if (inCuvant)), nu la fiecare separator — altfel spațiile multiple produc rânduri goale.
Tehnica 2 — Filtrarea caracterelor
Pentru „elimină X din șir", nu ștergi caractere — construiești un șir nou cu ce păstrezi, folosind doi indici care avansează independent:
int k = 0;
for (int i = 0; s[i] != '\0'; i++)
if (!deSters(s[i])) rezultat[k++] = s[i];
rezultat[k] = '\0'; // OBLIGATORIU
i parcurge tot, k avansează doar când chiar scrii. E aceeași tehnică ca la
filtrarea vectorilor, aplicată caracterelor.
Terminatorul de la final e obligatoriu. Fără rezultat[k] = '\0', afișarea continuă în memorie
dincolo de șir și apar caractere aleatorii.
Probleme: eliminarea cifrelor din șir
Tehnica 3 — Teste pe caractere
Caracterele sunt numere. În tabela ASCII, grupurile sunt consecutive, deci testele devin comparații de interval:
if (c >= '0' && c <= '9') // cifra
if (c >= 'a' && c <= 'z') // litera mica
if (c >= 'A' && c <= 'Z') // litera mare
Ghilimelele simple contează: '0' e caracterul zero (cod 48), nu numărul 0.
Conversia majusculă → minusculă se face adunând 32, pentru că literele mici sunt cu exact atât
mai departe ('A' = 65, 'a' = 97):
if (c >= 'A' && c <= 'Z') c = c + 32;
Verificarea intervalului e necesară — altfel strici cifrele și semnele de punctuație. Tehnica e utilă oriunde enunțul cere și majuscule, și minuscule: în loc de zece comparații pentru vocale, converteşti și compari cu cinci.
Probleme: numărul de vocale
Tehnica 4 — Compararea cuvintelor
#include <cstring>
if (strcmp(cuvant, cautat) == 0) nr++;
Două capcane, ambele frecvente:
==nu merge pe șiruri de caractere. Compară adresele din memorie, nu conținutul, iar rezultatul e aproape întotdeauna fals.strcmpreturnează0la egalitate, nu1. Valoarea returnată e diferența în ordine alfabetică: negativă, zero sau pozitivă.
Cuvinte întregi vs. subșiruri. Citind cuvânt cu cuvânt cu
f >> cuvant, delimitarea se rezolvă singură —masininu va fi niciodată egal cusi. Dacă ai căuta custrstr, ai număra și aparițiile din interiorul altor cuvinte, ceea ce enunțurile cer de obicei să nu se întâmple.
Probleme: aparițiile unui cuvânt în text
Greșeli care se repetă
cin >> sîn loc degetline— se citește doar primul cuvântchar s[200]pentru „cel mult 200 de caractere" — lipsește locul terminatorului- Numărarea spațiilor + 1 — greșit la spații de la început sau final
- Terminatorul
'\0'uitat după construirea unui șir nou cuvant == cautatîn loc destrcmpstrcmp(...) == 1— funcția returnează0la egalitate- Conversia
c + 32fără verificarea intervalului — strică cifrele - Rânduri goale la separatori multipli, din lipsa testului
if (inCuvant)
Toate problemele din această categorie
Fiecare are rezolvare completă în C++, explicată pas cu pas.