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

345 阅读3分钟

C++字符串类有许多成员函数。其中两个是pop_back()和erase()函数。pop_back()函数从字符串中删除最后一个元素。erase()函数可以擦除字符串中的任何一个元素。erase函数有三个变体。它们的不同之处在于它们接受的参数的种类。这种同名的函数被称为重载函数。

C++字符串可以用两种主要方式声明:作为一个恒定的字符指针(array-of-char)或从字符串库的字符串类中实例化。这里,pop_back()和erase()函数是字符串对象的,从字符串类实例化出来。字符阵列的最后一个元素不能被删除,因为字符阵列不是一个实例化的对象。

字符串的字面意义是由字符的值组成的,这是真的。每个字符都在一个元素内。所以字符串字面意义实际上是由元素组成的。最后一个字符与它的最后一个元素一起被移除。

这篇文章解释了如何删除字符串的最后一个元素,以及它的字符。

文章内容

void pop_back()

这个字符串类的成员函数删除了字符串的最后一个元素。该函数返回void。这意味着没有任何东西从它那里返回,也没有任何变量可以接收从它那里返回的东西。这个函数的使用在下面的程序中得到了说明。

  #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "LMNOPQR";


        cout <<str <<endl;


        str.pop_back();


        for (int i=0; i<str.size(); i++)

            cout <<str[i];

        cout <<endl;


        return 0;

    }

输出结果是

 LMNOPQR

 LMNOPQ

最后一个字符已被删除。该程序的前两行包括了必要的库。当然,其中之一是字符串库。因为所有涉及的字符串都是从字符串类中实例化出来的,所以必须包括字符串库。下一行是一个声明。它声明下面的所有名字都属于标准名称空间,除非另有说明。

main()函数体以字符串对象的声明(实例化)开始。下一条语句在输出端显示这个新声明的字符串的字面意思。之后的语句使用pop_back()成员函数删除了最后一个字符。下一个代码段使用一个带有索引的for-loop来显示所有的字符,这些字符不再有最后一个,是一个连续的序列。

迭代器 erase(const_iterator p)

如果迭代器指向最后一个元素(字符),那么erase成员函数可以删除最后一个元素。该函数返回一个迭代器,该迭代器指向刚被删除的元素(或者刚被删除的元素是最后一个元素)。下面的程序说明了这一点。

 #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "LMNOPQR";


        cout <<str <<endl;


        string::iterator p = str.end();

        p--;


        string::iterator it = str.erase(p);


        for (int i=0; i<str.size(); i++)

            cout <<str[i];

        cout <<endl;


        return 0;

    }

输出结果是

 LMNOPQR

 LMNOPQ

该程序前三行的解释与前一个程序相同。在main()函数主体中,第一条语句声明了字符串对象。下一条语句在输出端显示这个新声明的字符串的字面意思。这个打印仍然可以用for-loop来完成。之后的语句获得一个迭代器,该迭代器正好指向最后一个字符元素之后。这是用成员函数end()完成的。注意迭代器的声明方式(=的左手边)。然后迭代器被递减以指向最后一个元素。

接下来,用成员函数erase()删除最后一个元素。下一个代码段使用一个带有索引的for-loop来显示所有的字符,这些字符在终端不再有最后一个字符,是一个连续的序列。

iterator erase(const_iterator first, const_iterator last)

这个成员函数将擦除字符串中的一系列字符元素。这里,first是一个迭代器,指向该范围的第一个元素。返回的迭代器指向刚才的元素,就在范围之后。如果那里没有元素,它将指向字符串的结尾。Last是一个迭代器,指向范围内的最后一个元素。这个最后一个元素不参与擦除工作。

要删除最后一个元素,诀窍是使 "last",刚好指向字符串的最后一个元素之外;并使 "first "指向字符串的最后一个元素。有了这一切,擦除函数就会去掉最后一个元素。下面的程序显示了它是如何完成的。

 #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "LMNOPQR";

        cout <<str <<endl;


        string::iterator p = str.begin();

        p = p + 6;

        string::iterator q = str.end();


        string::iterator it = str.erase(p, q);


        for (it = --it; it >= str.begin(); it--)

            cout << *it;

        cout <<endl;


        return 0;

    }

输出结果是

 LMNOPQR

 QPONML

在删除字符R(连同其元素)后,剩余的字符串被逐个打印,但顺序相反。

该程序的前三行的解释与前一个程序相同。在main()函数主体中,第一个语句声明了字符串对象。接下来的语句打印出新声明的字符串。

接下来的代码段有三个语句。第一条声明了一个迭代器,指向字符串的第一个字符。在到达最后一个字符'R'之前,必须再计算字符串的六个字符。因此,这一段的第二条语句在迭代器上增加了6。这一段的下一条语句声明了一个迭代器q,它正好指向字符串的结尾处。现在的情况是,擦除最后一个元素:q正好指向'R'之后,p指向'R'。

擦除'R'的语句是。

        string::iterator it = str.erase(p, q);

在'R'被擦除后,最后一个字符变成了'Q'。返回的迭代器,即这里的'it',正好指向'Q'之后。

接下来的代码段是一个for-loop。这个for-loop的初始化语句简单地递减了 "it",以指向新的最后一个字符,'Q'。Q "被打印到终端。当'it'大于str.begin()时,for-loop继续递减 "it",打印相应的字符。当 "it "等于str.begin()时,即 "it "指向'L',for-loop打印'L'并停止。这样,没有'R'的字符串就会按相反的顺序打印。

要想获得一个迭代器所指向的值,可以在迭代器前面加上指示符,*。

basic_string& erase(size_type pos = 0, size_type n = npos)

这个成员函数擦除一个范围,就像上面的函数一样。然而,它使用索引而不是迭代器。如果参数pos是0,那么范围就从第一个元素开始。如果参数n是字符串的长度(字符数),那么范围在最后一个字符处结束。两个参数都有其默认值。这个函数返回字符串类对象,并删除范围内的字符。

这里要玩的技巧是使pos的值成为最后一个字符的索引。最后一个字符(元素)的索引是列表的大小(长度)减去1。对于这个问题,这里的第二个参数应该被省略。最后的索引是由以下公式给出的。

    str.size() - 1

下面的程序,使用这个成员函数,从字符串中取出最后一个字符'R'。

#include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "LMNOPQR";

        cout <<str <<endl;


        int l = str.size() - 1;


        string ret = str.erase(l);


        for (int i = 0; i <ret.size(); i++)

            cout <<str[i];

        cout <<endl;


        for (int i = 0; i <str.size(); i++)

            cout <<str[i];

        cout <<endl;


        return 0;

    }

输出结果是

lmnopqr  
  
lmnopq  
  
lmnopq

原始字符串和返回的字符串都丢失了'R'。程序的前三行的解释与前面的程序相同。在main()函数主体中,第一个语句声明了字符串对象。下一条语句打印出新声明的字符串。

下一条语句确定原始字符串的最后一个元素的索引。之后的语句使用这个索引擦除最后一个字符。下一个代码段使用索引逐一打印出返回字符串的字符。最后一个代码段使用索引一个一个地打印出原始字符串的字符。

总结

正常的字符串类成员函数是pop_back()函数,用于删除字符串的最后一个字符,以及容纳它的元素。有三个erase()重载成员函数也可用于此。其中一个接收一个指向最后一个字符的迭代器,并删除最后一个字符。另一个接收一个范围,由两个迭代器表示:一个迭代器指向最后一个字符,另一个指向最后一个字符之后。有了这个,最后一个字符就被取走了。第三个重载函数使用最后一个字符的索引来删除它。本文中的所有讨论都符合C++20的要求。