Удалить последний символ из строки 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.substr(0, st.size()-1). Но она по- прежнему не выглядит правильно, я думаю , что правильный способ заключается в использовании функции , которая предназначена для решения этой задачи, она называется Стирание () и код: st.erase(st.size()-1). Это будет называться "мутантной версией".
Чаре Томчак

1
@CzarekTomczak: я понимаю, что это не совсем то, о чем просили, таким образом, отказ от ответственности перед фактической сущностью.
Матье М.

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

404

Простое решение, если вы используете C ++ 11. Вероятно, O (1) время:

st.pop_back();

49
это для с ++ 11!
Амир

1
Как FYI - он поддерживается только из GCC 4.7 (конечно, вместе с переключателем компиляции -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 :: erase хороша, но мне нравится "- 1" (независимо от размера или конечного итератора) - для меня это помогает выразить намерение.

Кстати, действительно ли нет std :: string :: pop_back? - кажется странным.


11
Нет std::string::pop_backв C ++ 03; это было добавлено в C ++ 0x, хотя.
Джеймс МакНеллис

Хорошо, спасибо. Это вызвало некоторую путаницу - я могу поклясться, что использовал это, но его там нет. Возможно, у меня где-то есть нестандартная библиотека в каком-то компиляторе (между VC ++ 2003, VC ++ 2008, MinGW GCC3, MinGW GCC 4 и Linux GCC 4, у вас есть несколько отличий). Скорее всего, я просто путаюсь с другими типами.
Steve314

resize (), вероятно, не предназначен для такого использования, это функция, связанная с памятью, erase () предназначена для удаления символов.
Чаре Томчак

3
@Czarek Tomczak - извините за абсурдно поздний ответ, но resizeэто функция изменения размера, и больше не функция памяти, как все, что может увеличить необходимую память. Например, если вы resizeуменьшите размер, это не уменьшит зарезервированную память. Я думаю, вы думаете о том reserve, что, по крайней мере, может уменьшить объем выделяемой памяти, если будет предложено - см. Здесь изменить размер и зарезервировать здесь .
Steve314

3
if (! str.empty ()) предпочтительнее размера
ericcurtin

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

Это предполагает, что вы знаете, что строка не пуста. Если это так, вы получите out_of_rangeисключение.


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

Нил прав. Я, наверное, должен был уточнить это в своем ответе. Второй параметр будет эффективно изменять значение последнего символа, поэтому он не будет печататься, но длина строки останется прежней. Использование erase фактически «удаляет» последний символ и изменит размер строки.
RC.

@RC Будет напечатано, если вы используете что-то вроде cout << buf. Как это будет выглядеть, будет зависеть от вашей платформы. И вы всегда можете уточнить, отредактировав свой ответ.

Что гораздо лучше о size() вместо end()другого ответа?
Рибамар

17

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

Ссылка: std :: string :: erase () прототип 2

не требуется c ++ 11 или c ++ 0x.


1
Это может привести к странной ситуации: размер строки был уменьшен, но последний символ не установлен в '\ 0'.
Deqing

1
@Deqing, можешь ли ты рассказать подробнее о том, что происходит в таком случае?
Рибамар

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

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

9
int main () {

  string str1="123";
  string str2 = str1.substr (0,str1.length()-1);

  cout<<str2; // output: 12

  return 0;
}

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 не может быть преобразован в normal_iterator.

C ++ 11 в этом случае ваш друг.


Этот метод также имеет проблемы, последний символ не установлен в '\ 0'.
Deqing

1
Любая конкретная причина не делать str.erase(str.end() - 1)?
vallentin

-4

Если длина не равна нулю, вы также можете

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

4
Установка последнего символа в \0не меняет длину строки. str.length()будет неточным.
jww

Да, я вижу это сейчас. Мы рассматриваем C ++. Вы правы, это не меняет длину строки
Ян Глейзер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.