C++: C++ string
最后更新:2026-08-26
C 风格字符串(字符数组)用起来很麻烦,还容易出 bug(缓冲区溢出、忘记 \0)。
C++ 提供了 string 类——把字符串封装成一个对象,用起来安全又方便。
1. 什么是 string?
(1) 1.1 生活中的类比
| 生活场景 | 程序中的对应 |
|---|---|
| 你有一个背包,可以往里面装东西 | string 对象 |
| 背包能自动扩容(装不下就换大的) | string 动态管理内存 |
| 背包有好几个口袋,方便拿东西 | string 的成员函数 |
string 的优势:
- 不用管内存——自动分配和释放
- 不用管 \0——自动处理结束符
- 功能强大——拼接、查找、替换都很方便
(2) 1.2 为什么要用 string?
用 C 风格字符串(麻烦):
▶ 示例 2:代码示例(难度⭐)
CPP
#include <iostream>
#include <cstring>
int main() {
char greeting[50] = "Hello, ";
char name = "MOTO";
std::strcat(greeting, name); // 要担心数组够不够大
std::cout << greeting << std::endl;
return 0;
}
输出:
TEXT
📖 仅展示
(程序输出)
用 string(简单):
CPP
#include <iostream>
#include <string>
int main() {
std::string greeting = "Hello, ";
std::string name = "MOTO";
greeting += name; // 自动拼接,不用担心内存
std::cout << greeting << std::endl;
return 0;
}
2. string 的声明与初始化
(1) 2.1 基本用法
CPP
#include <iostream>
#include <string>
int main() {
// 方法一:直接初始化
std::string s1 = "Hello";
// 方法二:用构造函数
std::string s2("World");
// 方法三:重复某个字符
std::string s3(5, '*'); // "*****"
std::cout << s1 << " " << s2 << " " << s3 << std::endl;
return 0;
}
💡 重点: 使用 string 必须 `#include <string>`。
3. string 的常用操作
(1) 3.1 拼接字符串(+ 和 +=)
CPP
#include <iostream>
#include <string>
int main() {
std::string firstName = "MOTO";
std::string lastName = "Zhang";
// 方法一:用 +
std::string fullName1 = firstName + " " + lastName;
std::cout << fullName1 << std::endl; // MOTO Zhang
// 方法二:用 +=
std::string fullName2 = firstName;
fullName2 += " ";
fullName2 += lastName;
std::cout << fullName2 << std::endl; // MOTO Zhang
return 0;
}
(2) 3.2 获取长度(length 和 size)
CPP
#include <iostream>
#include <string>
int main() {
std::string name = "MOTO";
std::cout << "name: " << name << std::endl;
std::cout << "length(): " << name.length() << std::endl; // 4
std::cout << "size(): " << name.size() << std::endl; // 4
return 0;
}
💡 提示: length() 和 size() 完全一样,用哪个都行。
(3) 3.3 访问单个字符( 和 at)
CPP
#include <iostream>
#include <string>
int main() {
std::string name = "MOTO";
// 方法一:用
std::cout << name[0] << std::endl; // M
name[0] = 'm'; // 可以修改
// 方法二:用 at()(会检查越界)
std::cout << name.at(1) << std::endl; // o
// name.at(10); // ❌ 会抛异常(比 安全)
return 0;
}
💡 区别:
name[i]— 不检查越界,效率高name.at(i)— 检查越界,安全但慢一点
4. string 的常用成员函数
(1) 4.1 查找子串(find)
CPP
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, World!";
// 查找子串
size_t pos = text.find("World");
if (pos != std::string::npos) {
std::cout << "找到 \"World\",位置:" << pos << std::endl; // 7
} else {
std::cout << "没找到" << std::endl;
}
return 0;
}
💡 提示: 如果没找到,find() 返回 std::string::npos(通常是 -1 的无符号版本)。
(2) 4.2 提取子串(substr)
CPP
#include <iostream>
#include <string>
int main() {
std::string email = "moto@example.com";
// 提取子串:从位置 0 开始,取 4 个字符
std::string user = email.substr(0, 4);
std::cout << "用户名:" << user << std::endl; // moto
// 提取子串:从位置 5 开始,取到末尾
std::string domain = email.substr(5);
std::cout << "域名:" << domain << std::endl; // example.com
return 0;
}
(3) 4.3 替换子串(replace)
CPP
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, World!";
// 替换:从位置 7 开始,2 个字符,替换成 "C++"
text.replace(7, 5, "C++");
std::cout << text << std::endl; // Hello, C++!
return 0;
}
5. 输入和输出 string
(1) 5.1 用 cin 读取(遇到空格停止)
CPP
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "请输入名字:";
std::cin >> name; // ⚠️ 遇到空格就停止
std::cout << "你好," << name << "!" << std::endl;
return 0;
}
运行效果:
TEXT
📖 仅展示
请输入名字:MOTO Zhang
你好,MOTO! ← 只读取了 "MOTO"
(2) 5.2 用 getline 读取整行(推荐)
CPP
#include <iostream>
#include <string>
int main() {
std::string fullName;
std::cout << "请输入全名:";
std::getline(std::cin, fullName); // ✅ 读取整行(包括空格)
std::cout << "你好," << fullName << "!" << std::endl;
return 0;
}
运行效果:
TEXT
📖 仅展示
请输入全名:MOTO Zhang
你好,MOTO Zhang! ← 完整读取
💡 重点: 如果前面用了 cin >>,记得加 cin.ignore() 丢弃换行符!
6. 实战:简单的文本处理
▶ 示例 1:统计单词个数(难度⭐⭐)
CPP
#include <iostream>
#include <string>
#include <sstream> // 用于 stringstream
int main() {
std::string line;
std::cout << "请输入一行文本:";
std::getline(std::cin, line);
// 用 stringstream 分割单词
std::istringstream ss(line);
std::string word;
int count = 0;
while (ss >> word) {
count++;
}
std::cout << "单词个数:" << count << std::endl;
return 0;
}
输出:
TEXT
📖 仅展示
请输入一行文本:
单词个数:
运行效果:
TEXT
📖 仅展示
请输入一行文本:Hello World, this is C++!
单词个数:5
7. 常见错误
(1) 7.1 忘记 #include <string>
错误示例:
CPP
#include <iostream> // ❌ 忘记引入 string
int main() {
std::string name = "MOTO"; // ❌ 编译报错
return 0;
}
修复: 加 #include <string>。
(2) 7.2 用 cin >> 读取带空格的字符串
错误示例:
CPP
#include <iostream>
#include <string>
int main() {
std::string address;
std::cout << "请输入地址:";
std::cin >> address; // ❌ 遇到空格就停止
std::cout << "地址:" << address << std::endl;
return 0;
}
修复: 用 std::getline()。
❓ 常见问题
Q string 和 char 能互相转换吗? A:能! > > // string → char > std::string s = "Hello"; > const char cstr = s.c_str(); // 返回 const char > > // char → string > char cstr = "Hello"; > std::string s = cstr; // 自动转换 >**
Q:为什么我的 string 拼接很慢?
A 每次拼接都可能重新分配内存。如果要在循环里拼接,用
std::stringstream 或 std::string::reserve() 预分配空间。Q string 能存中文字符吗?
A 能!但要确保源文件是 UTF-8 编码,且终端支持 UTF-8。 > > std::string name = "张三"; // 可以存中文 > std::cout << name << std::endl; >
▶ 示例 3:字符串拼接与查找(难度⭐)
CPP
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + " " + s2;
std::cout << "拼接结果:" << s3 << std::endl;
size_t pos = s3.find("World");
if (pos != std::string::npos) {
std::cout << "找到World,位置:" << pos << std::endl;
}
return 0;
}
输出:
TEXT
📖 仅展示
拼接结果:Hello World
找到World,位置:6
💡 提示:C++的
std::string 支持 + 拼接,find() 查找返回位置或 npos(未找到)。
📖 小节
- string 是 C++ 的字符串类,比 C 风格字符串更安全、更易用
- 必须
`#include <string>` - 常用操作:
+/+=拼接、length()/size()获取长度、find()查找、substr()提取子串 - 读取整行用
std::getline() string会自动管理内存,不用担心缓冲区溢出
📝 作业
-
基础题 (Difficulty ⭐): 写一个程序,让用户输入两个字符串,拼接后输出。
-
进阶题 (Difficulty ⭐⭐): 写一个程序,让用户输入一个字符串,统计里面有多少个数字字符('0'-'9')。
-
挑战题 (Difficulty ⭐⭐⭐): 写一个程序,实现"简单的学生信息管理系统":
-
用
string存姓名、学号、专业 -
实现添加、查询、显示所有学生信息的功能
-
(选做)把数据保存到文件
- std::string 是 C++ 标准库字符串,自动管理内存
- string 支持 + 拼接、== 比较、 下标访问
- 常用方法:length/size/substr/find/append
- string 与 C 风格字符串互转:c_str()
- 处理输入时注意 getline 和 cin >> 混用的缓冲问题
8. 🚀 下一步
学会了 string,接下来我们学习 结构体(struct)(第20课)—— 把多个不同类型的变量组合成一个整体,是"类"的前奏!