web-dev-qa-db-fra.com

Rechercher si une chaîne contient un caractère en C++ (boost autorisé)

Supposons que j'ai une chaîne et que je veux savoir si un caractère spécifique (comme '|') est présent ou non, quelle est la technique la meilleure et la plus rapide pour le faire? Je sais que la chaîne trouve une implémentation. Je demande une implémentation encore plus rapide que celle-ci.

14
psyche

Utilisez std::string::find

if (str.find('|') != std::string::npos)
{
    // ...
}

Il y a peu de chances qu'il y ait quelque chose de plus efficace. O(n) est ce que vous pouvez faire de mieux. L'implémentation standard de la bibliothèque devrait être plutôt optimale.

30
Fred Larson

De this source le test empirique réalisé avec Visual Studio 2013 Compiler montre que la routine strchr est environ 2x plus rapide que l'implémentation std :: string :: find.

1
Mouze

Une autre méthode consiste à utiliser la fonction strchr sur la chaîne c_str correspondante:

if(strchr(str.c_str(), '|'))
{
    \\found
}

Je ne sais pas comment cela se compare à la recherche standard en termes de vitesse, bien que ...

La position du personnage trouvé est 

size_t pos = strchr(str.c_str(),'|') - str.c_str();
1
afakih

Ajoutant la réponse de Tom Tanner. Si vous ne souhaitez pas effectuer de calcul a priori, vous serez bloqué sur O (n), c’est-à-dire qu’il existe une corrélation linéaire entre la longueur de la chaîne recherchée et la consommation de temps. Tom suggéra de mettre en place un tableau (ou un vecteur) de booléens indiquant si un certain caractère se produisait. Il faudrait O(n) une fois pour indexer la chaîne, mais vous pouvez ensuite vérifier le nombre quelconque de caractères dans O(1) (temps constant), le cas échéant. L'inconvénient de cette approche est que vous aurez besoin de beaucoup de mémoire (une fois que vous aurez décidé de prendre en charge le format Unicode).

En guise de compromis, vous pouvez utiliser std :: set ou similaire, en ne stockant que les caractères existant dans votre chaîne d'entrée. La consommation de mémoire serait alors approximativement linéaire par rapport au nombre de caractères différents dans la chaîne mais la recherche serait O (log n), c’est-à-dire logarithmique dans le temps.

Bien sûr, vous devez mesurer/profiler, puis expliquer ici le cas d'utilisation que vous optimisez réellement. En attendant, gardez ce qui est le plus facile à comprendre et à lire.

1
Simon Schmeißer

Il n'y a qu'une seule façon de faire cela. Il suffit de parcourir la chaîne pour vérifier si le personnage que vous recherchez existe. Vous pouvez le faire en utilisant la fonction string::find, qui obtient un caractère et retourne la première position dans la chaîne, ou string::npos si la valeur n'est pas présente. Vous pouvez également utiliser std::find, qui obtient deux itérateurs, begin et end et une valeur de clé 'k', et renvoie un itérateur pointant vers la première occurrence de k dans la plage [begin, end] ou end si k n'a pas été trouvé. Et bien sûr, vous pouvez implémenter vous-même la fonction de recherche, comme ceci:

string::size_type pos=string::npos;
for(string::size_type i=0; i<s.size(); ++i) {
  if(s[i] == key) {
     pos=i;
     break;
  }
}
if(pos != string::npos) {
  // key was found
} else {
  // not found
}

ou ca:

string::iterator pos=s.end();
for(string::iterator i=s.begin(); i!=s.end(); ++i) {
  if(*i == key) {
    pos=i;
    break;
  }
}
if(pos != s.end()) {
  // found
} else {
  // not found
}

En savoir plus sur les std::string::find et std::find:

0

Vous pouvez essayer ceci:

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

Compte tenu de votre déclaration voulant que vous souhaitiez quelque chose de plus rapide que string :: find, la seule chose à laquelle je puisse penser serait de créer une classe dotée d'opérateurs d'affectation hautement personnalisés qui, à chaque mise à jour de la chaîne, mettrait à jour une table interne contenant la première position dans la chaîne de tous les caractères possibles (256 pour une chaîne de caractères, 65536 (?) pour une chaîne large). Ceci a O(1) recherché au prix de beaucoup de complexité ajoutée aux opérations non const.

0
Tom Tanner