什么是子串以及如何在C++中识别、返回、删除和替换子串

104 阅读3分钟

子字符串或子串或范围只是字符串字面中的一部分字符序列。知道什么是C++中的子串对程序员来说是不够的。程序员必须了解如何通过代码来识别子串。程序员必须知道如何返回一个子串。程序员必须知道如何删除一个子串。程序员必须知道如何在删除后替换一个子串。

字符串可以通过两种主要方式创建:通过const char*(array-of-char)或者从字符串类中实例化。在从字符串类实例化的情况下,必须将字符串库包含在C++程序中。在C++中识别、返回、删除和替换子串,通常只能通过从字符串类中实例化的字符串对象来完成。

字符串对象是一个具有方法(成员函数)的数据结构。它的列表由元素组成,每个元素都有一个字符。列表的值就是字符。像一个数组一样,字符串对象的每个字符都可以通过一个索引来访问。因此,一个子字符串可以通过索引来识别:一个较低索引和一个较高索引。范围从低索引开始到高索引,不包括高索引。高索引的字符不包括在这个范围内,子串的长度是从低索引的字符到高索引的字符之前的字符。

两个迭代器也可以识别一个子串或范围:第一个迭代器是范围的开始,而最后一个迭代器,是在实际的最后一个字符之后的字符(或在字符串的末端)。迭代器和索引之间有一个简单的关系--见下文。

这篇文章解释了什么是子串以及如何在C++中识别、返回、删除和替换子串。

文章内容

识别和返回一个子串

C++类有一个成员函数,叫做substr(),用于子串()。其语法是:

    basic_string substr(size_type pos = 0, size_type n = npos) const

这个函数将子串作为一个字符串对象返回。第一个参数表示子串开始的索引位置。pos的字符被包含在子串中。第二个参数给出了子串的长度。长度是指从pos开始的字符数。它不包括较高索引的字符。更高的索引是:pos + npos (虽然长度,npos是向左移了一个位置)。索引计数从零开始。 下面的程序说明了这个成员函数的使用。

#include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";


        string substrin = str.substr(8, 5);


        cout <<substrin <<endl;


        return 0;

    }

输出结果是

    three

如果没有这两个参数,就会考虑整个字符串,正如下面的程序所说明的。

 #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";


        string substrin = str.substr();


        cout <<substrin <<endl;


        return 0;

    }

输出结果是

    one_two_three_four_five

语法末尾的保留词,const,意味着substr()函数复制了子串并返回它。它不会删除该子串。

迭代器和索引的关系

当一个迭代器指向一个字符时,为了得到区间末端的迭代器,只需加上区间的字符长度(数量),新的迭代器就会指向区间的末端。这最后一个迭代器的字符不包括在范围或子串中。这里的range和substring是同一件事(它们在上面是同一件事)。对于substr()字符串成员函数,npos是区间的长度。

与索引0相对应的迭代器是。

    str.begin()

npos可以被添加到这个迭代器中,以指向区间的最后一个元素。区间的最后一个元素或最后一个字符不是子串的一部分。

对应于字符串最后一个字符后的那一点的迭代器是。

    str.end()

npos可以从中减去,以便指向任何想要的字符串的第一个字符。

begin()和end()是字符串类的成员函数。

删除一个子串

一个子串在一个字符串对象中被识别,其参数是substr()函数的pos和npos。回顾一下,npos是一个区间。字符串类也有一个叫做eras()的成员函数。eras()有重载形式。其中一个重载的erase()成员函数用pos和npos来识别子串。语法是。

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

这个擦除函数删除了子串,并返回删除子串后的原始字符串。

所以,要删除一个子串,不需要使用substr()函数。需要的是它的参数。要删除一个子串,请使用字符串对象的erase成员函数。要想拥有一个子串的副本,只需在擦除前使用substr()函数。下面的程序展示了一个删除子串的好方法。

 #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";


        string substrin = str.substr(8, 5);

        string ret = str.erase(8, 5);


        cout <<substrin <<endl;

        cout <<str <<endl;

        cout <<ret <<endl;


        return 0;

    }

输出结果是

 three

    one_two__four_five

    one_two__four_five

一个用迭代器参数删除子串的语法是。

    iterator erase(const_iterator first, const_iterator last)

这样,子串的开头首先由迭代器确定,对应于索引,pos。为了获得子串的结尾,迭代器由last来识别,last是由first + npos获得的。使用这个重载的erase()函数来删除一个子串的代码,将作为一个练习留给读者。

替换一个子串

真正识别一个子串的是参数:pos和npos.要返回一个子串,请使用字符串类成员函数substr()。要删除一个子串,请使用字符串类的成员函数,eras()。要用一个任意长度的子串来替换一个子串,请使用字符串类成员函数,replace()。replace函数有许多重载的变体。其中使用索引的是

    basic_string& replace(size_type pos1, size_type n1, const T& t)

其中pos1是pos,n1是npos,而t是一个独立的字符数组,用于替换。它返回原始字符串,包括替换后的字符串。

注意:在C++中,一个子串在被替换之前不应该被删除(擦除)。
下面的程序展示了一个替换子串的好方法。

#include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";


        char chs[] = "ccc";


        string substrin = str.substr(8, 5);

        string ret = str.replace(8, 5, chs);


        cout <<substrin <<endl;

        cout <<str <<endl;

        cout <<ret <<endl;


        return 0;

    }

输出结果是

three

    one_two_ccc_four_five

    one_two_ccc_four_five

上述代码的替换长度小于5个字符。下面的程序显示了替换量大于5个字符的情况。

#include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";


        char chs[] = "cccccccc";


        string substrin = str.substr(8, 5);

        string ret = str.replace(8, 5, chs);


        cout <<substrin <<endl;

        cout <<str <<endl;

        cout <<ret <<endl;


        return 0;

    }


    three

    one_two_cccccccc_four_five

    one_two_cccccccc_four_five

用迭代器参数替换子串的语法是

    basic_string& replace(const_iterator i1, const_iterator i2, const T& t)

在这个语法中,子串的开头是由迭代器i1确定的,它对应的索引是pos。为了获得子串的结尾,迭代器由i2来识别,i2是通过i1 + npos获得的。下面的程序显示了如何使用这种语法。

 #include <iostream>

    #include <string>

    using namespace std;

   
    int main()

    {

        string str = "one_two_three_four_five";

        string::const_iterator itB = str.begin();

        string::const_iterator itPos = itB + 8;

        string::const_iterator itNpos = itPos + 5;


        char chs[] = "ccccc";


        string substrin = str.substr(8, 5);

        string ret = str.replace(itPos, itNpos, chs);


        cout <<substrin <<endl;

        cout <<str <<endl;

        cout <<ret <<endl;


        return 0;

    }

输出结果是

three

    one_two_ccccc_four_five

    one_two_ccccc_four_five

注意,使用的迭代器是常数迭代器。与索引pos相对应的迭代器是用itB+8得到的。对应于较高索引的迭代器是用itPos + 5得到的。

结论

一个子串或子串或范围只是一个字符串字面中的一部分字符序列。要返回一个子串,可以使用字符串类的成员函数substr()。要删除一个子串,请使用字符串类的成员函数,eras()。要替换一个子串,请使用字符串类成员函数,replace()。对于所有这些函数,索引参数pos和索引区间npos是识别主字符串子串的关键。