注意:在使用 string 类时,必须包含头文件 #include <string>。
一、string 的初始化与遍历
1. string 的初始化
string 支持多种初始化方式,这里介绍常用的三种,同时 string 也支持 cin 输入与 cout 输出。
1.1 默认初始化(创建一个空字符串 "")
语法形式: string s1;
示例:
std;
{
string s1;
cout << s1 << endl;
;
}
本文详细介绍了 C++ 标准库中 string 类的核心功能。内容包括 string 的三种初始化方式(默认、直接构造、拷贝构造),以及三种遍历方法(下标访问、范围 for 循环、迭代器)。此外,还讲解了 string 的容量管理函数(如 capacity、reserve、clear、empty)和常用成员函数(如 operator+=、push_back、append、substr、find、replace、getline)。文章通过代码示例展示了各函数的具体用法及运行结果,帮助读者掌握 string 类的基本操作与性能特性。
注意:在使用 string 类时,必须包含头文件 #include <string>。
string 支持多种初始化方式,这里介绍常用的三种,同时 string 也支持 cin 输入与 cout 输出。
语法形式: string s1;
示例:
std;
{
string s1;
cout << s1 << endl;
;
}
运行结果:

语法形式: string(const char* s);
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("Hello world");
cout << s1 << endl;
return 0;
}
运行结果:

语法形式: string(const string& str);
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1;
cin >> s1;
string s2(s1);
cout << s2 << endl;
return 0;
}
运行结果:

基本用法: size() 与 length() 都返回字符串中字符的个数(即字节数,不包括末尾隐藏的 \0)。
语法形式:
size_t size() const;
size_t length() const;
区别: length() 在 C++ 早期是作为独立的字符串处理工具设计的,而 size() 是后来 C++ 引入了 STL(标准模板库),规定所有的容器都必须提供一个统一的接口来获取元素个数。为了让 string 也能融入这个体系,使其像一个容器一样工作,就增加了 size(),推荐使用 size()。
使用:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1.size() << endl;
cout << s1.length() << endl;
return 0;
}
运行结果:

其实 string 在底层是一个类,因此重载了 [],以便我们读取/修改 string 中的字符。
语法形式:
char& operator[](size_t pos);
const char& operator[](size_t pos) const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1[5] << endl; // 访问下标为 5 的元素
s1[6] = 'M'; // 修改下标为 6 的元素
cout << s1 << endl;
return 0;
}
运行结果:

如果访问的下标超过了元素个数,会发生什么?编译器可能会报错或读取一个垃圾字符。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1[1000] << endl;
return 0;
}
运行结果:

示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
for (int i = 0; i < s1.size(); i++) {
cout << s1[i] << " ";
}
cout << endl;
return 0;
}
运行结果:

示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
for (auto e : s1) {
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:

示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
string::iterator it = s1.begin();
while (it != s1.end()) {
cout << *it << " ";
it++;
}
cout << endl;
return 0;
}
运行结果:

解释: 迭代器(iterator)扮演着'中介'的角色,就像一个通用的指针,能够让你以统一的方式访问容器中的元素,而无需关心容器底层到底是怎么实现的。
以上面的例子为例:可以形象理解为遥控器与传送带。
*it(解引用):按下按钮,获取当前传送带位置上的物品(字符)。++it(自增):让传送带指向下一个物品。begin():遥控器指向传送带的第一个位置。end():遥控器指向传送带最后一个物品之后的空白位置。目前 string 中的 begin() 与 end() 就是迭代器,它们的语法形式为:
iterator begin(); const_iterator begin() const;
iterator end(); const_iterator end() const;
这是正向打印,还有两个反向打印的,分别为 rbegin() 和 rend()。
语法形式:
reverse_iterator rbegin(); const_reverse_iterator rbegin() const;
reverse_iterator rend(); const_reverse_iterator rend() const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
string::reverse_iterator it = s1.rbegin();
while (it != s1.rend()) {
cout << *it << " ";
it++;
}
cout << endl;
return 0;
}
运行结果:

作用: 让编译器通过初始值自动推导变量的类型,极大简化了冗长的代码,但是也降低了代码的可读性,所以要谨慎使用。
特点:
auto 声明指针类型时,用 auto 和 auto* 没有任何区别,但用 auto 声明引用类型时则必须加 &。auto 不能作为函数的参数,可以做返回值,但是建议谨慎使用。auto 不能直接用来声明数组。特点:
我们可以将其看作是对迭代的范围的复制,所以就无法改变遍历变量的值。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
for (auto e : s1) {
e = 'm';
cout << e << " ";
}
cout << endl;
cout << s1 << endl;
return 0;
}
运行结果:

可以看出 s1 的结果并没有改变,此时我们可以使用 &。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
for (auto &e : s1) {
e = 'm';
cout << e << " ";
}
cout << endl;
cout << s1 << endl;
return 0;
}
运行结果:

其实 string 的底层是由指针(指向存放字符的内存地址)、大小(Size):记录当前有效字符的数量、容量(Capacity):记录当前分配的总空间大小、内部缓冲区(Local Buffer):用于存放短字符串的固定大小数组这几个内部成员组成。
**容量(Capacity)**就是记录当前分配的总空间大小,这个容量不一定等于 size,它可以相等或更大,额外的空间允许对象在字符串中添加新字符。
容量的大小是会变化的,举一个例子:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
size_t sz = s1.capacity();
cout << "capacity changed: " << sz << '\n';
cout << "making s grow:\n";
for (int i = 0; i < 100; ++i) {
s1.push_back('c');
if (sz != s1.capacity()) {
sz = s1.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
cout << endl;
return 0;
}
运行结果:

可以看出容量的变化并不是按照 2 倍的扩容变化的,而是以下的规则:
在 VS 中,默认会为对象开辟一个 16 字节的内部缓冲区(其中 1 字节用于存放末尾的 \0),只要字符串长度小于 15,数据就直接存在栈上的对象内部,不涉及堆内存分配,当字符串长度超过 16 后,是先扩大两倍后,再扩 1.5 倍。
然而在 DevC++ 中按照 2 倍扩大的。
如果我们想要提前扩容,或者已知需要的空间,就可以用这个函数。
语法形式: void reserve(size_t n = 0);
规则: 如果 n 大于当前字符串容量,函数会使容器的增加到 n 个字符(或更大),在其他所有情况下,将字符串容量的缩小视为非约束,实现可以自由优化其他方式,使字符串容量大于 n。该函数不影响字符串长度,也无法改变其内容。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
s1.reserve(100);
cout << s1.capacity() << endl;
cout << endl;
return 0;
}
运行结果:

作用: 擦除字符串的内容,字符串变成空字符串(长度为 0 字符)。
语法形式: void clear();
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
s1.clear();
cout << s1.size() << endl;
cout << endl;
return 0;
}
控制台输出:

作用: 测试字符串是否空。
语法形式: bool empty() const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
s1.clear();
if (s1.empty()) {
cout << "字符串为空" << endl;
}
return 0;
}
运行结果:

string 支持在字符串末尾相加。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1 << endl;
s1 += " Hello kong";
cout << s1 << endl;
return 0;
}
作用: 在字符串末尾附加字符 c。
语法形式: void push_back(char c);
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1 << endl;
s1.push_back(' ');
s1.push_back('m');
cout << s1 << endl;
return 0;
}
语法形式:
string& append(const string& str);
作用: 添加一串字符串。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
cout << s1 << endl;
s1.append("geerghre");
cout << s1 << endl;
return 0;
}
string& append(const string& str, size_t subpos, size_t sublen);
作用: 从字符位置 subpos 开始并跨越 sublen 字符添加一串字符串。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "I love ";
string s2 = "C++ Programming";
// 参数解释:
// s2: 源字符串
// 4: 从索引 4 开始(即第 5 个字符 'P')
// 7: 截取 7 个字符(即 "Program")
s1.append(s2, 4, 7);
cout << s1 << endl; // 输出:I love Program
return 0;
}
作用: 生成子串。
语法形式: string substr(size_t pos = 0, size_t len = npos) const;
说明: 返回一个新构建的对象,其值初始化为该对象子字符串的副本,子串是对象中从字符 pos 位置开始并跨越字符 len(或直到字符串末尾,以先到者为准)的部分。
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
string s2;
s2 = s1.substr(5);
cout << s2 << endl;
return 0;
}
运行结果:

作用: 搜索字符串中参数指定的序列的首次出现,当指定了 pos 时,搜索只包括位置 pos 及其后字符,忽略任何可能包含 pos 之前字符的情况,如果没有就返回 npos。
语法形式: size_t find(const string& str, size_t pos = 0) const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("HelloWorld");
size_t pos = s1.find('#');
if (pos == string::npos) {
cout << "没有这个字符串" << endl;
}
return 0;
}
作用: 用新内容替换字符串中从字符 pos 开始并跨成 len 字符的部分。
语法形式: string& replace(size_t pos, size_t len, const string& str);
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("Hello.Worl.dtdjd.dhsdjt");
size_t pos = s1.find('.');
while (pos != string::npos) {
s1.replace(pos, 1, "##");
pos = s1.find('.', pos + 2);
}
cout << s1 << endl;
return 0;
}
运行结果:

作用: 可用于处理含有空格的字符串。
语法形式: istream& getline(istream& is, string& str);
示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1, s2;
cout << "请输入 s1 的字符串:";
cin >> s1;
cout << "s1 的字符串为:";
cout << s1 << endl << endl;
cout << "请输入 s2 的字符串:";
getline(cin, s2);
cout << "s2 的字符串为:";
cout << s2 << endl;
return 0;
}
运行结果:


微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online