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 ()?

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
}

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.


¡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


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
}

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.