Controlla se una stringa contiene una stringa in C ++


494

Ho una variabile di tipo std::string. Voglio verificare se contiene un certo std::string. Come potrei farlo?

Esiste una funzione che restituisce true se viene trovata la stringa e false se non lo è?


6
Intendi char * string o la stringa da STL?
Anthares,

1
Non è una stringa char *. Ho dovuto #includere <stringa> per usarlo.
neuromante il

1
Alcune delle soluzioni stanno usando s2 per la stringa che voglio trovare. Funzionerà comunque se uso qualcosa come "this is a string" anziché s2?
neuromante il

2
Sì, perché esiste un costruttore di stringhe per il tipo std :: string.

18
Qualcuno, per favore, fai una proposta da aggiungere std::basic_string::containsallo stdlib.
emlai,

Risposte:


723

Utilizzare std::string::findcome segue:

if (s1.find(s2) != std::string::npos) {
    std::cout << "found!" << '\n';
}

Nota: "trovato!" verrà stampato se s2è una sottostringa di s1, entrambi s1e s2sono di tipo std::string.


117

Puoi provare a usare la findfunzione:

string str ("There are two needles in this haystack.");
string str2 ("needle");

if (str.find(str2) != string::npos) {
//.. found.
} 

27

In realtà, puoi provare a utilizzare la libreria boost, penso che std :: string non fornisca un metodo sufficiente per eseguire tutte le operazioni di stringa comuni. In boost, puoi semplicemente usare boost::algorithm::contains:

#include <string>
#include <boost/algorithm/string.hpp>

int main() {
    std::string s("gengjiawen");
    std::string t("geng");
    bool b = boost::algorithm::contains(s, t);
    std::cout << b << std::endl;
    return 0;
}

33
"Penso che std :: string non fornisca un metodo sufficiente per eseguire tutte le operazioni di stringa comuni". Ma esiste un findmetodo esattamente per l'attività in questione. Non è necessario introdurre una dipendenza dalla libreria.
stefan,

8
@stefan, hai ragione, esiste un metodo find, ma che ne dici di dividere, sostituire e molti altri membri dello staff. Puoi confrontare std :: string con la stringa api in Java.PS: Penso anche che contenga sia molto più elegante di trova per verificare se una stringa contiene un'altra stringa.
Geng Jiawen,

1
Anche questo è breve e più facile da ricordare. Cpp 17 ha aggiunto il supporto per il filesystem. Spero che Cpp 2x faccia qualcosa anche per le stringhe. È molto dolorosa la mancanza del supporto del metodo di stringa di base nel cpp moderno.
Geng Jiawen,

1
Hai davvero bisogno delle "usings"? Quando leggo questo codice, non ho idea se containssia std::containso boost::contains, che sembra un inconveniente significativo. Immagino che std :: contiene non esiste attualmente, ma non sono sicuro che sia ragionevole supporre che il lettore abbia memorizzato tutto ciò che è in std. E std::containspotrebbe benissimo esistere in qualche versione futura di c ++, che romperebbe questo programma.
Don Hatch,

12

Puoi provare questo

string s1 = "Hello";
string s2 = "el";
if(strstr(s1.c_str(),s2.c_str()))
{
   cout << " S1 Contains S2";
}

4

Nel caso in cui la funzionalità sia fondamentale per il tuo sistema, è effettivamente utile utilizzare un vecchio strstrmetodo. Il std::searchmetodo all'interno algorithmè il più lento possibile. La mia ipotesi sarebbe che ci vuole molto tempo per creare quegli iteratori.

Il codice che ho usato per cronometrare è tutto

#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <random>
#include <chrono>

std::string randomString( size_t len );

int main(int argc, char* argv[])
{
        using namespace std::chrono;

        const size_t haystacksCount = 200000;
        std::string haystacks[haystacksCount];
        std::string needle = "hello";

        bool sink = true;

        high_resolution_clock::time_point start, end;
        duration<double> timespan;

        int sizes[10] = { 10, 20, 40, 80, 160, 320, 640, 1280, 5120, 10240 };

        for(int s=0; s<10; ++s)
        {
                std::cout << std::endl << "Generating " << haystacksCount << " random haystacks of size " << sizes[s] << std::endl;
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        haystacks[i] = randomString(sizes[s]);
                }

                std::cout << "Starting std::string.find approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(haystacks[i].find(needle) != std::string::npos)
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting strstr approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(strstr(haystacks[i].c_str(), needle.c_str()))
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting std::search approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(std::search(haystacks[i].begin(), haystacks[i].end(), needle.begin(), needle.end()) != haystacks[i].end())
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
        }

        return 0;
}

std::string randomString( size_t len)
{
        static const char charset[] = "abcdefghijklmnopqrstuvwxyz";
        static const int charsetLen = sizeof(charset) - 1;
        static std::default_random_engine rng(std::random_device{}());
        static std::uniform_int_distribution<> dist(0, charsetLen);
        auto randChar = [charset, &dist, &rng]() -> char
        {
                return charset[ dist(rng) ];
        };

        std::string result(len, 0);
        std::generate_n(result.begin(), len, randChar);
        return result;
}

Qui genera casuale haystackse cerco in essi il needle. Il conteggio del pagliaio è impostato, ma la lunghezza delle stringhe all'interno di ciascun pagliaio è aumentata da 10 all'inizio a 10240 alla fine. Il più delle volte il programma trascorre effettivamente a generare stringhe casuali, ma è prevedibile.

L'output è:

Generating 200000 random haystacks of size 10
Starting std::string.find approach
Processing of 200000 elements took 0.00358503 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0022727 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0346258 seconds.

Generating 200000 random haystacks of size 20
Starting std::string.find approach
Processing of 200000 elements took 0.00480959 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00236199 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0586416 seconds.

Generating 200000 random haystacks of size 40
Starting std::string.find approach
Processing of 200000 elements took 0.0082571 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00341435 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0952996 seconds.

Generating 200000 random haystacks of size 80
Starting std::string.find approach
Processing of 200000 elements took 0.0148288 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00399263 seconds.
Starting std::search approach
Processing of 200000 elements took 0.175945 seconds.

Generating 200000 random haystacks of size 160
Starting std::string.find approach
Processing of 200000 elements took 0.0293496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00504251 seconds.
Starting std::search approach
Processing of 200000 elements took 0.343452 seconds.

Generating 200000 random haystacks of size 320
Starting std::string.find approach
Processing of 200000 elements took 0.0522893 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00850485 seconds.
Starting std::search approach
Processing of 200000 elements took 0.64133 seconds.

Generating 200000 random haystacks of size 640
Starting std::string.find approach
Processing of 200000 elements took 0.102082 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00925799 seconds.
Starting std::search approach
Processing of 200000 elements took 1.26321 seconds.

Generating 200000 random haystacks of size 1280
Starting std::string.find approach
Processing of 200000 elements took 0.208057 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0105039 seconds.
Starting std::search approach
Processing of 200000 elements took 2.57404 seconds.

Generating 200000 random haystacks of size 5120
Starting std::string.find approach
Processing of 200000 elements took 0.798496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0137969 seconds.
Starting std::search approach
Processing of 200000 elements took 10.3573 seconds.

Generating 200000 random haystacks of size 10240
Starting std::string.find approach
Processing of 200000 elements took 1.58171 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0143111 seconds.
Starting std::search approach
Processing of 200000 elements took 20.4163 seconds.

La versione più breve della risposta è: usando c invece di c ++ :)
r0ng

3

Se non si desidera utilizzare le funzioni di libreria standard, di seguito è riportata una soluzione.

#include <iostream>
#include <string>

bool CheckSubstring(std::string firstString, std::string secondString){
    if(secondString.size() > firstString.size())
        return false;

    for (int i = 0; i < firstString.size(); i++){
        int j = 0;
        // If the first characters match
        if(firstString[i] == secondString[j]){
            int k = i;
            while (firstString[i] == secondString[j] && j < secondString.size()){
                j++;
                i++;
            }
            if (j == secondString.size())
                return true;
            else // Re-initialize i to its original value
                i = k;
        }
    }
    return false;
}

int main(){
    std::string firstString, secondString;

    std::cout << "Enter first string:";
    std::getline(std::cin, firstString);

    std::cout << "Enter second string:";
    std::getline(std::cin, secondString);

    if(CheckSubstring(firstString, secondString))
        std::cout << "Second string is a substring of the frist string.\n";
    else
        std::cout << "Second string is not a substring of the first string.\n";

    return 0;
}

6
Stai già usando std :: string, quindi il tuo codice dipende già da std lib. Non vedo alcun motivo per evitare la soluzione accettata usando std :: string :: find.
b00n12

Sì, è un buon punto. Non pensavo che quando ho scritto questo. Immagino che cosa ho pensato quando ho scritto questo fosse forse come evitare di usare std :: find.
Test123 del

3
Solo per i futuri visitatori: questo algoritmo non è in realtà corretto. Poiché "i" non torna più indietro dopo una corrispondenza di sottostringa non riuscita, alcuni casi non vengono associati, ad esempio si consideri: aaabc, aab
sAm_vdP

1
Questo ha diversi bug. CheckSubstring(std::string firstString, std::string secondString)copia in profondità entrambe le stringhe passate alla funzione, che è costosa, in particolare per le stringhe più lunghe che richiedono allocazioni di heap. Inoltre, diciamo che si chiama CheckSubstring("XYZab", "ab\0\0")- il whileciclo finirà il confronto aa a, ba b, il NUL implicita alla fine della prima stringa alla NUL esplicita nel secondo, poi si leggerà al di là del buffer della prima stringa, avendo un comportamento indefinito. Per correggere usare for (... i <= firstString.size () - secondString (). Size (); ...) `.
Tony Delroy,

1

Se la dimensione delle stringhe è relativamente grande (centinaia di byte o più) e c ++ 17 è disponibile, potresti voler utilizzare il cercatore Boyer-Moore-Horspool (esempio da cppreference.com):

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

int main()
{
    std::string in = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
                     " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
    std::string needle = "pisci";
    auto it = std::search(in.begin(), in.end(),
                   std::boyer_moore_searcher(
                       needle.begin(), needle.end()));
    if(it != in.end())
        std::cout << "The string " << needle << " found at offset "
                  << it - in.begin() << '\n';
    else
        std::cout << "The string " << needle << " not found\n";
}

3
I segni dei tempi. Ai vecchi tempi qualcuno avrebbe offerto una funzione bool contains(const std::string& haystack, const std::string& needle). Oggi offrono una serie di pezzi del puzzle che prendono il nome da alcuni oscuri autori di documenti oscuri per renderlo più simile all'informatica ...
BitTickler

0

È inoltre possibile utilizzare lo spazio dei nomi di sistema. Quindi è possibile utilizzare il metodo contiene.

#include <iostream>
using namespace System;

int main(){
    String ^ wholeString = "My name is Malindu";

    if(wholeString->ToLower()->Contains("malindu")){
        std::cout<<"Found";
    }
    else{
        std::cout<<"Not Found";
    }
}

Questa risposta si applica solo all'estensione C ++ proprietaria di Microsoft C ++ / CX o C ++ / CLI
H. Al-Amri,

1
sì, mi dispiace, non sapevo che funzionasse in questo modo solo un giorno dopo averlo pubblicato.
Malindu Dilanka,

-1

Questa è una funzione semplice

bool find(string line, string sWord)
{
    bool flag = false;
    int index = 0, i, helper = 0;
    for (i = 0; i < line.size(); i++)
    {
        if (sWord.at(index) == line.at(i))
        {
            if (flag == false)
            {
                flag = true;
                helper = i;
            }
            index++;
        }
        else
        {
            flag = false;
            index = 0;
        }
        if (index == sWord.size())
        {
            break;
        }
    }
    if ((i+1-helper) == index)
    {
        return true;
    }
    return false;
}

4
Ciao, benvenuto in SO. Potresti modificare la tua risposta e aggiungere un commento su come funziona e come differisce dalle altre risposte? Grazie!
Fabio dice di reintegrare Monica il

-1
#include <algorithm>        // std::search
#include <string>
using std::search; using std::count; using std::string;

int main() {
    string mystring = "The needle in the haystack";
    string str = "needle";
    string::const_iterator it;
    it = search(mystring.begin(), mystring.end(), 
                str.begin(), str.end()) != mystring.end();

    // if string is found... returns iterator to str's first element in mystring
    // if string is not found... returns iterator to mystring.end()

if (it != mystring.end())
    // string is found
else
    // not found

return 0;
}

11
Prova a evitare di scaricare il codice come risposta e prova a spiegare cosa fa e perché. Il tuo codice potrebbe non essere ovvio per le persone che non hanno l'esperienza di programmazione pertinente. Modifica la tua risposta per includere chiarimenti, contesto e prova a menzionare eventuali limiti, ipotesi o semplificazioni nella tua risposta.
Sᴀᴍ Onᴇᴌᴀ

Grazie per chiarire il codice, per l'utilizzo usingcon solo le funzioni richieste e per non scaricare l'intero spazio dei nomi nello spazio globale. Per quanto riguarda il commento @ SᴀᴍOnᴇᴌᴀ, suppongo che l'utente non abbia letto i commenti nel tuo codice.
v010dya,

-2

Da così tante risposte in questo sito non ho trovato una risposta chiara, quindi in 5-10 minuti ho capito da solo la risposta. Ma questo può essere fatto in due casi:

  1. O CONOSCI la posizione della sottostringa che cerchi nella stringa
  2. O non conosci la posizione e la cerchi, carattere per carattere ...

Supponiamo quindi che cerchiamo la sottostringa "cd" nella stringa "abcde" e utilizziamo la funzione incorporata del substr più semplice in C ++

per 1:

#include <iostream>
#include <string>

    using namespace std;
int i;

int main()
{
    string a = "abcde";
    string b = a.substr(2,2);    // 2 will be c. Why? because we start counting from 0 in a string, not from 1.

    cout << "substring of a is: " << b << endl;
    return 0;
}

per 2:

#include <iostream>
#include <string>

using namespace std;
int i;

int main()
{
    string a = "abcde";

    for (i=0;i<a.length(); i++)
    {
        if (a.substr(i,2) == "cd")
        {
        cout << "substring of a is: " << a.substr(i,2) << endl;    // i will iterate from 0 to 5 and will display the substring only when the condition is fullfilled 
        }
    }
    return 0;
}

2
In che modo la risposta migliore ("usa std :: string :: find"), pubblicata 8 anni prima, non era abbastanza chiara?
Steve Smith,

-3

Possiamo usare questo metodo invece. Solo un esempio dai miei progetti. Fare riferimento al codice. Sono inclusi anche alcuni extra.

Guarda le dichiarazioni if!

/*
Every C++ program should have an entry point. Usually, this is the main function.
Every C++ Statement ends with a ';' (semi-colon)
But, pre-processor statements do not have ';'s at end.
Also, every console program can be ended using "cin.get();" statement, so that the console won't exit instantly.
*/

#include <string>
#include <bits/stdc++.h> //Can Use instead of iostream. Also should be included to use the transform function.

using namespace std;
int main(){ //The main function. This runs first in every program.

    string input;

    while(input!="exit"){
        cin>>input;
        transform(input.begin(),input.end(),input.begin(),::tolower); //Converts to lowercase.

        if(input.find("name") != std::string::npos){ //Gets a boolean value regarding the availability of the said text.
            cout<<"My Name is AI \n";
        }

        if(input.find("age") != std::string::npos){
            cout<<"My Age is 2 minutes \n";
        }
    }

}

Mi dispiace, non ho visto che qualcuno ha pubblicato la stessa cosa che ho fatto in precedenza.
Malindu Dilanka,

1
"Iscriviti a me su YouTube" può essere considerato spam. Per favore, tienilo a mente in futuro. Leggi anche Come rispondere e come non essere uno spammer
Zoe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.