Comparaison std :: string (vérifiez si la chaîne commence par une autre chaîne)

90

Je dois vérifier si un std: string commence par "xyz". Comment le faire sans chercher dans toute la chaîne ou créer des chaînes temporaires avec substr ().

jackhab
la source

Réponses:

164

J'utiliserais la méthode de comparaison:

std::string s("xyzblahblah");
std::string t("xyz")

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
Wacek
la source
3
Pourquoi n'utilisez-vous pas simplement s.compare (t)?
Franck Mesirard
5
@FranckMesirard: C'est parce que, par défaut, comparer essaierait de comparer la longueur entière de la chaîne passée aux données du membre et renverrait false, tandis que donner la longueur comme la longueur du paramètre passé le ferait retourner true (ce qui signifie std :: basic_string :: compare , lorsqu'il est utilisé avec offset & length, peut être utilisé comme String.BeginsWith () dans d'autres bibliothèques.) Sans l'offset et la longueur, ce ne serait pas vrai.
legends2k
1
Cela renvoie vrai si t est vide.
gliderkite
14
@gliderkite Comme il se doit ... la chaîne vide est un préfixe initial de chaque chaîne.
Jim Balter
1
Comme il se doit, c'est correct ... Si vous voulez exclure les chaînes vides: if (! T.empty () &&! S.compare (0, t.length (), t))
ericcurtin
14

Une approche qui pourrait être plus conforme à l'esprit de la bibliothèque standard serait de définir votre propre algorithme begin_with.

#include <algorithm>
using namespace std;


template<class TContainer>
bool begins_with(const TContainer& input, const TContainer& match)
{
    return input.size() >= match.size()
        && equal(match.begin(), match.end(), input.begin());
}

Cela fournit une interface plus simple au code client et est compatible avec la plupart des conteneurs de bibliothèque standard.

Neutrino
la source
Cool! Cela devrait être ajouté pour booster!
David
2
@David: Si boost est une dépendance autorisée, voir boost :: algorithm :: starts_with - 'Starts with' predicate
Gabor
10

Regardez la bibliothèque String Algo de Boost , qui a un certain nombre de fonctions utiles, telles que starts_with, istart_with (insensible à la casse), etc. seulement les fichiers nécessaires

Alex Ott
la source
4

Il semble que std :: string :: starts_with soit dans C ++ 20, tandis que std :: string :: find peut être utilisé

std::string s1("xyzblahblah");
std::string s2("xyz")

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
Alejadro Xalabarder
la source
1
C'est bien mieux que la réponse acceptée std::string::comparecar elle permet de vérifier facilement si la chaîne commence par un littéral sans répéter le littéral lui-même pour trouver sa taille. Et merci d'avoir indiqué la solution directe C ++ 20.
Ruslan
Si s1 ne commence pas par s2, cela essaiera toujours de le faire correspondre par la suite, ce qui n'est pas aussi bon que compare ().
A117 du
0

Je sens que je ne comprends pas entièrement votre question. Il semble que cela devrait être trivial:

s[0]=='x' && s[1]=='y' && s[2]=='z'

Cela ne regarde (au plus) que les trois premiers caractères. La généralisation d'une chaîne inconnue au moment de la compilation vous obligerait à remplacer ce qui précède par une boucle:

// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
  if (s[i]!=t[i])
    return false;
}
1800 INFORMATIONS
la source
Eh bien, je sais comment comparer des chaînes en utilisant les fonctions C. Ma question portait sur le faire de manière orientée objet au moyen de C ++ STL.
jackhab
Aucune fonction C n'est utilisée ici. Et la bibliothèque standard ne vous empêche pas d'écrire vos propres fonctions.
6
et si t est plus court que s?
vidstige du
@jackhab L'auteur de STL dit que "STL n'est pas orienté objet. Je pense que l'orientation objet est presque autant un canular que l'intelligence artificielle." - stlport.org/resources/StepanovUSA.html
Jim Balter
1
@vidstige Ensuite, la boucle se termine lorsqu'elle rencontre le NUL de fin dans t.
Jim Balter