MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Căutarea unui subșir

Funcția find() returnează indexul primei apariții a unui subșir sau a unui caracter în șir, ca o valoare de tip size_t:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::cout << text.find("ed") << std::endl;      // 14
    std::cout << text.find("friend") << std::endl;  // 2
    std::cout << text.find('d') << std::endl;     // 7
    std::cout << text.find("apple") << std::endl;  // 18446744073709551615
}

Dacă șirul sau caracterul nu este găsit (ca în ultimul exemplu de mai sus), se returnează constanta specială std::string::npos, care reprezintă un număr foarte mare (după cum se vede în exemplu: 18446744073709551615). La căutare, putem verifica dacă rezultatul funcției find() este egal cu această constantă:

if (text.find("banana") == std::string::npos)
{
    std::cout << "Not found" << std::endl;
}

Funcția find are mai multe versiuni. De exemplu, al doilea parametru poate specifica indexul de la care începe căutarea:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    // căutare de la indexul 10
    std::cout << text.find("friend", 10) << std::endl;      // 22
}

Folosind această versiune, putem scrie un program care numără aparițiile unui cuvânt într-un text:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"friend"};
    unsigned count{};       // numărul aparițiilor
    for (unsigned i {}; i <= text.length() - word.length(); )
    {
        // obținem indexul
        size_t position = text.find(word, i);
        // dacă nu există nicio apariție de la indexul i, ieșim din ciclu
        if (position == std::string::npos) break;
        // dacă apariția a fost găsită, incrementăm contorul
        ++count;
        // trecem la următorul index după position
        i = position + 1;
    }
    std::cout << "The word is found " << count << " times." << std::endl; // The word is found 2 times.
}

Aici, în buclă, parcurgem textul în care trebuie să găsim cuvântul, până când contorul i ajunge la text.length() - word.length(). Cu ajutorul funcției find() obținem indexul primei apariții a cuvântului în text, începând de la indexul i. Dacă nu sunt găsite apariții, ieșim din buclă. Dacă este găsit un index, i este actualizat la poziția de după apariție.

Rezultatul este că, deoarece cuvântul „friend” apare de două ori în text, programul va afișa:

The word is found 2 times.

Alternativ, am putea folosi o buclă while:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"friend"};
    unsigned count{};       // numărul aparițiilor
    size_t index{}; // indexul de start
    while ((index = text.find(word, index)) != std::string::npos)
    {
        ++count;
        index += word.length(); // deplasăm indexul după sfârșitul cuvântului
    }
    std::cout << "The word is found " << count << " times." << std::endl;
}

O altă versiune permite căutarea doar a unei părți a șirului. Ca al treilea parametru, se transmite numărul de caractere din șirul căutat care vor fi luate în considerare:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"endless"};
    // căutare de la indexul 10, pentru primele 3 caractere ale cuvântului "endless", adică "end"
    std::cout << text.find("endless", 10, 3) << std::endl;      // 25
}

Este important de menționat că, în acest caz, șirul căutat trebuie să fie un literal de șir sau un șir în stil C (de exemplu, un tablou de caractere terminat cu \0).

Funcția rfind. Căutare în ordine inversă

Funcția rfind() funcționează similar cu find(), acceptă aceiași parametri, dar caută subșirul în ordine inversă – de la sfârșitul șirului:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::cout << text.rfind("ed") << std::endl;      // 33
    std::cout << text.rfind("friend") << std::endl; // 22
    std::cout << text.rfind('d') << std::endl;     // 34
    std::cout << text.rfind("apple") << std::endl;  // 18446744073709551615
}

Căutarea oricărui caracter dintr-un set

Perechea de funcții find_first_of() și find_last_of() permite găsirea, respectiv, a primului și a ultimului index al oricărui caracter dintr-un set:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"Phone number: +23415678901"};
    std::string letters{"0123456789"};  // caracterele căutate
    std::cout << text.find_first_of(letters) << std::endl;      // 15
    std::cout << text.find_last_of(letters) << std::endl;      // 25
}

În acest caz căutăm în șirul "Phone number: +23415678901" prima și ultima poziție a oricărui caracter din "0123456789". Astfel, obținem începutul și sfârșitul numărului de telefon.

Dacă dorim să găsim pozițiile caracterelor care nu sunt dintr-un set, putem folosi funcțiile find_first_not_of() (prima poziție) și find_last_not_of() (ultima poziție):

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"Phone number: +23415678901"};
    std::string letters{"0123456789"};  // caractere căutate
    std::cout << text.find_first_not_of(letters) << std::endl;      // 0
    std::cout << text.find_last_not_of(letters) << std::endl;       // 14
}

Putem combina funcțiile. De exemplu, să găsim numărul de cuvinte într-un șir:

#include <iostream>
#include <string>
 
int main()
{
    std::string text {"When in Rome, do as the Romans do."};    // textul inițial
    const std::string separators{ " ,;:.\"!?'*\n" }; // separatori de cuvinte
    unsigned count{};   // contor de cuvinte
    size_t start { text.find_first_not_of(separators) }; // indexul de început al primului cuvânt
    while (start != std::string::npos) // dacă am găsit un cuvânt
    {
        // incrementăm contorul de cuvinte
        count++;
        size_t end = text.find_first_of(separators, start + 1); // găsim unde se termină cuvântul
        if (end == std::string::npos) 
        {
            end = text.length();
        }
        start = text.find_first_not_of(separators, end + 1); // găsim indexul următorului cuvânt și actualizăm start
    }
    // afișăm numărul de cuvinte
    std::cout << "Text contains " << count << " words" << std::endl;    // Text contains 8 words
}

Pe scurt, să analizăm acest cod. Ca text în care vom număra cuvintele, definim variabila text. De asemenea, definim un șir de separatori, cum ar fi semne de punctuație, spații, caractere de linie nouă, care nu sunt considerate cuvinte:

const std::string separators{ " ,;:.\"!?'*\n" }; // separatori de cuvinte

Înainte de a procesa textul introdus, obținem indexul primului caracter al primului cuvânt din text. Pentru aceasta se folosește funcția find_first_not_of(), care returnează primul index al unui caracter care nu se află în separators:

size_t start { text.find_first_not_of(separators) };

Apoi, în bucla while, verificăm dacă indexul obținut este valid:

while (start != std::string::npos)

De exemplu, dacă șirul conține doar caractere din separators, atunci funcția find_first_not_of() va returna std::string::npos, ceea ce înseamnă că în text nu mai există caractere ce pot face parte din cuvinte.

Dacă start indică un index valid al începutului unui cuvânt, incrementăm contorul de cuvinte. Apoi căutăm indexul primului caracter din separators care vine imediat după cuvânt. Practic, acesta este indexul de după ultimul caracter al cuvântului, pe care îl stocăm în variabila end:

size_t end = text.find_first_of(separators, start + 1); // găsim unde s-a terminat cuvântul

Pentru a determina poziția de final a cuvântului, folosim funcția find_first_of(), care returnează prima poziție a oricărui caracter din separators, începând de la start + 1.

Poate apărea situația în care funcția find_first_of() nu găsește niciun caracter din separators (de exemplu, dacă ultimul cuvânt este la finalul textului și nu este urmat de semne de punctuație sau spații). În acest caz, indexul final va fi egal cu lungimea textului:

if (end == std::string::npos) // dacă NU este găsit niciun separator
    end = text.length();       // setăm end la finalul textului

După ce am determinat indexul de început și sfârșit al cuvântului, actualizăm start cu indexul de început al următorului cuvânt și repetăm pașii buclei:

start = text.find_first_not_of(separators, end + 1); // căutăm indexul următorului cuvânt și actualizăm start

La final, afișăm numărul de cuvinte găsite.