C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ string类常用成员函数

C++ string类常用成员函数有哪些?详解构造函数、容量操作与修改方法

作者:凉茶钱

还在为C++字符串操作发愁?本文全面解析std::string类的常用成员函数,包括构造函数、容量管理、字符串修改、查找截取等,并介绍迭代器遍历和非成员函数,帮你轻松掌握C++字符串处理技巧,避免常见陷阱

string类简介

C++ 的 std::string 是标准库提供的字符串类,使用时需要引入头文件<string>。它封装了字符序列,能够自动管理内存,相比 C 语言的字符数组,使用更加简便安全,内置了多种成员函数完成字符串的获取、查找、修改与截取等操作,支持运算符重载,方便字符串的拼接和比较。

https://legacy.cplusplus.com/reference/string/string/?kw=string可通过该网站了解

总结:

std::string 是 C++ 标准库中的字符串类,本质是 basic_string<char>的类型别名。字符串是用来表示字符序列的对象,标准 string 类为这类对象提供支持,它的接口类似于字节标准容器,同时增加了专门用于操作单字节字符字符串的特性。

typedef basic_string<char, char_traits, allocator>string;

string 类是 basic_string 类模板的实例化版本,以 char 作为字符类型,并使用默认的字符特征与内存分配器类型。

需要注意的是,这个类以字节为单位处理数据,和字符编码相互独立。如果使用它处理 UTF-8 这类多字节、变长字符序列,类内所有成员函数以及迭代器,都只会按照字节进行操作,而不是按照编码后的实际字符。

string类常用接口(成员函数)

string类对象默认成员函数

string类对象构造函数

这张图片介绍C++ 中 std::string 的各类构造函数,也就是创建 string 对象的多种方式。列出了 string 全部重载构造函数,用于构造 string 对象,不同版本对应不同的初始化方法。

参数解释如下:

这张图是对构造函数里各个参数的说明。

简单来说,第一张图展示构造函数的重载列表与功能简述,说明创建 string 对象的多种途径,第二张图解释各个参数的含义、约束以及使用时的注意事项。

#include<iostream>
#include<string>
 
using namespace std;
 
int main()
{

	string s1;

	string s2("hello world");

	string s3(5, 'x');

	string s4(s2);
 
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
 
	return 0;
}

这段代码演示了 std::string 中四种常用的构造函数。

函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n,char c)string类对象中包含n个字符c
string(const string&s)拷贝构造函数

string类对象析构函数

如图:

这张图片介绍的是 std::string 的析构函数~string。析构函数的作用是销毁 string 对象,它会借助分配器释放 string 申请的全部存储空间。析构函数具备不抛出异常的保证,执行过程不会抛出异常。

在程序运行过程中,当 string 对象离开作用域时,析构函数会被自动调用,它会自动释放字符串底层动态开辟的字符数组内存,避免内存泄漏。结合前面的构造函数来看,构造函数负责创建对象并分配内存,析构函数负责销毁对象并回收内存,二者相互配合完成 string 对象生命周期的管理。

string类对象赋值运算符重载函数

如图:

std::string 的赋值运算符 operator=,它的作用是给字符串赋予新内容,替换掉对象原本存储的数据,更多赋值方式可以查看 assign 成员函数。

这个运算符存在多个重载版本

  1. 第一种接收 const string & 类型的对象 str,复制另一个 string 对象的内容;
  2. 第二种接收 const char * 类型的 C 风格字符串,复制以空字符结尾的字符序列;
  3. 第三种接收单个字符 c,会让字符串只保存这一个字符,长度变为 1。

C++11 还增加了移动赋值以及初始化列表赋值的重载版本。

#include<iostream>
#include<string>
 
using namespace std;
 
int main()
{
	//构造空的string类对象,即空字符串
	string s1;
	//用C-string来构造string类对象,内容为hello world
	string s2("hello world");
	//string类对象中包含5个字符'x'
	string s3(5, 'x');
	//拷贝构造函数,用s2拷贝生成s4
	string s4(s2);
 
	//输出s4当前的内容
	cout << s4 << endl;
 
	//调用赋值运算符重载,将s3赋值给s4,覆盖原有内容
	s4 = s3;
	//输出赋值后的s4
	cout << s4 << endl;
 
	//调用赋值运算符重载,将C风格字符串"ABCDEF"赋值给s4
	s4 = "ABCDEF";
	//输出赋值后的s4
	cout << s4 << endl;
 
	//调用赋值运算符重载,将单个字符'Y'赋值给s4
	s4 = 'Y';
	//输出赋值后的s4
	cout << s4 << endl;
 
	return 0;
}

string类对象的迭代遍历及元素访问操作

共八个迭代器访问接口:

共4个元素访问接口:

函数名称功能说明
operator[]返回pos位置的字符,const string类对象调用
begin+endbegin获取一个字符的迭代器+end获取最后一个字符下一个位置的迭代器
rbegin+rendbegin获取一个字符的迭代器+end获取最后一个字符下一个位置的迭代器
范围forC++支持更简洁的范围for的新遍历方式

operator[]运算符重载

std::string 的下标运算符 operator [],用来获取字符串指定位置上的字符,一共有两个重载版本,普通版本返回字符的引用,常量版本返回常量字符引用。该运算符会返回字符串 pos 位置字符的引用,string 的下标从 0 开始计数,第一个字符对应的下标是 0。

当字符串是 const 修饰的常量对象,并且 pos 等于字符串长度时,会返回空字符 '\0' 的引用。参数 pos 代表字符在字符串中的位置,类型是无符号整数 size_t。返回值根据对象是否为常量区分,如果 string 对象带有 const 修饰,返回 const char&,普通对象则返回 char&,可以通过这个引用修改对应位置的字符。

需要注意,operator [] 不会做下标越界检查,如果 pos 超出有效范围,会产生未定义行为。

用operator[]遍历string类对象:

#include<iostream>
#include<string>
using namespace std;
 
int main()
{
	string st1("Hello world");
	
	for (size_t i = 0; i < st1.size(); i++)
	{
		cout << st1[i] << endl;
	}
 
 
	return 0;
}

用operator[]修改string类对象:

int main()
{
	string st1("Hello world");
	
	for (size_t i = 0; i < st1.size(); i++)
	{
		++st1[i];
		cout << st1[i] << endl;
	}
 
	return 0;
}

顺序迭代器begin+end

begin:

std::string 的 begin 成员函数,作用是返回指向字符串起始位置的迭代器。

它包含两个重载版本,普通对象调用返回 iterator,const 修饰的 string 对象调用返回 const_iterator。这个函数不需要传入任何参数,返回的迭代器指向字符串的第一个字符。如果 string 对象带有 const 修饰,返回的是 const_iterator,只能读取字符,不能修改;普通 string 对象返回 iterator,可以读写字符。string 的 iterator 与 const_iterator 都属于随机访问迭代器,iterator 指向普通字符,const_iterator 指向常量字符。

注意:

const_iterator 是迭代器的类型,代表常量迭代器。这个迭代器本身可以移动,比如可以自增、自减,但是不能通过这个迭代器修改它指向的字符。也就是说,*it 不能赋值,只能读取内容。当 string 对象是 const 常量字符串的时候,begin () 返回的就是 const_iterator。

const iterator 是给普通迭代器 iterator 加上 const 修饰。此时迭代器本身不能改变指向,迭代器的位置固定,不能移动,但是可以通过这个迭代器修改指向的字符。简单来说,迭代器本身不可变,指向的数据可以修改。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s = "hello";

	// const_iterator:迭代器可移动,不能修改指向内容
	string::const_iterator cit = s.begin();
	cit++;
	//*cit = 'x'; 这一行编译报错,不能修改

	// const iterator:迭代器本身不可移动,指向内容可以修改
	const string::iterator it = s.begin();
	//it++; 这一行编译报错,迭代器不能移动
	*it = 'H';
	cout << s << endl;

	return 0;
}

end:

std::string 的 end 成员函数,用来返回指向字符串末尾之后位置的迭代器。

它有两个重载版本,普通 string 对象调用返回 iterator,const 修饰的 string 对象调用返回 const_iterator。这个迭代器指向字符串最后一个字符的下一个位置,这是一个理论上的虚拟位置,不可以对这个迭代器解引用读取字符。

标准库采用左闭右开区间规则,end 经常和 begin 搭配使用,用来划定包含字符串全部字符的范围。如果 string 是空字符串,end 返回的迭代器和 begin 返回的迭代器相等。这个函数不需要传入参数。返回值是字符串末尾之后位置的迭代器,如果 string 对象带有 const 修饰,返回 const_iterator,普通对象返回 iterator,iterator 和 const_iterator 都属于随机访问迭代器。

begin+end迭代器顺序遍历访问string类对象:

int main()
{
	string st1("Hello world");
	//迭代器
	string::iterator it = st1.begin();
	while (it != st1.end())
	{
		cout << *it << endl;
		++it;
	}
 
	return 0;
}

begin+end迭代器修改string对象:

int main()
{
	string st1("Hello world");
	//迭代器
	string::iterator it = st1.begin();
	while (it != st1.end())
	{
		++(*it);
 
		cout << *it << endl;
		++it;
	}
 
	return 0;
}

反向迭代器rbegin+rend

如图:

std::string 的 rbegin 反向起始迭代器函数。它有两个重载版本,普通 string 对象调用返回 reverse_iterator,const 修饰的 string 对象调用返回 const_reverse_iterator。

rbegin 会返回一个反向迭代器,指向字符串的最后一个字符,也就是反向遍历的起点。反向迭代器的遍历方向是反过来的,对反向迭代器做自增操作,迭代器会向字符串开头方向移动。rbegin 指向的位置,正好是 end 所指向位置的前一个字符。这个函数不需要传入参数。返回值是字符串反向起点的反向迭代器,如果 string 对象带有 const 修饰,返回 const_reverse_iterator,普通对象返回 reverse_iterator。

reverse_iterator 和 const_reverse_iterator 都属于反向随机访问迭代器,reverse_iterator 可以修改指向字符,const_reverse_iterator 只能读取字符。一般 rbegin 会和 rend 配合使用,用来反向遍历字符串。

std::string 的 rend 反向结束迭代器函数。它有两个重载版本,普通 string 对象调用返回 reverse_iterator,const 修饰的 string 对象调用返回 const_reverse_iterator。

rend 返回的反向迭代器指向字符串第一个字符前面的虚拟位置,也就是反向遍历的终点,这个位置不存在真实字符,不能解引用。rbegin 到 rend 构成的区间包含字符串全部字符,遍历顺序是逆序。这个函数不需要传入参数。返回值是反向终点的反向迭代器,如果 string 对象带有 const 修饰,返回 const_reverse_iterator,普通对象返回 reverse_iterator。reverse_iterator 和 const_reverse_iterator 都属于反向随机访问迭代器。

rbegin 和 rend 搭配做反向遍历,区间同样是左闭右开。rbegin 是反向起点,rend 是反向终点。

使用rbegin+rend迭代器反向遍历访问string类对象:

int main()
{
	string st1("Hello world");
 
	//反向迭代器
	string::reverse_iterator rit = st1.rbegin();
	while (rit != st1.rend())
	{
		cout << *rit << endl;
		++rit;
	}
 
	return 0;
}

使用rbegin+rend反向迭代器修改string类对象:

int main()
{
	string st1("Hello world");
 
	//反向迭代器
	string::reverse_iterator rit = st1.rbegin();
	while (rit != st1.rend())
	{
		++(*rit);
		cout << *rit << endl;
		++rit;
	}
 
	return 0;
}

范围for

范围 for,全称:range-based for loop。它本质是语法糖,底层会自动调用容器的 begin 和 end 迭代器来完成遍历,省去手动写迭代器的代码。

一共有三种常用写法,各自作用不一样。第一种是值拷贝写法,char ch : s。每次循环会把字符串里的字符复制一份放到 ch 里面,ch 只是副本,修改 ch 不会改变原来字符串里的内容。这种写法适合简单读取,char 类型拷贝开销很小,但是如果是大型对象,拷贝会带来额外性能消耗。

string s = "abc";
for(char ch : s)
{
    ch = 'x'; // 修改的只是副本,原s不变
    cout << ch;
}

第二种是普通引用写法,char& ch : s。ch 是原字符串字符的别名,不会产生拷贝,直接绑定原始数据。修改 ch 就会直接修改原字符串对应的字符。这个写法只能用于非 const 的 string 对象,如果字符串被 const 修饰,不能使用普通引用。

string s = "abc";
for(char& ch : s)
{
    ch += 1; // 直接修改原字符串s
}

第三种是 const 引用写法,const char& ch : s。ch 是常量引用,绑定原始字符,不会拷贝,同时不能通过 ch 修改字符内容。这种写法没有拷贝开销,效率高。const 修饰的字符串只能用这个写法,普通字符串只读遍历的时候也推荐使用,避免不小心修改原数据。

const string s = "abc";
for(const char& ch : s)
{
    cout << ch;
    // ch = '1'; 编译报错,禁止修改
}

编译器底层翻译逻辑,当你写范围 for 遍历 string 的时候,编译器会自动转换成迭代器版本的代码。循环开始的时候只会获取一次 begin 迭代器和 end 迭代器,之后循环就依靠这两个迭代器完成遍历。这就带来一个重要的限制,在范围 for 循环内部,不要对 string 做插入或者删除字符的操作,一旦字符串扩容或者长度改变,迭代器就会失效,程序会出现未定义行为,可能乱码或者崩溃。

string s = "hello";
for (char ch : s)
{
    cout << ch;
}

改代码转变为:

auto __begin = s.begin();
auto __end = s.end();
for( ; __begin != __end; ++__begin )
{
    char ch = *__begin;
    cout << ch;
}

范围 for 有几个明显的限制。

第一,它只能正向遍历,不能直接反向遍历字符串,如果想要逆序访问字符,还是要用 rbegin 和 rend 反向迭代器。

第二,范围 for 只能拿到元素本身,不会提供当前元素的下标,如果遍历过程中需要知道索引位置,范围 for 就不太方便,这时优先选用下标或者迭代器遍历。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    // 1. 值拷贝:副本,修改不影响原字符串
    cout << "值拷贝遍历:";
    for(char ch : s)
    {
        // ch = 'a'; // 无效,副本
        cout << ch << " ";
    }
    cout << endl;

    // 2. 普通引用:可以修改原字符串
    cout << "引用遍历(修改原串):";
    for(char& ch : s)
    {
        ch -= 32; //小写转大写
        cout << ch << " ";
    }
    cout << endl;

    //3.const引用:只读,推荐只读场景
    const string str = "TEST";
    cout << "const引用只读遍历:";
    for(const char& ch : str)
    {
        cout << ch << " ";
        //ch = 'X'; //报错,不能修改
    }
    cout << endl;

    return 0;
}

范围for顺序访问string类对象:

int main()
{
	string st1("Hello world");
 
	for (auto ch : st1)
	{
		cout << ch << endl;
	}
 
	return 0;
}

范围for修改string类对象:

int main()
{
	string st1("Hello world");
 
	for (auto &ch : st1)
	{
		ch++;
		cout << ch << endl;
	}
 
	return 0;
}

string类对象的容量操作

string类对象容量相关操作函数共有9个,如下:

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串是否为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数改成n个,多出的空间用字符c填充

size()函数

如图:

std::string::size 是 string 的成员函数,函数原型为 size_t size () const,不需要参数,是 const 成员函数,const 对象也可以调用。它返回字符串占用的字节数量,也就是字符串里面有效字符的个数,返回值类型是 size_t,这是一种无符号整型。size 统计的是字节数,不是字符个数,在处理 UTF-8 这类多字节编码文字时,一个汉字占多个字节,size 得到的结果会大于文字数量。size 和 length 是完全等价的同义词,两者返回的值一模一样。size 代表当前有效字符的字节数,和 capacity 容量不是一回事,capacity 是预先分配的内存总大小,capacity>= size。

重点要注意返回类型 size_t 是无符号数,不能直接和负数比较,容易出现逻辑错误。如果写 if (s.size () - 10 > 0),当 s.size () 小于 10 的时候,无符号数减负数会变成一个很大的正数,判断永远成立,引发 bug。

int main()
{
	string st1("Hello world");
	
	cout << st1.size() << endl;
 
	return 0;
}

length()函数

如图:

std::string::length 是 string 的成员函数,原型为 size_type length () const,无参数,属于 const 成员函数,const 字符串对象也可以调用。它返回字符串中有效字符的数量,返回类型 size_type 本质就是无符号整型 size_t。

文档明确说明 length 和 size 是同义词,两者返回完全相同的值,底层实现没有区别,只是名字不同。这里统计的是 string 内部存储的 char 单元数量,也就是字节数,不是语义上的文字个数。如果存放 UTF-8 中文,一个汉字占用多个 char 字节,length 返回的数值会大于汉字数量。length 得到的是当前有效字符数量,不等于底层预分配的内存容量 capacity,capacity 是预先申请好的内存总大小,capacity 一定大于或者等于 length。

int main()
{
	string st1("Hello world");
 
	cout << st1.length() << endl;
 
	return 0;
}

capacity()函数

如图:

std::string::capacity 是 string 的成员函数,原型为 size_type capacity () const,无参数,属于 const 成员函数,const 对象也可以调用。它返回当前底层已经分配好的内存空间大小,单位是 char。capacity 代表预先申请的内存总量,而 size 或者 length 是当前字符串里面有效字符的数量,capacity 大于等于 size。多出来的预留空间,是为了后续追加字符的时候减少内存重新分配的开销。

capacity 并不是字符串长度的硬上限,当写入字符超出 capacity 时,string 会自动重新分配更大的内存。字符串理论上能存放的最大长度由 max_size 决定。string 的 capacity 在修改字符串时有可能发生变化。可以调用 reserve 函数手动修改 capacity,主动提前预留内存。返回类型 size_type 是无符号整型。

int main()
{
	string st1("Hello world");
 
	cout << st1.size() << endl;
	cout << st1.capacity() << endl;
 
	return 0;
}

empyt()函数

如图:

std::string::empty 是 string 的成员函数,原型为 bool empty () const,无参数,属于 const 成员函数,const 对象也可以调用。它用来判断字符串是否为空,判断标准就是字符串长度是否等于 0。当字符串有效长度为 0 时返回 true,有字符则返回 false。这个函数不会修改字符串本身内容,如果想要清空字符串,需要调用 clear 函数。

int main()
{
	string st1("Hello world");
	string st2;
 
	cout << st1.empty() << endl;
	cout << st2.empty() << endl;
 
	return 0;
}

clear()函数

如图:

std::string::clear 是 string 的成员函数,原型为 void clear (),无参数,无返回值。它的作用是删除字符串内部全部内容,执行之后字符串长度变成 0,变成空串。调用 clear 只会修改 size,不会释放底层已经分配的内存,capacity 保持不变。

int main()
{
	string st1("Hello world");
	cout << st1.empty() << endl;
 
	st1.clear();
	cout << st1.empty() << endl;
 
	return 0;
}

reserve()函数

如图:

std::string::reserve 是 string 的成员函数,原型为 void reserve (size_type n = 0),无返回值。它用来主动请求修改 string 的 capacity 预留内存容量。

如果传入的 n 大于当前 capacity,函数会重新分配内存,将 capacity 扩充到 n 或者更大的值。如果 n 小于等于当前 capacity,这只是一个不强制生效的缩减请求,编译器可以选择不缩减容量,capacity 有可能保持不变。

reserve 不会改变 string 的 size,也不会修改字符串里面的内容,只作用于底层预分配内存。参数 n 是无符号整型 size_type。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "abc";
    cout << "初始size:" << s.size() << " capacity:" << s.capacity() << endl;

    s.reserve(100);
    cout << "reserve(100)后size:" << s.size() << " capacity:" << s.capacity() << endl;

    s.reserve(10);
    cout << "reserve(10)后size:" << s.size() << " capacity:" << s.capacity() << endl;

    return 0;
}

resize()函数

如图:

std::string::resize 用来修改字符串的有效长度 size,有两个重载版本。

第一个版本只传入 n,当 n 小于当前长度,截断字符串只保留前 n 个字符;当 n 大于当前长度,末尾补空字符 '\0'。

第二个版本额外传入字符 c,扩容新增位置就用 c 填充。resize 会改变 size,有可能触发 capacity 扩容。resize 修改的是有效字符数量,和 reserve 只修改预留容量不改变 size 有本质区别。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    cout << "原字符串:" << s << " size:" << s.size() << endl;

    // 1.缩短长度,n小于原size
    s.resize(3);
    cout << "resize(3)后字符串:" << s << " size:" << s.size() << endl;

    // 2.拉长长度,不指定填充字符,默认填充'\0'
    s.resize(6);
    cout << "resize(6)后size:" << s.size() << endl;

    // 3.拉长长度,指定填充字符'x'
    s.resize(10, 'x');
    cout << "resize(10,'x')后字符串:" << s << " size:" << s.size() << endl;

    return 0;
}

注意:

size () 与 length () 方法底层实现原理完全相同,引入 size () 的原因是为了与其他容器的接口保持一致,一般情况下基本都是用 size ()。

clear () 只是将 string 中有效字符清空,不改变底层空间大小。

resize (size_t n) 与 resize (size_t n, char c) 都是将字符串中有效字符个数改变到 n 个,不同的是当字符个数增多时:resize (n) 用 0 来填充多出的元素空间,resize (size_t n, char c) 用字符 c 来填充多出的元素空间。注意:resize 在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

reserve (size_t res_arg=0):为 string 预留空间,不改变有效元素个数,当 reserve 的参数小于 string 的底层空间总大小时,reserve 不会改变容量大小。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    cout << "size:" << s.size() << " length:" << s.length() << endl;

    s.clear();
    cout << "clear后 size:" << s.size() << " capacity:" << s.capacity() << endl;

    s = "hello";
    s.resize(3);
    cout << "resize(3) 缩短后:" << s << " capacity:" << s.capacity() << endl;

    s.resize(8);
    cout << "resize(8) 扩容,默认补\\0, size:" << s.size() << endl;

    s.resize(12, 'a');
    cout << "resize(12,'a')扩容,用a填充:" << s << " size:" << s.size() << endl;

    s.reserve(30);
    cout << "reserve(30)后 capacity:" << s.capacity() << " size:" << s.size() << endl;

    s.reserve(10);
    cout << "reserve(10),参数小于当前capacity,容量不变:" << s.capacity() << endl;

    return 0;
}

string类对象的字符串修改操作

修饰符:

字符串操作:

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回C格式字符串
find+nops从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

push_back()函数

如图:

std::string::push_back 函数原型为 void push_back (charT c),无返回值。功能是在 string 尾部追加一个字符,字符串长度 size 加 1。该接口只能追加单个字符,不能直接追加字符串。如果底层空间不足,会自动扩容。它和 += 追加字符效果类似,是容器风格的接口,和 vector 的 push_back 保持接口统一。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "test";
    cout << "原始字符串:" << s << " size:" << s.size() << endl;

    // push_back:在字符串末尾追加单个字符,只能传字符,不能传字符串
    s.push_back('!');
    cout << "push_back('!')后:" << s << " size:" << s.size() << endl;

    s.push_back('A');
    cout << "push_back('A')后:" << s << " size:" << s.size() << endl;

    return 0;
}

append()函数

如图:

std::string::append 有多个重载版本,作用是在字符串末尾追加字符序列,返回自身引用,支持链式调用。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    string str2 = "world";
    cout << "原始字符串s:" << s << endl;

    // 1.追加完整string对象
    s.append(str2);
    cout << "append(str2):" << s << endl;

    // 2.追加str2的子串,从下标0取3个字符
    s.append(str2,0,3);
    cout << "append(str2,0,3):" << s << endl;

    // 3.追加C风格字符串
    s.append("!!!");
    cout << "append(\"!!!\"):" << s << endl;

    // 4.追加C字符串前2个字符
    s.append("abcd",2);
    cout << "append(\"abcd\",2):" << s << endl;

    // 5.追加5个相同字符'*'
    s.append(5,'*');
    cout << "append(5,'*'):" << s << endl;

    return 0;
}

append 参数说明:

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    string str = "teststring";
    cout << "原始s:" << s << endl;

    // append(str, subpos, sublen):从str的subpos位置开始,截取sublen个字符追加
    s.append(str, 4, 3);
    cout << "append(str,4,3):" << s << endl;

    // sublen传string::npos代表取到str末尾
    s.append(str, 2, string::npos);
    cout << "append(str,2,npos):" << s << endl;

    // append(n,c) 追加n个字符c
    s.append(3, '!');
    cout << "append(3,'!'):" << s << endl;

    return 0;
}

operator+=()函数

如图:

如果需要截取子串、指定数量追加等复杂操作,需要使用 append。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello";
    string str = " world";
    cout << "原始s:" << s << endl;

    // 追加string对象
    s += str;
    cout << "s += str:" << s << endl;

    // 追加C风格字符串
    s += "!!";
    cout << "s += \"!!\":" << s << endl;

    // 追加单个字符
    s += 'A';
    cout << "s += 'A':" << s << endl;

    return 0;
}

c_str()函数

如图:

std::string::c_str 函数原型为 const charT* c_str () const,无参数。 它返回一个字符数组指针,数组里存放 string 对应的字符序列,并且在末尾自动添加 '\0' 结束符,得到标准 C 风格字符串。 返回的指针指向的内容不允许修改。如果后续调用修改该 string 对象的成员函数,这个指针就会失效。 该函数主要用于 C++ 的 string 和 C 语言字符串接口 交互。C++11 之后 c_str () 和 data () 效果基本一致。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "hello world";
    const char* p = s.c_str();
    cout << p << endl;

    // 可以传入接收C字符串的函数
    printf("%s\n", p);

    return 0;
}

find+nops函数

如图:

std::string::find 用于在字符串中查找目标序列第一次出现的位置,返回值类型为 size_type。pos 参数默认等于 0,代表从下标 0 开始查找;如果指定 pos,则只从 pos 位置(包含 pos)向后搜索,忽略 pos 之前的内容。find 要求完整序列匹配,和 find_first_of 不同,查找多字符目标时必须全部字符连续匹配才算找到,不能只匹配单个字符。

重载版本介绍:

  1. 接收 string 对象 str,pos 默认 0,查找 str 完整子串第一次出现位置。
  2. 接收 C 风格字符串 s,pos 默认 0,查找 C 字符串。
  3. 接收字符指针 s、pos、n,取 s 的前 n 个字符作为目标序列查找。
  4. 接收单个字符 c,pos 默认 0,查找该字符第一次出现位置。 查找失败时返回 string::npos。
#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s = "abcabc123";
    size_t ret;

    ret = s.find("abc", 1);
    if(ret != string::npos)
        cout << ret << endl;

    ret = s.find("abx");
    if(ret == string::npos)
        cout << "未找到" << endl;

    return 0;
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文