way strings comparing best c++ string-comparison prefix

c++ - strings - Compruebe si una cadena es un prefijo de otra



string== string c++ (12)

Tengo dos cadenas que me gustaría comparar: String y String: ¿Hay alguna función de biblioteca que devuelva verdadero al pasar estas dos cadenas, pero falso para decir String y OtherString ?

Para ser precisos, quiero saber si una cadena es un prefijo de otra.


¿Qué pasa con el "buscar" y verificar el resultado para la posición 0?

string a = "String"; string b = "String:"; if(b.find(a) == 0) { // Prefix } else { // No Prefix }


¿Qué tal simplemente?

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 ++ no C, seguro, simple, eficiente.

Probado con:

#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; }


Con string::compare , debería poder escribir algo como:

bool match = (0==s1.compare(0, min(s1.length(), s2.length()), s2,0,min(s1.length(),s2.length())));

Alternativamente, en caso de que no deseemos usar la función de miembro length() :

bool isPrefix(string const& s1, string const&s2) { const char*p = s1.c_str(); const char*q = s2.c_str(); while (*p&&*q) if (*p++!=*q++) return false; return true; }


Creo que strncmp es lo más cercano a lo que estás buscando.

Sin embargo, si se reformula, puede estar buscando strstr(s2,s1)==s2 , que no es necesariamente la forma más eficaz de hacerlo. Pero no quieres entrenar n ;-)

De acuerdo, está bien, la versión de c ++ sería !s1.find(s2) .

Bueno, puedes hacerlo aún más c ++, algo como esto: std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end() .


Esto es eficiente y conveniente:

a.size() >= b.size() && a.compare(0, b.size(), b) == 0

Con std::string , la operación de size es de costo cero, y compare utiliza el método de traits::compare rápidos traits::compare .

Tenga en cuenta que sin la comparación de tamaño, compare solo no es suficiente porque compara solo caracteres a.size() y "xyz" sería un prefijo de "xy" .


La manera más fácil es usar las funciones de miembro substr () y compare () :

string str = "Foobar"; string prefix = "Foo"; if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";


Puedes usar esto:

para c ++ 14 o menos

bool has_prefix (std::string str, std::string prefix) { return str.find(prefix, 0) == 0; }

para 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; }


Si sabe qué cadena es más corta, el procedimiento es simple, solo use std::equal con la cadena más corta primero. Si no lo hace, algo como lo siguiente debería funcionar:

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


Use std::mismatch . Pase la secuencia más corta como el primer rango de iterador y la más larga como el segundo rango de iterador. El retorno es un par de iteradores, el primero es el iterador en el primer rango y el segundo, en el segundo rage. Si el primero es el final del primer rango, entonces usted sabe que la cadena corta es el prefijo de la cadena más larga, por ejemplo

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


str1.find (str2) devuelve 0 si se encuentra str2 completo en el índice 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; }

Salida:

str2 starts with str1 str3 does not start with str1 one is prefix of another one is not prefix of another


std::string(X).find(Y) es cero si y solo si Y es un prefijo de X


Si puede ignorar razonablemente cualquier codificación de varios bytes (por ejemplo, UTF-8), entonces puede usar strncmp para esto:

// 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 insiste en usar una versión elegante de C ++, puede usar el algoritmo std::equal (con el beneficio adicional de que su función también funciona para otras colecciones, no solo para cadenas):

// 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() ); }