web-dev-qa-db-fra.com

comment vérifier le début de la chaîne en C ++

Existe-t-il un moyen en C++ de vérifier si une chaîne commence par une certaine chaîne (plus petite que l'original)? Tout comme nous pouvons le faire en Java

bigString.startswith(smallString);
48
sufyan siddique
std::string s("Hello world");

if (s.find("Hello") == 0)
{
    std::cout << "String starts with Hello\n";
}
80

Vous pouvez le faire avec string::compare(), qui offre diverses options pour comparer tout ou partie de deux chaînes. Cette version compare smallString avec le préfixe de taille approprié de bigString (et fonctionne correctement si bigString est plus court que smallString):

bigString.compare(0, smallString.length(), smallString) == 0

J'ai tendance à envelopper cela dans une fonction libre appelée startsWith(), car sinon cela peut sembler un peu mystérieux.

MISE À JOUR: C++ 20 ajoute nouvelles fonctions starts_with Et ends_with, Vous pourrez donc enfin écrire juste bigString.starts_with(smallString).

62
Alan Stokes

Les approches utilisant string::find() ou string::substr() ne sont pas optimales car elles font soit une copie de votre chaîne, soit recherchent plus de correspondances au début de la chaîne. Ce n'est peut-être pas un problème dans votre cas, mais si c'est le cas, vous pouvez utiliser le std::equal algorithme. N'oubliez pas de vérifier que la "botte de foin" est au moins aussi longue que l '"aiguille".

#include <string>    

using namespace std;

bool startsWith(const string& haystack, const string& needle) {
    return needle.length() <= haystack.length() 
        && equal(needle.begin(), needle.end(), haystack.begin());
}
30
Kleist

La solution correcte, comme toujours, vient de Boost: boost::algorithm::starts_with .

13
avakar

Pour optimiser un peu:

if ( smallString.size() <= bigString.size() &&
     strncmp( smallString.c_str(), bigString.c_str(), smallString.length() ) == 0 )

N'oubliez pas de #include <cstring> ou #include <string.h>

5
Borzh

Avec C++ 20, vous pouvez utiliser std::basic_string::starts_with (ou std::basic_string_view::starts_with ):

#include <string_view>

std::string_view bigString_v("Winter is gone"); // std::string_view avoids the copy in substr below.
std::string_view smallString_v("Winter");
if (bigString_v.starts_with(smallString_v))
{
    std::cout << "Westeros" << bigString_v.substr(smallString_v.size());
}
2
Roi Danton

L'approche la plus simple serait:

if ( smallString.size() <= bigString.size()
    && std::equals( smallString.begin(), smallString.end(), bigString.end() )

(Cela fonctionnera également si l'un des deux, ou les deux, est un vecteur. Ou tout autre type de conteneur standard.)

1
James Kanze

strstr() renvoie un pointeur sur la première occurrence d'une chaîne dans une chaîne.

0
rogerlsmith

J'ai pensé qu'il était logique de publier une solution brute qui n'utilise aucune fonction de bibliothèque ...

// Checks whether `str' starts with `start'
bool startsWith(const std::string& str, const std::string& start) {
    if (&start == &str) return true; // str and start are the same string
    if (start.length() > str.length()) return false;
    for (size_t i = 0; i < start.length(); ++i) {
        if (start[i] != str[i]) return false;
    }
    return true;
}

Ajout d'un simple std::tolower nous pouvons rendre ce cas insensible

// Checks whether `str' starts with `start' ignoring case
bool startsWithIgnoreCase(const std::string& str, const std::string& start) {
    if (&start == &str) return true; // str and start are the same string
    if (start.length() > str.length()) return false;
    for (size_t i = 0; i < start.length(); ++i) {
        if (std::tolower(start[i]) != std::tolower(str[i])) return false;
    }
    return true;
}
0
cute_ptr

Je suis surpris que personne n'ait encore publié cette méthode:

#include <string>    
using namespace std;

bool starts_with(const string& smaller_string, const string& bigger_string) 
{
    return (smaller_string == bigger_string.substr(0,smaller_string.length()));
}
0