【C++】STL - string类

一、string 的定义

string有多个构造函数的重载:

cpp 复制代码
string();  
string(const char* s);  //复制s字符串
string(const char* s, size_t n);  //复制s所字符串的前n个字符
string(size_t n, char c);  //生成n个c字符
string(const string& str);  //复制str
string(const string& str, size_t pos, size_t len = npos);  //复制str的字符从pos位置开始向后len个字符
cpp 复制代码
string s1;                    
string s2("hello world");    
string s3("hello world", 3); 
string s4(5, 'c');            
string s5(s4);               
string s6(s2, 0, 4);        

二、string插入

1、push_back

void push_back (char c);

cpp 复制代码
int main() {
	string s;
	const char* str = "hello world";
	for (int i = 0; i < strlen(str); i++) {
		s.push_back(str[i]);
	}
	cout << s << endl; //hello world
	return 0;
}

2、insert

string& insert (size_t pos, const string& str);

string& insert (size_t pos, const char* s);

iterator insert (iterator p, char c);

cpp 复制代码
int main() {
	string s;
	const char* str = "hello world";
	for (int i = 0; i < strlen(str); i++) {
		s.insert(s.end(), str[i]);
	}
	s.insert(0, "A");
	s.insert(0, str);
	cout << s << endl; //hello worldAhello world
	return 0;
}

三、string拼接

append

string& append (const string& str);

string& append (const char* s);

string& append (size_t n, char c);

cpp 复制代码
int main() {
	string s1("hello");
	string s2("world");
	s1.append(s2);
	s1.append(" xyz");
	s1.append(3, '!');

	cout << s1 << endl; //helloworld xyz!!!
	return 0;
}

四、string删除

1、pop_back

void pop_back();

cpp 复制代码
int main() {
	string s;
	const char* str = "hello world";
	for (int i = 0; i < strlen(str); i++) {
		s.push_back(str[i]);
	}
	cout << s << endl; //hello world
	s.pop_back();
	cout << s << endl; //hello worl

	return 0;
}

2、erase

string& erase (size_t pos = 0, size_t len = npos);

iterator erase (iterator p);

iterator erase (iterator first, iterator last);

cpp 复制代码
int main() {
	string s;
	const char* str = "hello world";
	for (int i = 0; i < strlen(str); i++) {
		s.push_back(str[i]);
	}
	s.erase(6, 1);
	cout << s << endl;//hello orld

	s.erase(s.end()-1);
	cout << s << endl;//hello orl

	s.erase(s.begin(), s.end());
	cout << s << endl;//
	return 0;
}

五、string查找

1、find

size_t find (const string& str, size_t pos = 0) const;

size_t find (const char* s, size_t pos = 0) const;

size_t find (char c, size_t pos = 0) const;

cpp 复制代码
int main()
{
	string s1("https://blog.csdn.net/m0_72651735?type=blog");

	//搜索与对象所匹配的第一个位置
	string s2("blog");
	size_t pos1 = s1.find(s2);
	cout << pos1 << endl; //8

	//搜索与字符串所匹配的第一个位置
	char str[] = "csdn";
	size_t pos2 = s1.find(str);
	cout << pos2 << endl;  //13

	//搜索与字符所匹配的第一个位置
	size_t pos3 = s1.find('/');
	cout << pos3 << endl; //6
	return 0;
}

2、rfind

size_t rfind (const string& str, size_t pos = npos) const;

size_t rfind (const char* s, size_t pos = npos) const;

size_t rfind (char c, size_t pos = npos) const;

cpp 复制代码
int main()
{
	string s1("https://blog.csdn.net/m0_72651735?type=blog");

	//搜索与对象所匹配的反向第一个位置
	string s2("blog");
	size_t pos1 = s1.rfind(s2);
	cout << pos1 << endl; //39

	//搜索与字符串所匹配的反向第一个位置
	char str[] = "csdn";
	size_t pos2 = s1.rfind(str);
	cout << pos2 << endl;  //13

	//搜索与字符所匹配的反向第一个位置
	size_t pos3 = s1.rfind('/');
	cout << pos3 << endl; //21
	return 0;
}

六、string比较

int compare (const string& str) const;

int compare (size_t pos, size_t len, const string& str) const;

int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
1、两个字符串中谁的第一个不匹配的字符值较小,或者所有比较字符都匹配,但比较字符串较短,则返回小于0的值。

2、两个字符串中谁的第一个不匹配的字符值较大,或者所有比较字符都匹配,但比较字符串较长,则返回大于0的值。

3、两个字符串相等,则返回0。

cpp 复制代码
int main()
{
	string s1("hello world");
	string s2("swean");

	cout << s1.compare(s2) << endl; //1
	cout << s1.compare(6, 3, s2) << endl; //1
	cout << s1.compare(0, 4, s2, 0, 4) << endl; //-1
	return 0;
}

七、string替换

replace

string& replace (size_t pos, size_t len, const char* s);

string& replace (size_t pos, size_t len, size_t n, char c);

cpp 复制代码
int main()
{
	string s("hello world");

	//replace(pos, len, str)将pos位置开始的len个字符替换为字符串str
	s.replace(6, 4, "swean"); //hello sweand

	//replace(pos, len, n, char)将pos位置开始的len个字符替换为n个字符char
	s.replace(10, 1, 2, '-'); //hello swea--d

	cout << s << endl;
	return 0;
}

八、string交换

swap

void swap (string& x, string& y);

void swap (string& str);

cpp 复制代码
int main()
{
	string s1("hello world");
	string s2("swean");

	//类的成员函数swap交换s1和s2
	s1.swap(s2);
	cout << s1 << endl; //swean
	cout << s2 << endl; //hello world

	//非成员函数swap交换s1和s2
	swap(s1, s2);
	cout << s1 << endl; //hello world
	cout << s2 << endl; //swean
	return 0;
}

九、string大小和容量

1、size / length

size_t size() const;

size_t length() const;

cpp 复制代码
int main()
{
	string s("swean");
	cout << s.size() << endl; //5
	cout << s.length() << endl; //5
	return 0;
}

2、max_size

size_t max_size() const;

cpp 复制代码
int main()
{
	string s;
	cout << s.max_size() << endl; //4294967294
	return 0;
}

3、capacity

size_t capacity() const;

cpp 复制代码
int main()
{
	string s("swean");
	cout << s.capacity() << endl; //15
	return 0;
}

4、resize

1、当n大于当前的size时,将size扩大到n,扩大的字符为c,c默认为'\0'。

 2、当n小于当前的size时,将size缩小到n。

void resize (size_t n);

void resize (size_t n, char c);

cpp 复制代码
int main()
{
	string s1("swean");
	//resize(n)当n大于当前的size时,将size扩大到n,扩大的字符为c,c默认为'\0'。
	s1.resize(20);
	cout << s1 << endl; //swean
	cout << s1.size() << endl; //20
	cout << s1.capacity() << endl; //31

	string s2("swean");
	//resize(n, char)n大于对象当前的size时,将size扩大到n,扩大的字符为char
	s2.resize(20, 'x');
	cout << s2 << endl; //sweanxxxxxxxxxxxxxxxx
	cout << s2.size() << endl; //20
	cout << s2.capacity() << endl; //31

	string s3("swean");
	//resize(n)n小于对象当前的size时,将size缩小到n
	s3.resize(2);
	cout << s3 << endl; //sw
	cout << s3.size() << endl; //2
	cout << s3.capacity() << endl; //15
	return 0;
}

5、reserve

 1、当n大于对象当前的capacity时,将capacity扩大到n或大于n。

 2、当n小于对象当前的capacity时,什么也不做。

void reserve (size_t n = 0);

cpp 复制代码
int main()
{
	string s("swean");
	cout << s << endl; //swean
	cout << s.size() << endl; //5
	cout << s.capacity() << endl; //15

	//reverse(n)当n大于对象当前的capacity时,将当前对象的capacity扩大为n或大于n
	s.reserve(20);
	cout << s << endl; //swean
	cout << s.size() << endl; //5
	cout << s.capacity() << endl; //31

	//reverse(n)当n小于对象当前的capacity时,什么也不做
	s.reserve(2);
	cout << s << endl; //swean
	cout << s.size() << endl; //5
	cout << s.capacity() << endl; //31
	return 0;
}

这里我们可以测试一下在vs2022环境下,capacity的扩容机制是什么样的

cpp 复制代码
int main() {
	string s;
	int cp = s.capacity();
	cout << "初始capacity:" << cp << endl;
	for (int i = 0; i < 200; i++) {
		if (s.capacity() != cp) {
			cp = s.capacity();
			cout << "扩容capacity:" << cp << endl;
		}
		s.push_back('a');
	}
	return 0;
}

可以看出差不多是1.5倍,而且还有对齐

6、clear

void clear();

cpp 复制代码
int main()
{
	string s("swean");

	s.clear();
	cout << s << endl; //空字符串,但是capacity不会改变
	return 0;
}

7、empty

bool empty() const;

cpp 复制代码
int main()
{
	string s("swean");
	cout << s.empty() << endl; //0

	s.clear();
	cout << s.empty() << endl; //1
	return 0;
}

十、string访问元素

1、 +下标

因为string类对 运算符进行了重载,所以我们可以直接使用 +下标访问对象中的元素。并且该重载使用的是引用返回,所以我们可以通过 +下标修改对应位置的元素。

char& operator\[\] (size_t pos);

const char& operator\[\] (size_t pos) const;

cpp 复制代码
int main()
{
	string s("hello world");
	//[]+下标访问对象元素
	for (int i = 0; i < s.size(); i++)
	{
		cout << s[i];
	}
	cout << endl; //hello world

	//[]+下标修改对象元素内容
	for (int i = 0; i < s.size(); i++)
	{
		s[i] += 1;
	}
	cout << s << endl; //ifmmp!xpsme
	return 0;
}

2、at

char& at (size_t pos);

const char& at (size_t pos) const;

cpp 复制代码
int main()
{
	string s("hello world");
	//[]+下标访问对象元素
	for (int i = 0; i < s.size(); i++)
	{
		cout << s.at(i);
	}
	cout << endl; //hello world

	//[]+下标修改对象元素内容
	for (int i = 0; i < s.size(); i++)
	{
		s.at(i) = 'x';
	}
	cout << s << endl; //xxxxxxxxxxx
	return 0;
}

3、范围for

cpp 复制代码
int main()
{
	string s("hello world");
	//使用范围for访问对象元素
	for (auto e : s)
	{
		cout << e;
	}
	cout << endl; //hello world

	//使用范围for访问对象元素,并对其进行修改
	for (auto& e : s) //需要修改对象的元素,e必须是引用类型
	{
		e += 1;
	}
	cout << s << endl; //ifmmp!xpsme
	return 0;
}

4、iterator

cpp 复制代码
int main()
{
	string s("hello world");
	
	//使用迭代器访问对象元素
	string::iterator it1 = s.begin();
	while (it1 != s.end())
	{
		cout << *it1;
		it1++;
	}
	cout << endl; 

	//使用迭代器访问对象元素,并对其进行修改
	string::iterator it2 = s.begin();
	while (it2 != s.end())
	{
		*it2 += 1;
		it2++;
	}
	cout << s << endl; 
	return 0;
}

十一、string运算符

1、operator=

 string类中对=运算符进行了重载,重载后的=运算符支持string类的赋值、字符串的赋值以及字符的赋值。

cpp 复制代码
int main()
{
	string s1;
	string s2("hello world");

	s1 = s2;
	cout << s1 << endl;

	s1 = "hello";
	cout << s1 << endl;  //hello

	s1 = 'x';
	cout << s1 << endl; //x
	return 0;
}

2、operator+=

 string类中对+=运算符进行了重载,重载后的+=运算符支持string类的复合赋值、字符串的复合赋值以及字符复合的赋值。

cpp 复制代码
int main()
{
	string s1;
	string s2("hello");

	s1 += s2;
	cout << s1 << endl; //hello

	s1 += " world";
	cout << s1 << endl; //hello world

	s1 += '!';
	cout << s1 << endl; //hello world!
	return 0;
}

3、operator+

 string类中对+运算符进行了重载,重载后的+运算符支持以下几种类型的操作:

 string类 + string类、string类 + 字符串、字符串 + string类、string类 + 字符、字符 + string类

它们相加均返回一个string类对象。

cpp 复制代码
int main()
{
	string s;
	string s1("swean");
	string s2("hello");
	char str[] = "world";
	char ch = '!';

	//string类 + string类
	s = s1 + s2;
	cout << s << endl; //sweanhello

	//string类 + 字符串
	s = s1 + str;
	cout << s << endl; //sweanworld

	//字符串 + string类
	s = str + s1;
	cout << s << endl; //worldswean

	//string类 + 字符
	s = s1 + ch;
	cout << s << endl; //swean!

	//字符 + string类
	s = ch + s1;
	cout << s << endl; //!swean
	return 0;
}

4、operator>> 和 operator<<

istream& operator>> (istream& is, string& str);

ostream& operator<< (ostream& os, const string& str);

cpp 复制代码
int main()
{
	string s;
	cin >> s; //输入
	cout << s << endl; //输出
	return 0;
}

5、关系运算符

 string类中还对一系列关系运算符进行了重载,==、!=、<、<=、>、>=。

cpp 复制代码
int main()
{
	string s1("abcd");
	string s2("abde");
	cout << (s1 > s2) << endl; //0
	cout << (s1 < s2) << endl; //1
	cout << (s1 == s2) << endl; //0
	return 0;
}

十二、string迭代器

1、正向迭代器

begin / end

iterator begin();

const_iterator begin() const;

iterator end();

const_iterator end() const;

cpp 复制代码
int main()
{
	string s("hello world");

	//正向迭代器
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it;
		it++;
	}
	cout << endl;

	return 0;
}

2、反向迭代器

rbegin / rend

reverse_iterator rbegin();

const_reverse_iterator rbegin() const;

reverse_iterator rend();

const_reverse_iterator rend() const;

cpp 复制代码
int main()
{
	string s("hello world");

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

十三、string转换字符串

字符串 ==> string

cpp 复制代码
int main()
{
	string s1("hello world");

	char str[] = "hello world";
	string s2(str);

	cout << s1 << endl; //hello world
	cout << s2 << endl; //hello world
	return 0;
}

2、c_str / data

const char* c_str() const;

const char* data() const;

  • 在C++98中,c_str()返回 const char* 类型,返回的字符串会以空字符结尾。
  • 在C++98中,data()返回 const char* 类型,返回的字符串不以空字符结尾。
  • C++11版本中,c_str()与data()用法相同。
cpp 复制代码
int main()
{
	string s("hello world");
	const char* str1 = s.data();
	const char* str2 = s.c_str();

	cout << str1 << endl;
	cout << str2 << endl;
	return 0;
}

十四、string子串提取

substr

string substr (size_t pos = 0, size_t len = npos) const;

cpp 复制代码
int main()
{
	string s1("hello world");
	string s2;

	//substr(pos, n)提取pos位置开始的n个字符
	s2 = s1.substr(2, 4);
	cout << s2 << endl;
	return 0;
}

这里我们可以实现一个网址分割

cpp 复制代码
int main() {
	string s1("https://blog.csdn.net/m0_72651735?type=blog");
	string sub1, sub2, sub3;

	int i1 = s1.find(':');
	if (i1 != string::npos) {
		sub1 = s1.substr(0, i1);
	}
	else {
		cout << "未找到" << endl;
	}
	int i2 = s1.find('/', i1 + 3);
	if (i2 != string::npos) {
		sub2 = s1.substr(i1+3, i2-(i1+3));
	}
	else {
		cout << "未找到" << endl;
	}
	sub3 = s1.substr(i2);
	cout << sub1 << endl;
	cout << sub2 << endl;
	cout << sub3 << endl;
}

copy

size_t copy (char* s, size_t len, size_t pos = 0) const;

cpp 复制代码
int main()
{
	string s("hello world");
	char str[20];

	//复制pos位置开始的n个字符
	size_t length = s.copy(str, 4, 2);
	//copy函数不会在复制内容的末尾附加'\0',需要手动加
	str[length] = '\0';
	cout << str << endl; 
	return 0;
}

十五、string的getline函数

使用>>时,当>>读取到空格便会停止读取,所以我们不能用>>将一串含有空格的字符串读入到string对象中。

cpp 复制代码
int main()
{
	string s;
	cin >> s; //hello world
	cout << s << endl; //hello
	return 0;
}

这时,getline函数就派上用场了

istream& getline (istream& is, string& str);

istream& getline (istream& is, string& str, char delim);

1.getline函数从is中提取到的字符存储到str中,直到读取到换行符'\n'为止。

cpp 复制代码
int main()
{
	string s;
	getline(cin, s); //hello world
	cout << s << endl; //hello world
	return 0;
}

2.getline函数从is中提取到的字符存储到str中,直到读取到分隔符delim为止。

cpp 复制代码
int main()
{
	string s;
	//hello
	//world
	//swean!
	getline(cin, s, '!'); 
	cout << s << endl; 
	//hello
	//world
	//swean
	return 0;
}
相关推荐
码匠许师傅1 小时前
【C++三方组件】toml++:人性化的配置文件格式
c++
骑着蜗牛撵大象3272 小时前
告别内存泄漏:LLMManager架构设计与智能指针在AI SDK中的智慧选型
c++·ai·架构
汉克老师3 小时前
CSP-J 2026 初赛试题解析(第二部分:阅读程序题(第一题))精讲
c++·csp-j·小学生·学c++编程
syagain_zsx3 小时前
算法基础篇 · 04 前缀和(C++ 题解)
c++·算法·前缀和
汉克老师4 小时前
CSP-J 2026 初赛试题解析(第三部分:完善程序题(第一题))精讲
c++·csp-j·小学生·学c++编程
haluhalu.5 小时前
初识 Protobuf:微服务跨语言通信的一份契约
java·c语言·开发语言·c++·python
longxuan015 小时前
倍增算法详解
c++·st表·倍增算法
-森屿安年-5 小时前
返回最大数
c++·贪心算法