从C ++字符串中删除最后一个字符


210

如何从C ++字符串中删除最后一个字符?

我尝试过,st = substr(st.length()-1);但是没有用。


6
您要删除最后一个字符的新字符串还是要删除最后一个字符的相同字符串?
Matthieu M. 2010年

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

Answers:


193

对于非变异版本:

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

20
@MatthieuM。您的示例令人困惑,我认为问题的实质是修改原始字符串,在您的示例中您并未修改原始字符串,因为在您的示例中原始字符串称为“ myString”,这会造成混淆,在问题上它是​​“ st”。您的代码应为:st = st.substr(0, st.size()-1)。但这仍然不是正确的方法,我认为正确的方法是使用要用于此任务的函数,该函数称为delete(),代码为:st.erase(st.size()-1)。这将被称为“变异版本”。
Czarek Tomczak 2013年

1
@CzarekTomczak:我知道这并不是要求的,因此在实际要旨之前免责声明。
Matthieu M.

2
@MattPhillips:尽管他的解决方案是C ++ 11特有的(pop_back在C ++ 03中不存在),但它也是就地修改(OP从未明确说明他是否想要就地)。这样,他有一个正确的答案,但不是唯一可能的答案。
Matthieu M.

404

如果使用的是C ++ 11,则为简单的解决方案。也可能是O(1)时间:

st.pop_back();

49
这是针对c ++ 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_backC ++ 03中没有。不过,它已在C ++ 0x中添加。
James McNellis

好,谢谢。这引起了一些混乱-我可以发誓我已经使用过它,但它还不存在。也许我在某个地方的某个编译器中有一个非标准库(在VC ++ 2003,VC ++ 2008,MinGW GCC3,MinGW GCC 4和Linux GCC 4之间,您确实会有一些区别)。更可能的是,我只是与其他类型混淆。
Steve314 2010年

resize()可能不适用于此类用途,它是与内存相关的函数,而delete()用于删除字符。
Czarek Tomczak 2013年

3
@Czarek Tomczak-很抱歉延迟答复,但它resize只是一个调整大小的函数,不再是其他任何可能增加所需内存的内存函数。例如,如果您resize较小,则不会减少保留的内存。我认为您正在考虑reserve,这至少可能会减少分配的内存(如果要求查看此处的大小此处保留)
Steve314 2014年

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()其他答案更好的了?
ribamar

17

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

参考:std :: string :: erase()原型2

不需要c ++ 11或c ++ 0x。


1
这可能会导致奇怪的情况:字符串的大小已减小,但最后一个字符未设置为'\ 0'。
德庆2014年

1
@Deqing您能否提供更多有关此类情况的详细信息?
ribamar 2014年

例如,如果您有string s("abc");擦除后似乎可以正常工作:cout<<s; // prints "ab",但是最后一个字符仍然存在:cout<<s[2]; // still prints 'c'
德庆2014年

1
容易解决的问题:公正str[str.length()-1] = 0; str.erase(str.end()-1);
出租车司机

5
@Dequing:您的示例无效。擦除会减小字符串的大小,因此访问s[2]是非法的。
EML,2015年

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'。
德庆2014年

1
有什么特殊原因不这样做str.erase(str.end() - 1)
vallentin

-4

如果长度不为零,也可以

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

4
将最后一个字符设置为\0不会更改字符串的长度。str.length()将不准确。
jww

是的,我现在看到了。我们正在考虑使用C ++。您是正确的,它不会更改字符串的长度
Jan Glaser
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.