Récupère le dernier élément d'un std :: string

87

Je me demandais s'il y avait une abréviation ou une manière plus élégante d'obtenir le dernier caractère d'une chaîne comme dans:

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

Quelque chose comme myString.back()ça ne semble pas exister. Y a-t-il un équivalent?

Deve
la source
Je pense que ce n'est pas nécessaire, car vous pouvez le faire assez facilement avec les fonctions fournies.
Hoàng Long
4
Cet argument vaut également pour les classes de conteneurs.
Deve

Réponses:

129

Dans C ++ 11 et au-delà, vous pouvez utiliser la backfonction membre:

char ch = myStr.back();

En C ++ 03, std::string::backn'est pas disponible en raison d'un oubli, mais vous pouvez contourner ce problème en déréférençant le point de reverse_iteratorretour de rbegin:

char ch = *myStr.rbegin();

Dans les deux cas, veillez à vous assurer que la chaîne contient au moins un caractère! Sinon, vous obtiendrez un comportement non défini , ce qui est une mauvaise chose.

J'espère que cela t'aides!

templatetypedef
la source
13
une fonction back () a été ajoutée en C ++ 11
eddi
1
@ eddi- Merci de l'avoir signalé! J'ai mis à jour ma réponse en conséquence.
templatetypedef
Remarque: j'ai dû forcer g ++ à compiler avec --std=c++11pour back()être disponible.
JulianHarty
@JulianHarty C'est vrai pour la plupart des fonctionnalités C ++ 11, je crois. :-)
templatetypedef
22

Vous voudrez probablement vérifier d'abord la longueur de la chaîne et faire quelque chose comme ceci:

if (!myStr.empty())
{
    char lastChar = *myStr.rbegin();
}
Kerri Brown
la source
2
Vous n'êtes pas obligé de vérifier la longueur. Si c'est la chaîne vide, vous obtenez simplement '\ 0' stocké dans lastChar.
Mark Loeser
4
@MarkLoeser: Ce n'est pas vrai. *myStr.end()n'est pas la même chose que myStr[myStr.size()]! Et, même si c'était le cas, myStr.rbegin()équivaut à myStr.end()-1, ce qui est clairement invalide sur une chaîne vide.
Courses de légèreté en orbite
7

Vous pouvez écrire un modèle de fonction backqui délègue à la fonction membre pour les conteneurs ordinaires et une fonction normale qui implémente la fonctionnalité manquante pour les chaînes:

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

Ensuite, vous pouvez simplement dire back(foo)sans vous soucier s'il foos'agit d'une chaîne ou d'un vecteur.

fredoverflow
la source
2

*(myString.end() - 1)peut être? Ce n'est pas vraiment élégant non plus.

Un python-esque myString.at(-1)demanderait trop à une classe déjà gonflée.

tenpn
la source