Vérifiez si une chaîne contient une chaîne en C ++

494

J'ai une variable de type std::string. Je veux vérifier s'il en contient un certain std::string. Comment ferais-je ça?

Existe-t-il une fonction qui renvoie true si la chaîne est trouvée et false si elle ne l'est pas?

neuromancien
la source
6
Voulez-vous dire chaîne char * ou la chaîne de la STL?
anthares
1
Ce n'est pas une chaîne char *. J'ai dû # inclure <chaîne> pour l'utiliser.
neuromancien
1
Certaines des solutions utilisent s2 pour la chaîne que je veux trouver. Cela fonctionnera-t-il toujours si j'utilise quelque chose comme "c'est une chaîne" au lieu de s2?
neuromancien
2
Oui car il existe un constructeur littéral de chaîne pour le type std :: string.
18
Quelqu'un s'il vous plaît faire une proposition à ajouter std::basic_string::containsau stdlib.
emlai

Réponses:

723

Utilisez std::string::findcomme suit:

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

Remarque: "trouvé!" sera imprimé si s2est une sous-chaîne de s1, les deux s1et s2sont de type std::string.

Guy Avraham
la source
117

Vous pouvez essayer d'utiliser la findfonction:

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

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

En fait, vous pouvez essayer d'utiliser la bibliothèque boost, je pense que std :: string ne fournit pas suffisamment de méthode pour effectuer toutes les opérations de chaîne courantes. Dans boost, vous pouvez simplement utiliser 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;
}
Geng Jiawen
la source
33
"Je pense que std :: string ne fournit pas assez de méthode pour faire toutes les opérations de chaîne courantes". Mais il existe une findméthode pour exactement la tâche en question. Pas besoin d'introduire une dépendance de bibliothèque.
Stefan
8
@stefan, vous avez raison, il existe une méthode de recherche, mais qu'en est-il de fractionner, remplacer et de nombreux autres membres du personnel.Vous pouvez comparer std :: string à l'api de chaîne en Java.PS:Aussi, je pense que contient est beaucoup plus élégant que trouver pour vérifier si une chaîne contient une autre chaîne.
Geng Jiawen
1
C'est aussi court et plus facile à mémoriser. Cpp 17 a un support supplémentaire pour le système de fichiers. J'espère que Cpp 2x fera aussi quelque chose pour la chaîne. Il est très douloureux de ne pas prendre en charge la méthode de base des chaînes dans les cpp modernes.
Geng Jiawen
1
Avez-vous vraiment besoin des "utilisations"? Quand je lis ce code, je n'ai aucune idée si containsc'est std::containsou boost::contains, ce qui semble être un inconvénient important. Je suppose que std :: contains n'existe pas actuellement, mais je ne suis pas sûr qu'il soit raisonnable de supposer que le lecteur a mémorisé tout ce qui est dans std. Et std::containspourrait très bien exister dans une future version de c ++, qui casserait ce programme.
Don Hatch
12

Vous pouvez essayer ceci

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

Dans le cas où la fonctionnalité est critique pour votre système, il est en fait avantageux d'utiliser une ancienne strstrméthode. La std::searchméthode au seinalgorithm est la plus lente possible. Je suppose que cela prend beaucoup de temps pour créer ces itérateurs.

Le code que j'ai utilisé pour chronométrer le tout est

#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;
}

Ici, je génère au hasard haystackset recherche en eux leneedle . Le nombre de meules de foin est défini, mais la longueur des chaînes dans chaque meule de foin est augmentée de 10 au début à 10240 à la fin. La plupart du temps, le programme passe à générer des chaînes aléatoires, mais il faut s'y attendre.

La sortie est:

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.
v010dya
la source
La version courte de la réponse est: utiliser c au lieu de c ++ :)
r0ng
3

Si vous ne souhaitez pas utiliser les fonctions de bibliothèque standard, voici une solution.

#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;
}
Testing123
la source
6
Vous utilisez déjà std :: string, donc votre code dépend déjà de std lib. Je ne vois vraiment aucune raison pour éviter la solution acceptée en utilisant std :: string :: find.
b00n12
Ouais, c'est un bon point. Je ne pensais pas ça quand j'ai écrit ça. Je suppose que ce que je pensais quand j'ai écrit c'était peut-être comment éviter d'utiliser std :: find.
Testing123
3
Juste pour les futurs visiteurs: cet algorithme n'est pas réellement correct. Parce que "i" ne revient jamais après une correspondance de sous-chaîne ayant échoué, certains cas ne sont pas mis en correspondance, par exemple, considérez: aaabc, aab
sAm_vdP
1
Cela a plusieurs bugs. CheckSubstring(std::string firstString, std::string secondString)deep copie les deux chaînes passées à la fonction, ce qui est coûteux, en particulier pour les chaînes plus longues qui nécessitent des allocations de tas. De plus, dites que vous appelez CheckSubstring("XYZab", "ab\0\0")- la whileboucle finira comparer aà a, bà b, l'NUL implicite à la fin de la première chaîne à la NUL explicite dans la seconde, il va lire au - delà de la mémoire tampon de la première chaîne, ayant un comportement non défini. Pour corriger, utilisez for (... i <= firstString.size () - secondString (). Size (); ...) '.
Tony Delroy
1

Si la taille des chaînes est relativement grande (des centaines d'octets ou plus) et que c ++ 17 est disponible, vous pouvez utiliser le moteur de recherche Boyer-Moore-Horspool (exemple de 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";
}
Konstantin Stupnik
la source
3
Les signes des temps. Autrefois, quelqu'un aurait offert une fonction bool contains(const std::string& haystack, const std::string& needle). De nos jours, ils offrent un ensemble de pièces de puzzle nommées d'après des auteurs obscurs de papiers obscurs pour le faire ressembler davantage à l'informatique ...
BitTickler
0

Vous pouvez également utiliser l'espace de noms System. Ensuite, vous pouvez utiliser la méthode contains.

#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";
    }
}
Malindu Dilanka
la source
Cette réponse ne s'applique qu'à l'extension C ++ propriétaire de Microsoft, soit C ++ / CX ou C ++ / CLI
H. Al-Amri
1
ouais, je suis désolé, je ne savais pas que ça fonctionne comme ça jusqu'à un jour après l'avoir posté.
Malindu Dilanka
-1

Ceci est une fonction simple

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;
}
neda
la source
4
Bonjour, bienvenue à SO. Pourriez-vous s'il vous plaît modifier votre réponse et ajouter un commentaire sur la façon dont cela fonctionne et en quoi il diffère des autres réponses? Je vous remercie!
Fabio dit Réintégrer Monica
-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;
}
zaonline
la source
11
S'il vous plaît essayez d'éviter de simplement vider le code comme réponse et essayez d'expliquer ce qu'il fait et pourquoi. Votre code peut ne pas être évident pour les personnes qui n'ont pas l'expérience de codage appropriée. Veuillez modifier votre réponse pour inclure des clarifications, du contexte et essayer de mentionner toute limitation, hypothèse ou simplification dans votre réponse.
Sᴀᴍ Onᴇᴌᴀ
Merci d'avoir rendu le code clair, de l'utiliser usingavec uniquement les fonctions requises et de ne pas vider tout l'espace de noms dans l'espace global. Quant au commentaire @ SᴀᴍOnᴇᴌᴀ, je suppose que l'utilisateur n'a pas lu les commentaires dans votre code.
v010dya
-2

À partir de tant de réponses sur ce site, je n'ai pas trouvé de réponse claire, alors en 5-10 minutes, j'ai moi-même trouvé la réponse. Mais cela peut se faire dans deux cas:

  1. Soit vous SAVEZ la position de la sous-chaîne que vous recherchez dans la chaîne
  2. Soit vous ne connaissez pas la position et la recherchez, caractère par caractère ...

Supposons donc que nous recherchons la sous-chaîne "cd" dans la chaîne "abcde", et que nous utilisons la fonction intégrée de substr la plus simple en C ++

pour une:

#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;
}

pour 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;
}
user7655194
la source
2
En quoi la première réponse ("use std :: string :: find"), publiée 8 ans plus tôt, n'était-elle pas assez claire?
Steve Smith
-3

Nous pouvons utiliser cette méthode à la place. Juste un exemple de mes projets. Référez-vous au code. Certains extras sont également inclus.

Regardez les instructions 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";
        }
    }

}
Malindu Dilanka
la source
Je suis désolé, je n'ai pas vu que quelqu'un a posté la même chose que moi auparavant.
Malindu Dilanka
1
"S'abonner à moi sur YouTube" peut être considéré comme du spam. Veuillez garder cela à l'esprit à l'avenir. Lisez aussi Comment répondre et comment ne pas être un spammeur
Zoe