web-dev-qa-db-fra.com

Vérifier si une chaîne est un préfixe d'une autre

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.

39
fredley

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.
}
48
Nim

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() );
}
17
James Kanze

std::string(X).find(Y) est zéro si et seulement si Y est un préfixe de X

14
MSalters

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;

}
5
Flexo

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() );
}
5
Frerich Raabe

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".

4
Neil Mayhew

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!";
2
user2180737

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;
}
1
john doe

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
0
Bojan Komazec

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
}
0
João Augusto