std :: comparación de cadenas (compruebe si la cadena comienza con otra cadena)

90

Necesito comprobar si una cadena std: comienza con "xyz". ¿Cómo lo hago sin buscar en toda la cadena o crear cadenas temporales con substr ()?

Jackhab
fuente

Respuestas:

164

Usaría el método de comparación:

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

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
Wacek
fuente
3
¿Por qué no usa simplemente s.compare (t)?
Franck Mesirard
5
@FranckMesirard: Eso es porque, por defecto, la comparación intentaría comparar la longitud completa de la cadena pasada con los datos del miembro y devolvería falso, mientras que dar la longitud como la longitud del parámetro pasado lo haría devolver verdadero (es decir, std :: basic_string :: compare , cuando se usa con offset & length, se puede usar como String.BeginsWith () en otras bibliotecas). Sin el offset y la longitud, esto no sería cierto.
legends2k
1
Esto devuelve verdadero si t está vacío.
Gliderkite
14
@gliderkite Como debería ... la cadena vacía es un prefijo inicial de cada cadena.
Jim Balter
1
Como debería, es correcto ... Si desea descartar cadenas vacías: if (! T.empty () &&! S.compare (0, t.length (), t))
ericcurtin
14

Un enfoque que podría estar más en consonancia con el espíritu de la biblioteca estándar sería definir su propio algoritmo starts_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());
}

Esto proporciona una interfaz más sencilla para el código del cliente y es compatible con la mayoría de los contenedores de la biblioteca estándar.

Neutrino
fuente
¡Frio! ¡Esto debería agregarse para impulsar!
David
2
@David: Si boost es una dependencia permitida, vea boost :: algorítm :: starts_with - predicado 'Empieza con'
Gabor
10

Busque la biblioteca String Algo de Boost , que tiene una serie de funciones útiles, como starts_with, istart_with (no distingue entre mayúsculas y minúsculas), etc. Si desea utilizar solo una parte de las bibliotecas boost en su proyecto, puede usar la utilidad bcp para copiar solo archivos necesarios

Alex Ott
fuente
4

Parece que std :: string :: starts_with está dentro de C ++ 20, mientras que std :: string :: find se puede usar

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

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
Alejadro Xalabarder
fuente
1
Esto es mucho mejor que el uso de la respuesta aceptada std::string::compareporque facilita verificar si la cadena comienza con un literal sin repetir el literal en sí para encontrar su tamaño. Y gracias por señalar la solución directa C ++ 20.
Ruslan
Si s1 no comienza con s2, este intentará igualarlo después, lo que no es tan bueno como compare ().
A117
0

Siento que no entiendo completamente su pregunta. Parece que debería ser trivial:

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

Esto solo mira (como máximo) los primeros tres caracteres. La generalización para una cadena que se desconoce en el momento de la compilación requeriría que reemplace lo anterior con un bucle:

// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
  if (s[i]!=t[i])
    return false;
}
1800 INFORMACIÓN
fuente
Bueno, sé cómo comparar cadenas al usar funciones C. Mi pregunta era sobre cómo hacerlo de forma orientada a objetos mediante C ++ STL.
jackhab
Aquí no se utiliza ninguna función de C. Y la biblioteca estándar no le impide escribir sus propias unciones.
6
y ¿qué pasa si t es más corto que s?
vidstige
@jackhab El autor de STL dice "STL no está orientado a objetos. Creo que la orientación a objetos es casi tan engañosa como la Inteligencia Artificial". - stlport.org/resources/StepanovUSA.html
Jim Balter
1
@vidstige Luego, el bucle termina cuando encuentra el NUL de terminación en t.
Jim Balter