Cerințele pe șiruri de caractere de la BAC informatică par diferite de la an la an, dar în spatele lor stau aceleași câteva operații: verificarea unui palindrom, recunoașterea vocalelor, transformarea literelor mici în majuscule, înlocuirea și ștergerea caracterelor sau a secvențelor. Dacă le știi pe acestea „pe de rost”, orice problemă nouă devine o combinație de piese cunoscute. Mai jos le ai pe toate, în C++, cu șiruri char[] și funcții din <cstring>.

1. Palindromul

Un șir este palindrom dacă se citește la fel de la stânga la dreapta și de la dreapta la stânga („cojoc”, „rotor”). Folosești doi indici: unul pornește de la început, celălalt de la sfârșit, și se apropie unul de celălalt cât timp caracterele sunt egale.

int palindrom(char s[])
{
    int i = 0, j = strlen(s) - 1;
    while (i < j)
    {
        if (s[i] != s[j]) return 0;
        i++;
        j--;
    }
    return 1;
}

Pentru „rotor”: compari s[0]='r' cu s[4]='r', apoi s[1]='o' cu s[3]='o', apoi i=j=2 și bucla se oprește → returnează 1. Pentru „radar” la fel, pentru „ramura” prima comparație e deja 'r' cu 'a' → 0. Nu ai nevoie să construiești șirul inversat; varianta cu doi indici e mai scurtă și nu folosește memorie suplimentară.

2. Vocale și consoane

Pentru litere mici, cel mai elegant test de vocală este strchr("aeiou", c) != NULL. Dacă textul conține și majuscule, folosește "aeiouAEIOU". O consoană este o literă care nu e vocală — dacă textul conține și spații sau cifre, verifică întâi că e literă.

int nv = 0, nc = 0;
for (int i = 0; s[i] != '\0'; i++)
    if (s[i] >= 'a' && s[i] <= 'z')
    {
        if (strchr("aeiou", s[i]) != NULL) nv++;
        else nc++;
    }

Pentru textul bac la info se obțin nv = 4 (a, a, i, o) și nc = 5 (b, c, l, n, f). Spațiile nu intră în niciun contor datorită testului de literă.

3. Majuscule și litere mici

Literele mici și majusculele corespunzătoare diferă în codul ASCII prin 32 ('a' = 97, 'A' = 65). Formula care nu depinde de memorarea acestei valori:

if (s[i] >= 'a' && s[i] <= 'z') s[i] = s[i] - 'a' + 'A';   // mică → mare
if (s[i] >= 'A' && s[i] <= 'Z') s[i] = s[i] - 'A' + 'a';   // mare → mică

Poți folosi și toupper/tolower din <cctype>, dar la itemii de urmărire apare frecvent varianta cu scăderea lui 32, deci trebuie să o recunoști. O variantă clasică de cerință: „transformați în majusculă ultima literă a fiecărui cuvânt” — o literă e ultima dacă după ea urmează spațiu sau '\0'.

4. Înlocuirea unui caracter

Înlocuirea unui caracter cu altul nu schimbă lungimea șirului, deci se face direct, pe loc. De exemplu, fiecare vocală se înlocuiește cu *:

for (int i = 0; s[i] != '\0'; i++)
    if (strchr("aeiou", s[i]) != NULL) s[i] = '*';

Textul informatica devine *nf*rm*t*c*. O variantă des întâlnită: fiecare literă se înlocuiește cu cea care urmează în alfabet, iar 'z' cu 'a'. Formula generală, pentru o deplasare cu k poziții (cifrul lui Cezar), este s[i] = (s[i] - 'a' + k) % 26 + 'a'. Pentru k = 1, 'c' devine 'd' și 'z' devine 'a', pentru că (25 + 1) % 26 = 0.

5. Ștergerea caracterelor: tehnica cu doi indici

Când ștergi caractere, șirul se scurtează. În loc să deplasezi tot restul șirului la fiecare ștergere, folosești un al doilea indice k, care arată unde scrii următorul caracter păstrat:

int k = 0;
for (int i = 0; s[i] != '\0'; i++)
    if (strchr("aeiou", s[i]) == NULL)
        s[k++] = s[i];
s[k] = '\0';

Pentru bacalaureat rămân doar consoanele: bclrt. Fiecare caracter e citit o singură dată și copiat cel mult o dată, deci algoritmul e liniar. Nu uita linia s[k] = '\0': fără ea, șirul ar păstra la final caracterele vechi.

6. Inserarea: construiești un șir nou

Dacă trebuie să adaugi caractere (de exemplu, să dublezi fiecare vocală), cel mai sigur este să construiești rezultatul într-un șir separat, suficient de mare:

char r[201];
int k = 0;
for (int i = 0; s[i] != '\0'; i++)
{
    r[k++] = s[i];
    if (strchr("aeiou", s[i]) != NULL) r[k++] = s[i];
}
r[k] = '\0';

Pentru bac rezultatul este baac. Dacă s are cel mult 100 de caractere, r poate ajunge la 200, plus terminatorul — de aici dimensiunea 201.

7. Înlocuirea unei secvențe cu alta

Cea mai „grea” dintre cerințele clasice: fiecare apariție a secvenței x în text se înlocuiește cu secvența y, care poate avea altă lungime. Folosești strstr pentru a găsi aparițiile și construiești rezultatul pe bucăți: partea dinaintea apariției, apoi y, apoi continui după apariție.

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char s[101], x[21], y[21], rez[256] = "";
    cin.getline(s, 101);
    cin.getline(x, 21);
    cin.getline(y, 21);
    char *p = s, *q = strstr(p, x);
    while (q != NULL)
    {
        strncat(rez, p, q - p);   // copiez ce e înainte de apariție
        strcat(rez, y);           // pun înlocuitorul
        p = q + strlen(x);        // continui după apariție
        q = strstr(p, x);
    }
    strcat(rez, p);               // restul textului
    cout << rez;
    return 0;
}

Pentru textul abracadabra, x = bra și y = *, se afișează a*cada*. Avantajul acestei scheme: nu modifici șirul original și nu riști să găsești din nou secvența în textul deja înlocuit (de exemplu, dacă y conține x).

La BAC: când cerința spune „modificați șirul în memorie și afișați-l”, poți folosi un șir auxiliar și apoi să-l copiezi înapoi cu strcpy(s, rez). Contează ca șirul s să conțină rezultatul corect la final, iar codul să fie clar.

Cum combini piesele

Aproape orice cerință e o compunere: „afișați cuvintele palindrom din text, transformate în majuscule” înseamnă strtok + funcția palindrom + transformarea literelor. Scrie fiecare operație separat (chiar ca subprogram, dacă enunțul permite) și apoi leagă-le. Codul rezultat e mai ușor de verificat — și de tine, și de corector.

De reținut