C++string中有关字符串内容修改和替换的函数浅析

1.assign()

原型:

//string (1)
basic_string& assign (const basic_string& str);
//substring (2)
basic_string& assign (const basic_string& str, size_type subpos, size_type sublen);
//c-string (3)
basic_string& assign (const charT* s);
//buffer (4)
basic_string& assign (const charT* s, size_type n);
//ill (5)
basic_string& assign (size_type n, charT c);
//range (6)
template <class InputIterator>
   basic_string& assign (InputIterator first, InputIterator last);

ps:charT是类模板basic_string的第1个参数,指定了字符串中字符的类型。用char实例化basic_string,得到string(可参考在下的“C++ string到底是什么”)。所以, 在string中,charT就是char。

示例:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string str1("123456");
    string str = "123456789";
    char* str2 = "abcdef";
    str.assign(str1);
    cout << str << endl;//123456   可见执行assign()后,str将被重写
    str.assign(str1, 2, 3);
    cout << str << endl;//345   从位置2开始的3个字符
    str.assign(str1, 1, 20);//超出范围
    cout << str << endl;//23456
    cout << str.length() << endl;//5 可见没有空格
    str.assign(str1, 2, str1.npos);//后面介绍npos
    cout << str << endl;//3456   从位置2到末尾的字符给str
    str.assign(5, ‘X‘);
    cout << str << endl;//XXXXX
    str.assign(str1.begin(), str1.end() - 1);
    cout << str << endl;//12345 从开头到结尾-1(即倒数第个字符)
    //str.assign(str1.begin() + 4, str1.end() - 4);//不能反着来,即试图将以str1.begin() + 4(5)开头,以str1.end() - 4(2)结尾的5432给str是不行的
    //cout << str << endl;                         //这样会出现运行时错误
    str.assign(str1.begin() + 2, str1.end() - 3);//前后指向同一字符(3),这样可以
    cout << str << endl;//3
    str.assign(str1.begin() + 2, str1.end() - 4);//这个却可以
    cout << str << endl;//空行
    cout << str.length() << endl;//0
    str.assign("abcdefg", 6);
    cout << str << endl;//abcdef 将abcdefg的前6个字符给str
    str.assign("abcdefg", 20);//超出范围
    cout << str << endl;//abcdefg+乱码
    cout << str.length() << endl;//10   说明将"abcdefg+3个空格"给了str
    str.assign(3, 0x41);
    cout << str << endl;//AAA   可以使用16进制的ASCII码 0x41换成10进制是65,是A的ASCII码
    str.assign(str2);
    cout << str << endl;//abcdef
    str.assign(str2, 2, 3);
    cout << str << endl;//cde   对char*型也可以
    return 0;
}

以上代码中有一句
str.assign(str1, 2, str1.npos);
这里我们解释npos:
它的定义如下:
std::string::npos
static const size_t npos = -1;
它是size_t类型的最大值,有些编译器也将它置为string对象的最大容量(按字节算,包括‘\0‘),而有些编译器不是,我们在后边将会看到。
为什么是最大呢?
-1用反码存储(32位),就是32个1,而size_t是无符号整型,所以,32个1的2进制转化为10进制就是2的32次方-1,即4294967295。
看下面一段验证代码:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string str1 = "123456789";
    cout << str1.npos << endl;//4294967295
    cout << (str1.npos == -1) << endl;//1
    cout << str1.max_size() << endl;//4294967294   1073741820(=2^30-4)
    return 0;
}

其中,4294967294是VS2013上的结果,可见max_size()不包括‘\0‘,1073741820是CodeBlocks12.11上的结果。
由此,我们可知,str.assign(str1, 2, str1.npos);等价于str.assign(str1, 2, 4294967294);

另外,在C++11中,还有两个重载的assign()函数,它们的原型分别是:

//initializer list(7)
basic_string& assign (initializer_list<charT> il);
//move (8)
basic_string& assign (basic_string&& str) noexcept;

其中,(7)与list容器有关,而(8)与右值引用和移动语义有关,这里我们暂不详述。
对于(8)中的noexcept关键字,它声明了函数不会抛出异常(当然函数不是真的就永远都不会抛出异常,比如该函数A(声明为noexcept)中调用了另一个函数B,而函数B中有抛出异常语句,那么,当我们调用函数A是,就可能抛出异常),由于noexcept不是本文的重点,这里我们不详述,有兴趣的读者可以自行查阅资料了解学习相关内容。

2.swap()

原型:void swap (basic_string& str);
只有这一个,要交换就交换整个字符串,这里没有针对子串的操作。
不举例。

3.erase()

原型:

//sequence (1)
basic_string& erase (size_type pos = 0, size_type len = npos);
//character (2)
     iterator erase (iterator p);
//range (3)
     iterator erase (iterator first, iterator last);

说明:
注意到basic_string& erase (size_type pos = 0, size_type len = npos);给出了默认参数,这样,我们在使用该函数时,就可以省略第2个参数,效果是删除从第1个参数所指位置(包括该位置)起的所有字符(正如下边示例中有关str3的操作和输出)。原因是len=npos,而npos一定大于string对象的最大长度。

示例:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string str1("123456789");
    string str2("123456789");
    string str3("123456789");
    string str4("123456789");
    string str5("123456789");
    string str6("123456789");
    string str7("123456789");
    string str8("123456789");
    str1.erase(2, 3);
    cout << str1 << endl;//126789
    str2.erase(2, 10); cout << endl;//空行
    str3.erase(7);//注意这里的参数值不能超过str3.length(),否则会出现运行时错误等于是输出空行,相当于删除‘\0‘及其后面的(当然后面什么也没有,
                  //因为‘\0‘已经是最后一个)
    cout << str3 << endl;//1234567   当省略第2个参数时,删除第1个参数所指位置起(即包括该位置)的所有字符
    //str4.erase(10, 5);//这么做不行
    //cout << str4 << endl;
    str4.erase(str4.begin());
    cout << str4 << endl;//23456789
    str5.erase(str5.begin() + 2);
    cout << str5<< endl;//12456789
    //str6.erase(str6.begin() + 10);//这么做不行
    //cout << str6 << endl;
    str6.erase(str6.end() - 2);
    cout << str6 << endl;//12345679
    //str7.erase(str7.end() - 10);//这么做不行
    //cout << str7 << endl;
    str7.erase(str7.begin()+2,str7.end()-2);
    str7.erase(str7.begin() + 2, str7.end() - 2);
    cout << str7 << endl;//1289   删除从str7.begin()+2(包括str7.begin()+2)到str7.end() - 2(包括str7.end() - 2)的所有字符
    //str8.erase(str8.begin() + 7, str8.end() - 5);//这么做不行
    //cout << str8 << endl;
    return 0;
}

4.clear()

原型:

void clear() noexcept;

作用:
删除字符串的所有内容。

示例:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string str("123456789");
    str.clear();
    cout << str << endl;//空行
    cout << str.length() << endl;//0
    return 0;
}

5.insert()

原型:

//string (1)
basic_string& insert (size_type pos, const basic_string& str);
//substring (2)
basic_string& insert (size_type pos, const basic_string& str,
                      size_type subpos, size_type sublen);
//c-string (3)
basic_string& insert (size_type pos, const charT* s);
//buffer (4)
basic_string& insert (size_type pos, const charT* s, size_type n);
//fill (5)
basic_string& insert (size_type pos,   size_type n, charT c);
     iterator insert (const_iterator p, size_type n, charT c);
//single character (6)
     iterator insert (const_iterator p, charT c);
//range (7)
template <class InputIterator>
     iterator insert (iterator p, InputIterator first, InputIterator last);
//initializer list (8)
basic_string& insert (const_iterator p, initializer_list<charT> il);

说明:
1)原型(8)与list容器有关,是C++11新标准,这里赞不详述。
2)以上原型中出现的返回值和参数有iterator和InputIterator与迭代器有关,这里也暂不详述,可以将其简单地理解为指针,begin()和end()的返回值与它们匹配。

示例:

#include<iostream>
#include<string>

using namespace std;

int main()
{
   /*
    *测试basic_string& insert (size_type pos, const basic_string& str);
   */
    string st1("123456789");
    //string st2("123456789");
    string str1("abc");
    st1.insert(3, str1);
    cout << st1 << endl;//123abc456789   注意是在pos所指位置前插入
    //st2.insert(10, str1);//超出范围
    //cout << st2 << endl;//不可以
    /*
    **测试basic_string& insert (size_type pos, const basic_string& str,size_type subpos, size_type sublen);
    */
    string st2("123456789");
    string st3("123456789");
    string str2("abcdefg");
    st2.insert(3, str2, 2, 3);
    cout << st2 << endl;//123cde456789
    st3.insert(3, str2, 4, 9);//超出范围
    cout << st3 << endl;//123efg456789   可见如果超出字符串的长度,则一直到字符串的最后,不补空格
    /*
    **测试basic_string& insert (size_type pos, const charT* s);
    */
    string st4("123456789");
    string st5("123456789");
    char* str3 = "abc";
    st4.insert(3, str3);
    cout << st4 << endl;//123abc456789
    st5.insert(3, "abc");
    cout << st5 << endl;//123abc456789
    /*
    **测试basic_string& insert (size_type pos, const charT* s, size_type n);
    */
    string st6("123456789");
    string st7("123456789");
    st6.insert(3, "abcdefg", 3);//n可以为0,为0时什么也不加 当n为负值时会出现运行时错误
    cout << st6 << endl;//123abc456789
    st7.insert(3, "abcdefg", 20);//超出范围
    cout << st7 << endl;//123abcdefg i n v a l i 456789  调大n值(如500)进行测试,发现中间多出来的是报错的语句和乱码,且每次运行的输出可能不一样
                        //CodeBlocks12.11上中间直接就是乱码
    /*
    **测试basic_string& insert (size_type pos,   size_type n, charT c);  和  iterator insert (const_iterator p, size_type n, charT c);
    */
    string st8("123456789");
    string st9("123456789");
    st8.insert(3, 2, ‘a‘);
    cout << st8 << endl;//123aa456789
    st9.insert(st9.begin() + 3, 2, ‘a‘);
    cout << st9 << endl;//123aa456789
    /*
    **测试iterator insert (const_iterator p, charT c);
    */
    string ss1("123456789");
    ss1.insert(ss1.begin()+3, ‘a‘);//由原型知,这里不能将ss1.begin()+3改为3
    cout << ss1 << endl;//123a456789
    /*
    **测试template <class InputIterator>
    **    iterator insert (iterator p, InputIterator first, InputIterator last);
    */
    string ss2("123456789");
    string str4("abcdefg");
    ss2.insert(ss2.begin() + 3, str4.begin(), str4.begin()+3);//超出范围会出现运行时错误
    cout << ss2 << endl;//123abc456789
    return 0;
}

6.append()

原型:

//string (1)
basic_string& append (const basic_string& str);
//substring (2)
basic_string& append (const basic_string& str, size_type subpos, size_type sublen);
//c-string (3)
basic_string& append (const charT* s);
//buffer (4)
basic_string& append (const charT* s, size_type n);
//fill (5)
basic_string& append (size_type n, charT c);
//range (6)
template <class InputIterator>
basic_string& append (InputIterator first, InputIterator last);
//initializer list(7)
basic_string& append (initializer_list<charT> il);

(7)不详述。
示例:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    /*
    **测试basic_string& append (const basic_string& str);
        */
    string st1("123456789");
    string str1("abc");
    string& ss = st1.append(str1);
    cout << ss << endl;//123456789abc
    cout << st1 << endl;//123456789abc
    /*
    **测试basic_string& append (const basic_string& str, size_type subpos, size_type sublen);
        */
    string st2("123456789");
    string st3("123456789");
    string str2("abcdefg");
    st2.append(str2, 2, 3);
    cout << st2 << endl;//123456789cde
    st3.append(str2, 3, 20);//超出范围
    cout << st3 << endl;//123456789defg    当用数字表示范围时,若超出范围,则直到字符串的结尾,不会补空格,也不会出现运行时错误
    cout << st3.length() << endl;//13      尽管如此,在实际编程时,也必须保证不超范围
    /*
    **测试basic_string& append (const charT* s);
        */
    string st4("123456789");
    st4.append("abc");
    cout << st4 << endl;//123456789abc
    /*
    **测试basic_string& append (const charT* s, size_type n);
    */
    string st5("123456789");
    st5.append("abc", 5);//超出范围
    cout << st5 << endl;//123456789abc+乱码
    /*
    **测试basic_string& append (size_type n, charT c);
    */
    string st6("123456789");
    st6.append(3, 0x41);//可以用16进制的ASCII码
    cout << st6 << endl;//123456789AAA
    /*
    **测试template <class InputIterator>
    **basic_string& append (InputIterator first, InputIterator last);
    */
    /*
    string st7("123456789");
    string str3("abcdefg");
    st6.append(str3.begin() + 2, str3.begin() + 10);//超出范围
    cout << st7 << endl;//当使用迭代器时,若超出范围,则会出现运行时错误
    */
    return 0;
}

7.replace()

原型:

//string (1)
basic_string& replace (size_type pos,     size_type len,     const basic_string& str);
basic_string& replace (const_iterator i1, const_iterator i2, const basic_string& str);
//substring (2)
basic_string& replace (size_type pos, size_type len, const basic_string& str,
                       size_type subpos, size_type sublen);
//c-string (3)
basic_string& replace (size_type pos,     size_type len,     const charT* s);
basic_string& replace (const_iterator i1, const_iterator i2, const charT* s);
//buffer (4)
basic_string& replace (size_type pos,     size_type len,     const charT* s, size_type n);
basic_string& replace (const_iterator i1, const_iterator i2, const charT* s, size_type n);
//fill (5)
basic_string& replace (size_type pos,     size_type len,     size_type n, charT c);
basic_string& replace (const_iterator i1, const_iterator i2, size_type n, charT c);
//range (6)
template <class InputIterator>
  basic_string& replace (const_iterator i1, const_iterator i2,
                       InputIterator first, InputIterator last);
//initializer list (7)
basic_string& replace (const_iterator i1, const_iterator i2, initializer_list<charT> il);

(7)不详述
示例:(这里仅给出部分原型的测试,其它的读者可参照前面几个函数的实例自行测试)

#include<iostream>
#include<string>

using namespace std;

int main()
{
    /*
    **测试basic_string& replace (size_type pos,     size_type len,     const basic_string& str);
    */
    string st1("123456789");
    string str1("abcde");
    string str2("ab");
    st1.replace(2, 3, str1);//将位置2开始的3个字符(345)换成abcde
    cout << st1 << endl;//12abcde6789
    string st2("123456789");
    st2.replace(1, 7, str1);
    cout << st2 << endl;//1abcde9
    string st3("123456789");
    st3.replace(6, 9, str2);//超出范围
    cout << st3 << endl;//123456ab
    /*
    **测试basic_string& replace (const_iterator i1, const_iterator i2, const basic_string& str);
    */
    /*string st4("123456789");
    st4.replace(st4.begin() + 8, st4.begin() + 10, str1);   //迭代器超范围,出现运行时错误
    cout << st4 << endl;*/
    /*
    **测试basic_string& replace (size_type pos,     size_type len,     const charT* s, size_type n);
    */
    string st5("123456789");
    st5.replace(2, 3, "abcdefg", 5);
    cout << st5 << endl;//12abcde6789
    string st6("123456789");
    st6.replace(2, 3, "abc", 20);//超出范围
    cout << st6 << endl;//12abc+乱码+6789   对于char*类型,若超出范围,就会出现乱码
    return 0;
}

以上各函数的原型及参数的意义大同小异,读者可以触类旁通。现结合以上各示例,对“超出范围”这一特殊情况给出一般性的规律总结:
1.对于string类型,用数字表示范围,超出时,自动截止到字符串的末尾,不会补空格,不会有乱码,也不会出现运行时错误。
2.对于string类型,用迭代器表示范围,超出时,出现运行时错误。
3.对于char*类型,用数字表示范围(只能用数字表示,char*是基本类型,没有迭代器),超出时,会出现乱码。

时间: 2024-10-10 23:18:33

C++string中有关字符串内容修改和替换的函数浅析的相关文章

C++中对字符串进行插入、替换、删除操作

#include <iostream> #include <string> using std::cout; using std::endl; using std::string; int main(void){ string str1="We can insert a string"; string str2="a str into "; //在字符串指定位置前面插入指定字符串 cout <<str1.insert(14,str

string中c_str()、data()、copy(p,n)函数的用法(转)

标准库的string类提供了3个成员函数来从一个string得到c类型的字符数组:c_str().data().copy(p,n). 1. c_str():生成一个const char*指针,指向以空字符终止的数组. 注: ①这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效.因此要么现用先转换,要么把它的数据复制到用户自己可以管理的内存中.注意.看下例: const char* c; string s="1234"; c = s.c_str(); co

Python中定义字符串和修改字符串的原理

   Python是用C语言开发的,在C语言中是没有字符串的概念,只有字符和字符数组,一般用字符数组表示字符串,所以在Python中定义一个字符串时,其实就是在内存中开辟一块空间, 例如: 定义一个字 符串string1=hello  --------->5个字符 字符数组['h','e','l','l','o'],其在内存中存储的位置为:['h','e','l','l','o'] 而如果想要修改该字符串为hellosb,在需要在内存中重新开辟一块数据空间为:['h','e','l','l','

把ArrayList集合中的字符串内容写到文本文件中

list列表数据导出到指定路径文本文档中 public  String getSDCardPath() { String sdCard = Environment.getExternalStorageDirectory().getAbsolutePath(); sdCard = sdCard + File.separator; return sdCard; } String mExportPath=getSDCardPath() + "TianChao/"+"Export/&

string中c_str()、data()、copy(p,n)函数的用法

标准库的string类提供了3个成员函数来从一个string得到c类型的字符数组:c_str().data().copy(p,n). 1. c_str():生成一个const char*指针,指向以空字符终止的数组. 注: ①这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效.因此要么现用先转换,要么把它的数据复制到用户自己可以管理的内存中.注意.看下例: const char* c; string s="1234"; c = s.c_str(); co

node.js中的字符串、对象和json处理函数

querystring.parse() 将字符串转成对象,就是把url上带的参数串转成数组对象. querystring.parse(str, [sep], [eq], [options]) 接收参数: str 欲转换的字符串 sep 设置分隔符,默认为 ‘&' eq 设置赋值符,默认为 ‘=' [options] maxKeys 可接受字符串的最大长度,默认为1000 querystring.parse('foo=bar&baz=qux&baz=quux&corge')

C++_如何得到类内字符串内容

在项目中遇到一个问题,在类外希望得到类中的字符串内容. 通过直接传递字符串指针实际并不能修改内容 可行的方法: 1.传递字符串数组的地址 2.传递字符串二级指针,即字符串地址 3.按照C++的方式传递一个 string引用, 通过引用直接修改 失败的方式:(截取代码:将函数封装到类里了,....代码太多,总体测试代码在文章末尾.感兴趣的同学自己复制) void GetStringC(char *a){ a = "Hi,Kemeng~: GetStringC"; } char * a2

图说:为什么Java中的字符串被定义为不可变的

8张图,看懂Java字符串的不变性 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时,其实会在堆内存中创建一个字符串对象,其中保存了一个字符数组,该数组中保存了字符串的内容. 上面的箭头可以理解为"存储他的引用". 当我们在代码中连续创建两个相同的字符串的时候,其实会指向同一个对象.因为当一个字符串被被创建的时候,首先会去这个字符串池中查找,如果找到,直接返回对该字符串的引用. 但是,如果在程

java入门学习笔记之2(Java中的字符串操作)

因为对Python很熟悉,看着Java的各种字符串操作就不自觉的代入Python的实现方法上,于是就将Java实现方式与Python实现方式都写下来了. 先说一下总结,Java的字符串类String本身定义了一些简单的字符串操作, 字符串常用操作有: 1. 取某一字符第一次出现/最后一次出现的索引 2. 取字符串某一位置的字符 3. 字符串截取 4. 去除首尾空格 5. 字符串字符替换 6. 判断两个字符串是否相等 7. 大小写转换 下面开始: 1.取某一字符第一次出现/最后一次出现的索引 JA