„Se citește un text de cel mult 100 de caractere, în care cuvintele sunt formate din litere mici ale alfabetului englez și sunt separate prin câte un spațiu…” — dacă ai rezolvat subiecte de BAC informatică, ai recunoscut deja începutul. Problemele cu cuvinte dintr-un text revin constant, iar în C++ ai două instrumente pentru ele: funcția strtok și parcurgerea manuală, caracter cu caracter. Fiecare are situațiile în care e alegerea bună.

Separarea cuvintelor cu strtok

strtok(s, sep) din <cstring> împarte șirul s în bucăți (numite token-uri), folosind ca separatori oricare dintre caracterele din sep. Se folosește în două feluri:

Când nu mai sunt cuvinte, returnează NULL. Schema completă, care afișează fiecare cuvânt pe câte o linie și le numără:

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

int main()
{
    char s[101];
    cin.getline(s, 101);
    int nr = 0;
    char *p = strtok(s, " ");
    while (p != NULL)
    {
        cout << p << '\n';
        nr++;
        p = strtok(NULL, " ");
    }
    cout << nr;
    return 0;
}

Pentru textul ana are mere se afișează „ana”, „are”, „mere” pe linii separate, apoi 3. Dacă textul conține și semne de punctuație, le pui în lista de separatori: strtok(s, " .,;!?"). Un avantaj în plus: strtok tratează corect și separatorii consecutivi (două spații la rând nu produc un cuvânt vid).

Ce face strtok „în spate”

strtok modifică șirul original: înlocuiește separatorul de după fiecare cuvânt cu '\0' și returnează adresa începutului de cuvânt. După ce ai terminat, în s a rămas doar primul cuvânt (dacă îl afișezi, vezi „ana”). De aceea:

Construirea unui text nou din cuvinte

Cerință tipică: „Afișați textul obținut prin eliminarea cuvintelor care au mai puțin de 4 litere. Dacă nu rămâne niciun cuvânt, afișați mesajul nu exista.” Cu strtok iei fiecare cuvânt, iar pe cele bune le lipești cu strcat într-un șir rezultat, inițial vid:

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

int main()
{
    char s[101], rez[101] = "";
    cin.getline(s, 101);
    char *p = strtok(s, " ");
    while (p != NULL)
    {
        if (strlen(p) >= 4)
        {
            if (rez[0] != '\0') strcat(rez, " ");
            strcat(rez, p);
        }
        p = strtok(NULL, " ");
    }
    if (rez[0] == '\0') cout << "nu exista";
    else cout << rez;
    return 0;
}

Pentru la bac avem doar trei ore se afișează avem doar trei. Observă testul rez[0] != '\0': pune spațiul doar între cuvinte, nu și înaintea primului. E un detaliu pe care corectorii îl văd imediat.

Parcurgerea manuală: când strtok nu e potrivit

Dacă trebuie să modifici cuvintele în interiorul textului (să le inversezi, să schimbi prima literă, să dublezi o vocală), e mai simplu să parcurgi șirul caracter cu caracter. Ideea de bază: un caracter s[i] este începutul unui cuvânt dacă nu e spațiu și fie e pe poziția 0, fie înaintea lui e un spațiu.

for (i = 0; s[i] != '\0'; i++)
    if (s[i] != ' ' && (i == 0 || s[i - 1] == ' '))
        s[i] = s[i] - 'a' + 'A';

Secvența transformă prima literă a fiecărui cuvânt în majusculă: ana are mere devine Ana Are Mere. Analog, s[i] este sfârșitul unui cuvânt dacă nu e spațiu și după el urmează un spațiu sau '\0'.

Inversarea fiecărui cuvânt pe loc

Combinând cele două idei, găsești pentru fiecare cuvânt poziția de început st și de sfârșit dr, apoi interschimbi literele din capete spre mijloc:

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

int main()
{
    char s[101];
    cin.getline(s, 101);
    int n = strlen(s), i = 0, st, dr;
    while (i < n)
    {
        while (i < n && s[i] == ' ') i++;   // sar peste spații
        st = i;
        while (i < n && s[i] != ' ') i++;   // merg până la finalul cuvântului
        dr = i - 1;
        while (st < dr)
        {
            char aux = s[st];
            s[st] = s[dr];
            s[dr] = aux;
            st++;
            dr--;
        }
    }
    cout << s;
    return 0;
}

Pentru bac la info se afișează cab al ofni. Spațiile rămân exact unde erau, pentru că lucrăm direct în șirul original. Urmărește un caz-limită: dacă textul se termină cu spațiu, după ultimul cuvânt st devine n, dr devine n−1, condiția st < dr e falsă și nu se întâmplă nimic — programul rămâne corect.

Cuvântul cel mai lung și alte cerințe clasice

Cu strtok, majoritatea cerințelor se reduc la o prelucrare a lui p în interiorul buclei:

La BAC: citește cu atenție ce garantează enunțul — „separate prin câte un spațiu”, „fără spații la început și la sfârșit”, „doar litere mici”. Aceste garanții îți simplifică programul, iar corectorii nu cer tratarea unor cazuri pe care enunțul le exclude. Folosește-le, dar nu presupune nimic în plus.

strtok sau parcurgere manuală?

SituațieAlegerea potrivită
Afișezi, numeri sau selectezi cuvintestrtok
Construiești un text nou din unele cuvintestrtok + strcat
Modifici literele cuvintelor în textparcurgere manuală
Ai nevoie și de textul inițial după prelucrareparcurgere manuală sau strtok pe o copie

De reținut