Отримайте останній елемент std :: string


87

Мені було цікаво, чи існує скорочення або більш елегантний спосіб отримати останній символ рядка, як у:

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

Щось начебто myString.back()не існує. Чи існує еквівалент?


Я думаю, що це не потрібно, тому що ви можете зробити це досить легко за допомогою наданих функцій.
Хоанг Лонг

4
Цей аргумент мав би місце і для класів контейнерів.
Deve

Відповіді:


129

У C ++ 11 і пізніших версіях ви можете використовувати функцію- backчлен:

char ch = myStr.back();

У C ++ 03 std::string::backнедоступний через недогляд, але ви можете обійти це шляхом розмежування посилань, з яких reverse_iteratorви повертаєтесь rbegin:

char ch = *myStr.rbegin();

В обох випадках будьте обережні, щоб переконатися, що в рядку насправді є хоча б один символ! В іншому випадку ви отримаєте невизначену поведінку , а це погана річ.

Сподіваюся, це допомагає!


13
функція back () була додана в C ++ 11
Едді

1
@ eddi- Дякую, що вказав на це! Відповідно я оновив свою відповідь.
templatetypedef

Примітка: Я повинен був змусити г ++ для компіляції з --std=c++11для back()бути доступні.
JulianHarty

@JulianHarty Це вірно для більшості функцій C ++ 11, я вважаю. :-)
templatetypedef

22

Можливо, вам спочатку потрібно перевірити довжину рядка і зробити щось подібне:

if (!myStr.empty())
{
    char lastChar = *myStr.rbegin();
}

2
Не потрібно перевіряти довжину. Якщо це порожній рядок, ви просто отримуєте '\ 0', що зберігається в lastChar.
Mark Loeser

4
@MarkLoeser: Це неправда. *myStr.end()це не те саме, що myStr[myStr.size()]! І навіть якщо б це було, myStr.rbegin()це еквівалентно myStr.end()-1, що явно недійсне для порожнього рядка.
Гонки легкості на орбіті

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, це рядок чи вектор.


2

*(myString.end() - 1)можливо? Це теж не зовсім елегантно.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.