Видаліть останній символ із рядка C ++


210

Як я можу видалити останній символ із рядка C ++?

Я спробував, st = substr(st.length()-1);але це не вийшло.


6
Ви хочете, щоб нова рядок із останнім символом було видалено або той самий рядок без останнього символу?
Матьє М.

Для MFC Visual C ++ CString: CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
sergiol

Відповіді:


193

Для немутуючої версії:

st = myString.substr(0, myString.size()-1);

20
@MatthieuM. Ваш приклад заплутаний, я думаю, що суть питання полягає в тому, щоб змінити оригінальну рядок, у вашому прикладі ви не змінюєте початкову рядок, тому що у вашому прикладі оригінальна рядок називається "myString", що надає плутанину, у питанні це "st". Ваш код повинен бути: st = st.substr(0, st.size()-1). Але вона по- , як і раніше не виглядає правильно, я думаю , що правильний спосіб полягає у використанні функції , яка призначена для вирішення цього завдання, вона називається Стирання () і код: st.erase(st.size()-1). Це було б названо "мутаційною версією".
Czarek Tomczak

1
@CzarekTomczak: Я розумію, що це не саме те, про що просили, тому відмова від відповідальності перед фактичною суттю.
Матьє М.

2
@MattPhillips: його рішення є C ++ 11 конкретним, хоча ( pop_backне існувало в C ++ 03), і це також є модифікацією на місці (а ОП ніколи не уточнював, хотів він на місці чи ні) ... як Таким чином , він має більш правильну відповідь, але не можливо тільки один.
Матьє М.

404

Просте рішення, якщо ви використовуєте C ++ 11. Можливо, O (1) час:

st.pop_back();

49
це для c ++ 11!
Амір

1
Як FYI - його підтримують лише з GCC 4.7 (поза курсом по w / the -std = c ++ 11 компіляція)
Shmil The Cat

20
Не забудьте перевірити length().

Так, це здається занадто далеко вниз ..!
Джеймс Бедфорд

1
The behavior is undefined if the string is empty. від сюди
Раффі

24
if (str.size () > 0)  str.resize (str.size () - 1);

Альтернатива std :: стирання - це добре, але мені подобається "- 1" (на основі розміру чи кінцевого ітератора) - це допомагає виражати наміри.

BTW - Чи дійсно немає std :: string :: pop_back? - здається дивним.


11
В std::string::pop_backC ++ 03 немає; він доданий в C ++ 0x, хоча
Джеймс Мак-Нілліс

Добре, дякую. Це викликало трохи плутанини - я можу поклястись, що користувався ним, але його там немає. Можливо, у мене є десь нестандартна бібліотека в якомусь компіляторі (між VC ++ 2003, VC ++ 2008, MinGW GCC3 MinGW GCC 4 та Linux GCC 4, у вас є кілька відмінностей). Швидше за все, я просто плутаюсь з іншими типами.
Steve314

resize (), ймовірно, не призначений для такого використання, це функція, пов'язана з пам'яттю, erase () - для видалення символів.
Czarek Tomczak

3
@Czarek Tomczak - вибачте за абсурдно пізню відповідь, але resizeце функція зміни розміру, і не більше функції пам'яті, що нічого іншого, що може збільшити необхідну пам'ять. Наприклад, якщо ви resizeменшого розміру, це не зменшить зарезервовану пам'ять. Я думаю, ви думаєте про це reserve, що принаймні може зменшити виділену пам'ять, якщо вас попросять - дивіться розмір тут і резервуйте тут .
Steve314

3
якщо (! str.empty ()) віддається перевага над розміром
ericcurtin

19
buf.erase(buf.size() - 1);

Це передбачає, що ви знаєте, що рядок не порожній. Якщо так, ви отримаєте out_of_rangeвиняток.


8
buf [buf.size () - 1] = '\ 0'; нічого не видаляє - він просто змінює символ, який був там, щоб мати значення нуль. std:; рядки можуть із задоволенням містити таких символів.

Ніл правильно. Я, мабуть, мав би уточнити це у своїй відповіді. Другий варіант ефективно змінить значення останнього символу, щоб він не друкувався, але довжина рядка залишиться такою ж. Використання стирання фактично "видаляє" останній символ і змінить розмір рядка.
RC.

@RC Він надрукує, припускаючи, що ви використовуєте щось на зразок cout << buf. Як вона з’явиться, буде залежати від вашої платформи. І ви завжди можете уточнити, відредагувавши свою відповідь.

Що набагато кращого size() замість end()іншої відповіді?
рибамар

17

str.erase( str.end()-1 )

Довідка: std :: string :: прототип 2 erase ()

не потрібно c ++ 11 або c ++ 0x.


1
Це може призвести до дивної ситуації: розмір рядка був зменшений, але для останнього символу не встановлено значення "\ 0".
Декін

1
@Deqing чи можете ви детальніше розповісти про те, що відбувається в такому випадку?
рибамар

Наприклад , якщо ви string s("abc");, після того, як стирають здається працюють: cout<<s; // prints "ab", однак, останній символ ще є: cout<<s[2]; // still prints 'c'.
Декінг

1
легко виправлено: простоstr[str.length()-1] = 0; str.erase(str.end()-1);
таксілій

5
@Dequing: ваш приклад недійсний. Стирання зменшує розмір рядка, тому доступ до s[2]нього незаконний.
EML

11

Це все, що вам потрібно:

#include <string>  //string::pop_back & string::empty

if (!st.empty())
    st.pop_back();


2

З C ++ 11 вам навіть не потрібна довжина / розмір. Поки рядок не порожній, ви можете зробити наступне:

if (!st.empty())
  st.erase(std::prev(st.end())); // Erase element referred to by iterator one
                                 // before the end

2

str.erase(str.begin() + str.size() - 1)

str.erase(str.rbegin())не компілюється, на жаль, оскільки reverse_iteratorне може бути перетворений у звичайний_тератор.

C ++ 11 - ваш друг у цьому випадку.


У цього методу також є проблема, для останнього символу не встановлено значення "\ 0".
Декінг

1
Якась конкретна причина цього не робити str.erase(str.end() - 1)?
валентін

-4

Якщо довжина не дорівнює нулю, ви також можете

str[str.length() - 1] = '\0';

4
Встановлення останнього символу \0не змінює довжину рядка. str.length()буде неточним.
jww

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