Obtener el último elemento de un std :: string

87

Me preguntaba si hay una abreviatura o una forma más elegante de obtener el último carácter de una cadena como en:

char lastChar = myString.at( myString.length() - 1 );

Algo como myString.back()no parece existir. ¿Existe un equivalente?

Deve
fuente
Creo que no es necesario, porque puedes hacerlo con bastante facilidad con las funciones proporcionadas.
Hoàng Long
4
Ese argumento también se aplicaría a las clases de contenedores.
Deve

Respuestas:

129

En C ++ 11 y posteriores, puede usar la backfunción miembro:

char ch = myStr.back();

En C ++ 03, std::string::backno está disponible debido a un descuido, pero puede evitar esto eliminando la referencia de lo reverse_iteratorque obtiene rbegin:

char ch = *myStr.rbegin();

En ambos casos, asegúrese de que la cadena tenga al menos un carácter. De lo contrario, obtendrá un comportamiento indefinido , lo cual es algo malo.

¡Espero que esto ayude!

templatetypedef
fuente
13
se ha agregado una función back () en C ++ 11
eddi
1
@ eddi- ¡Gracias por señalarlo! Actualicé mi respuesta en consecuencia.
templatetypedef
Nota: Tuve que forzar la compilación de g ++ --std=c++11para back()que estuviera disponible.
JulianHarty
@JulianHarty Eso es cierto para la mayoría de las características de C ++ 11, creo. :-)
templatetypedef
22

Probablemente desee verificar primero la longitud de la cadena y hacer algo como esto:

if (!myStr.empty())
{
    char lastChar = *myStr.rbegin();
}
Kerri Brown
fuente
2
No tienes que comprobar la longitud. Si es la cadena vacía, simplemente obtiene '\ 0' almacenado en lastChar.
Mark Loeser
4
@MarkLoeser: Eso no es cierto. *myStr.end()no es lo mismo que myStr[myStr.size()]! E, incluso si lo fuera, myStr.rbegin()es equivalente a myStr.end()-1, que es claramente inválido en una cadena vacía.
Lightness Races in Orbit
7

Podría escribir una plantilla de función backque delegue a la función miembro para contenedores ordinarios y una función normal que implemente la funcionalidad faltante para cadenas:

template <typename C>
typename C::reference back(C& container)
{
    return container.back();
}

template <typename C>
typename C::const_reference back(const C& container)
{
    return container.back();
}

char& back(std::string& str)
{
    return *(str.end() - 1);
}

char back(const std::string& str)
{
    return *(str.end() - 1);
}

Entonces puede decir back(foo)sin preocuparse si fooes una cadena o un vector.

fredoverflow
fuente
2

*(myString.end() - 1)¿tal vez? Eso tampoco es exactamente elegante.

Un pitón-esque myString.at(-1)estaría pidiendo demasiado de una clase ya hinchada.

tenpn
fuente