J'ai deux chaînes que j'aimerais comparer: String
et String:
. Existe-t-il une fonction de bibliothèque qui renvoie true lorsque ces deux chaînes sont passées, mais false pour say String
et OtherString
Pour être précis, je veux savoir si une chaîne est un préfixe d'une autre.
Utilisez std::mismatch
. Passez la chaîne la plus courte en tant que premier intervalle d'itérateur et la plus longue en tant que deuxième intervalle d'itérateur. Le retour consiste en une paire d'itérateurs, le premier est l'itérateur dans la première plage et le second, dans la deuxième. Si le premier est la fin de la première plage, alors vous savez que la chaîne courte est le préfixe de la chaîne la plus longue, par exemple.
std::string foo("foo");
std::string foobar("foobar");
auto res = std::mismatch(foo.begin(), foo.end(), foobar.begin());
if (res.first == foo.end())
{
// foo is a prefix of foobar.
}
Si vous savez quelle chaîne est plus courte, la procédure est simple, utilisez simplement std::equal
avec la chaîne la plus courte en premier. Si vous ne le faites pas, quelque chose comme ceci devrait fonctionner:
bool
unorderIsPrefix( std::string const& lhs, std::string const& rhs )
{
return std::equal(
lhs.begin(),
lhs.begin() + std::min( lhs.size(), rhs.size() ),
rhs.begin() );
}
std::string(X).find(Y)
est zéro si et seulement si Y
est un préfixe de X
Pourquoi pas simplement:
bool prefix(const std::string& a, const std::string& b) {
if (a.size() > b.size()) {
return a.substr(0,b.size()) == b;
}
else {
return b.substr(0,a.size()) == a;
}
}
C++ pas C, sûr, simple, efficace.
Testé avec:
#include <string>
#include <iostream>
bool prefix(const std::string& a, const std::string& b);
int main() {
const std::string t1 = "test";
const std::string t2 = "testing";
const std::string t3 = "hello";
const std::string t4 = "hello world";
std::cout << prefix(t1,t2) << "," << prefix(t2,t1) << std::endl;
std::cout << prefix(t3,t4) << "," << prefix(t4,t3) << std::endl;
std::cout << prefix(t1,t4) << "," << prefix(t4,t1) << std::endl;
std::cout << prefix(t1,t3) << "," << prefix(t3,t1) << std::endl;
}
Si vous pouvez raisonnablement ignorer tous les codages sur plusieurs octets (par exemple, UTF-8), vous pouvez utiliser strncmp
pour cela:
// Yields true if the string 's' starts with the string 't'.
bool startsWith( const std::string &s, const std::string &t )
{
return strncmp( s.c_str(), t.c_str(), t.size() ) == 0;
}
Si vous insistez pour utiliser une version C++ sophistiquée, vous pouvez utiliser l'algorithme std::equal
(avec l'avantage supplémentaire que votre fonction fonctionne également pour d'autres collections, pas seulement des chaînes):
// Yields true if the string 's' starts with the string 't'.
template <class T>
bool startsWith( const T &s, const T &t )
{
return s.size() >= t.size() &&
std::equal( t.begin(), t.end(), s.begin() );
}
C'est à la fois efficace et pratique:
a.size() >= b.size() && a.compare(0, b.size(), b) == 0
Avec std::string
, l'opération size
est sans coût et compare
utilise la méthode rapide traits::compare
.
Notez que sans la comparaison de taille, compare
seul n'est pas suffisant car il ne compare que les caractères a.size()
et "xyz"
serait un préfixe de "xy"
.
Le moyen le plus simple est d’utiliser les fonctions substr () et compare () member:
string str = "Foobar";
string prefix = "Foo";
if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";
Vous pouvez utiliser ceci:
pour c ++ 14 ou moins
bool has_prefix
(std::string str, std::string prefix) {
return str.find(prefix, 0) == 0;
}
pour c ++ 17
//is much faster
auto has_prefix
(std::string str, std::string_view prefix) -> decltype(str.find(prefix) == 0) {
return str.find(prefix, 0) == 0;
}
str1.find (str2) renvoie 0 si toute la str2 est trouvée à l'index 0 de str1:
#include <string>
#include <iostream>
// does str1 have str2 as prefix?
bool StartsWith(const std::string& str1, const std::string& str2)
{
return (str1.find(str2)) ? false : true;
}
// is one of the strings prefix of the another?
bool IsOnePrefixOfAnother(const std::string& str1, const std::string& str2)
{
return (str1.find(str2) && str2.find(str1)) ? false : true;
}
int main()
{
std::string str1("String");
std::string str2("String:");
std::string str3("OtherString");
if(StartsWith(str2, str1))
{
std::cout << "str2 starts with str1" << std::endl;
}
else
{
std::cout << "str2 does not start with str1" << std::endl;
}
if(StartsWith(str3, str1))
{
std::cout << "str3 starts with str1" << std::endl;
}
else
{
std::cout << "str3 does not start with str1" << std::endl;
}
if(IsOnePrefixOfAnother(str2, str1))
{
std::cout << "one is prefix of another" << std::endl;
}
else
{
std::cout << "one is not prefix of another" << std::endl;
}
if(IsOnePrefixOfAnother(str3, str1))
{
std::cout << "one is prefix of another" << std::endl;
}
else
{
std::cout << "one is not prefix of another" << std::endl;
}
return 0;
}
Sortie:
str2 starts with str1
str3 does not start with str1
one is prefix of another
one is not prefix of another
Je pense que strncmp
est le plus proche de ce que vous recherchez.
Cependant, si reformulé, vous pouvez rechercher strstr(s2,s1)==s2
, ce qui n’est pas nécessairement le moyen le plus efficace de le faire. Mais vous ne voulez pas travailler n
;-)
D'accord, d'accord, la version c ++ serait !s1.find(s2)
.
OK, vous pouvez le rendre encore plus c ++, quelque chose comme ceci: std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end()
.
Quel est le problème avec la "recherche" et la vérification du résultat pour la position 0?
string a = "String";
string b = "String:";
if(b.find(a) == 0)
{
// Prefix
}
else
{
// No Prefix
}