Удалить последний символ из строки C ++

210

Как я могу удалить последний символ из строки C ++?

Я пытался, st = substr(st.length()-1);но это не сработало.

skazhy
источник
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();
mpgaillard
источник
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? - кажется странным.

Steve314
источник
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исключение.

RC.
источник
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.

Ribamar
источник
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();
jcrv
источник
9
int main () {

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

  cout<<str2; // output: 12

  return 0;
}
codaddict
источник
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 ++. Вы правы, это не меняет длину строки
Ян Глейзер