Получить последний элемент std :: string

87

Мне было интересно, есть ли сокращение или более элегантный способ получить последний символ строки, например:

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

myString.back()Ничего подобного , похоже, не существует. Есть аналог?

Деве
источник
Я думаю, что в этом нет необходимости, потому что вы можете сделать это довольно легко с помощью предоставленных функций.
Hoàng Long
4
Этот аргумент применим и к классам-контейнерам.
Деве

Ответы:

129

В C ++ 11 и последующих версиях вы можете использовать backфункцию-член:

char ch = myStr.back();

В C ++ 03 std::string::backон недоступен из-за недосмотра, но вы можете обойти это, разыменовав reverse_iteratorвозвращаемое из rbegin:

char ch = *myStr.rbegin();

В обоих случаях убедитесь, что строка действительно содержит хотя бы один символ! В противном случае вы получите неопределенное поведение , а это плохо.

Надеюсь это поможет!

templatetypedef
источник
13
функция back () была добавлена ​​в C ++ 11
eddi
1
@ eddi: Спасибо, что указали на это! Я соответствующим образом обновил свой ответ.
templatetypedef
Примечание: Я должен был заставить г ++ для компиляции с --std=c++11для back()быть доступны.
JulianHarty
@JulianHarty Я считаю, что это верно для большинства функций C ++ 11. :-)
templatetypedef
22

Вероятно, вы захотите сначала проверить длину строки и сделать что-то вроде этого:

if (!myStr.empty())
{
    char lastChar = *myStr.rbegin();
}
Керри Браун
источник
2
Длину проверять не нужно. Если это пустая строка, вы просто сохраните '\ 0' в lastChar.
Марк Лозер,
4
@MarkLoeser: Это неправда. *myStr.end()не то же самое, что myStr[myStr.size()]! И даже если бы это было так, myStr.rbegin()эквивалентно myStr.end()-1, что явно недопустимо для пустой строки.
Lightness Races на орбите
7

Вы можете написать шаблон функции, backкоторый делегирует функцию-член для обычных контейнеров, и обычную функцию, которая реализует недостающую функциональность для строк:

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

Тогда вы можете просто сказать, back(foo)не беспокоясь, fooстрока это или вектор.

fredoverflow
источник
2

*(myString.end() - 1)может быть? Это тоже не совсем элегантно.

Питон-эск myString.at(-1)будет требовать слишком многого от уже раздутого класса.

tenpn
источник