2.“文字的魔法”:字符串
“文字的魔法”:字符串 (string 类的使用)
本章导读 (The Hook)
我们已经学会了用 char 来存储单个字符,比如 'A';也学会了用数组来存储一排 int 或 double。那么,我们最常打交道的文本,比如一个人的名字 "Li Hua",一句问候 "Hello, World!",应该如何存储呢?
一种朴素的想法是:用字符数组 char name[] = {'L', 'i', ' ', 'H', 'u', 'a'};。这在 C 语言中确实是这么做的,但它非常原始和危险,就像用一盘活字印刷的铅字来拼写单词,管理起来极其麻烦。
幸运的是,现代 C++ 早就为我们准备好了一件“神器”—— std::string!
你可以把 std::string 想象成一个智能化的、可伸缩的“文本盒子”。它不仅能帮你装下一整段文字,还自带了很多“魔法”技能:
- 它可以自动调整自己的大小来适应文字的长度。
- 你可以用
+号像拼接积木一样,把两个string连接起来。 - 你可以随时问它:“喂,你里面现在有多长?”,它会立刻告诉你。
这一章,我们将学习如何使用 string 这件神器。掌握了它,你就掌握了在 C++ 中处理一切文本信息的钥匙。
专业术语速查表 (Glossary)
点击展开/折叠本章术语表
string- 通俗比喻:一个智能的、专门用来存放一串文字的“魔法盒子”。
- 解释:C++ 标准库(Standard Library)中提供的一个类 (class),专门用于方便、安全地处理文本序列。
对象 (Object)
- 通俗比喻:一个“活”的、带有内置技能的“智能变量”。就像一台智能手机,它不仅有数据(照片、联系人),还有功能(打电话、拍照)。我们创建的每一个
string变量,都是一个string对象。 - 解释:类的实例。它是内存中一块包含了数据(成员变量)和可作用于这些数据的操作(成员函数/方法)的区域。
- 通俗比喻:一个“活”的、带有内置技能的“智能变量”。就像一台智能手机,它不仅有数据(照片、联系人),还有功能(打电话、拍照)。我们创建的每一个
方法 (Method) / 成员函数 (Member Function)
- 通俗比喻:对象自带的“技能”或“按钮”。我们通过
对象名.方法名()的形式来调用它。 - 解释:一个定义在类内部的函数,它作用于该类的对象。例如,
.length()就是string类的一个方法。
- 通俗比喻:对象自带的“技能”或“按钮”。我们通过
连接/拼接 (Concatenation)
- 通俗比喻:用“胶水”(
+号)把两个文本盒子里的内容粘在一起,形成一个更长的文本盒子。 - 解释:将两个或多个字符串首尾相连,创建一个新的字符串的过程。
- 通俗比喻:用“胶水”(
getline()- 通俗比喻:一个能“完整地读走一整行”的特殊指令。它会一直读取,直到遇到回车键为止。
- 解释:一个全局函数,用于从输入流中读取一整行文本(包括空格),并存入一个
string对象中。
核心概念讲解 (The Core Concept)
1. 使用 string 的第一步:引入头文件
string 不是 C++ 的基本内置类型(像 int double 那样),而是标准库提供的一个强大的工具。要使用它,必须先告诉编译器我们要用这个工具箱:
#include <string> // 必须包含这个头文件!2. string 的声明、初始化与输入输出
#include <iostream>
#include <string> // 别忘了它!
using namespace std;
int main() {
// --- 声明和初始化 ---
string name1; // 创建一个空的 string 对象
string greeting = "你好, "; // 创建的同时存入初始文字
string name2 = "李华";
// --- 输出 ---
cout << greeting << name2 << "!" << endl; // 输出:你好, 李华!
// --- 输入 (有陷阱!) ---
cout << "请输入你的姓氏: ";
string lastName;
cin >> lastName; // cin 会在遇到第一个空格或回车时停止读取
cout << "你的姓氏是: " << lastName << endl;
cout << "请输入你的座右铭 (可以带空格): ";
string motto;
// cin >> motto; // 如果用 cin,只能读到第一个空格前
// getline 是读取一整行文本的正确方式!
cin.ignore(); // !! 这是一个重要技巧,见下面的防坑指南 !!
getline(cin, motto);
cout << "你的座右铭是: \"" << motto << "\"" << endl;
return 0;
}getline(cin, 字符串变量) 是专门用来解决 cin >> 无法读取带空格文本的问题的。
3. string 的核心“魔法”
魔法一:用
+号拼接字符串string firstName = "张"; string lastName = "三"; string fullName = firstName + lastName; // 轻松拼接 cout << "全名: " << fullName << endl; // 输出: 全名: 张三魔法二:用
.length()获取长度
注意这个.的用法,我们称之为“点运算符”,用来调用对象的方法。string password = "abc12345"; cout << "你的密码长度是: " << password.length() << " 位。" << endl; // 输出: 8 // .size() 和 .length() 功能完全一样,用哪个都行 cout << "密码长度也可以用 .size() 获取: " << password.size() << " 位。" << endl;魔法三:像数组一样用
[]访问单个字符string的底层其实就是一个字符数组,所以我们可以用熟悉的[]配合索引来操作。string message = "Hello"; // 索引同样从 0 开始 char firstChar = message; // 'H' char lastChar = message[message.length() - 1]; // 最后一个字符的索引是 长度-1 cout << "第一个字符是: " << firstChar << endl; cout << "最后一个字符是: " << lastChar << endl; // 也可以修改 message = 'J'; cout << "修改后的消息: " << message << endl; // 输出: Jello
动手试试 (Try It Yourself!)
用户信息卡
- 编写一个程序,依次提示用户输入姓名、年龄和城市。
- 将这些信息用
string的+拼接成一个完整的句子。 - 例如,如果输入 "张三", "20", "北京",则最后打印出:"用户信息:姓名-张三, 年龄-20, 居住城市-北京。"
- 提示:年龄是
int,需要先读入int变量,拼接时可以再处理。但为了简化,本题你可以先把年龄也当作string来读入。
简单回文判断
- 回文是指正着读和倒着读都一样的字符串,比如 "level", "madam"。
- 让用户输入一个不带空格的单词。
- 使用
for循环和[]运算符,判断这个单词是不是回文。 - 思路:比较第 0 个字符和最后一个字符,第 1 个字符和倒数第二个字符... 是否都相等。只需要比较到字符串的中间位置即可。
“简单回文判断”参考答案 (点击展开)
#include <iostream>
#include <string>
using namespace std;
int main() {
string word;
cout << "请输入一个不带空格的英文单词: ";
cin >> word;
bool isPalindrome = true; // 先假设它是回文
int len = word.length();
// 只需要循环到字符串的一半
for (int i = 0; i < len / 2; i++) {
cout << "正在比较: " << word[i] << " 和 " << word[len - 1 - i] << endl;
// 比较头尾对应的字符
if (word[i] != word[len - 1 - i]) {
isPalindrome = false; // 只要有一对不相等,就不是回文
break; // 无需再比较了,直接跳出循环
}
}
cout << "------------------------" << endl;
if (isPalindrome) {
cout << "单词 \"" << word << "\" 是一个回文。" << endl;
} else {
cout << "单词 \"" << word << "\" 不是一个回文。" << endl;
}
return 0;
}“防坑”指南与常见错误 (The Pitfalls)
致命错误:忘记 #include <string>
如果你使用了 string 但忘记包含头文件,编译器会报出 'string' was not declared in this scope 这样的错误,意思是它根本不认识 string 是什么东西。这是新手使用 string 时排名第一的错误。
巨大陷阱:混用 cin >> 和 getline()
这是一个非常隐蔽但极为常见的 bug。
cout << "请输入你的年龄: ";
int age;
cin >> age; // 用户输入 20 然后敲了回车
cout << "请输入你的全名: ";
string fullName;
getline(cin, fullName); // 问题在这里!
cout << age << "岁的" << fullName << "你好!" << endl;当你为 age 输入 20 并敲下回车时,cin >> age; 只会取走 20,那个回车符(\n)还留在输入缓冲区里。紧接着 getline 开始工作,它一上来就看到了这个被遗弃的回车符,以为“哦,这一行结束了”,于是它读入了一个空字符串!
解决方案:在 cin >> ... 之后,getline(...) 之前,手动“吃掉”那个多余的回车符。cin.ignore(); // 这行代码会读取并丢弃输入缓冲区中的一个字符(正好是那个回车符)
本章小结 (The Summary)
我们解锁了处理文本的“魔法”!
std::string是 C++ 中处理字符串的首选工具,它安全、方便、功能强大。- 使用前必须
#include <string>。 +号可以轻松拼接字符串;.length()或.size()可以获取其长度。- 我们可以像操作数组一样,用
[]和索引来访问string中的单个字符。 - 读取不带空格的文本用
cin >>,读取一整行(包括空格)必须使用getline(cin, ...)。 - 要警惕
cin >>和getline()混用时,遗留在缓冲区里的回车符问题,并用cin.ignore()来解决。
我们现在已经有了可以组织数据的“容器”(数组和字符串)。但当我们的程序逻辑越来越复杂时,main 函数会变得越来越臃肿。是时候学习如何组织我们的代码了。下一章,我们将学习编程中最核心的概念之一——“代码食谱”:函数的定义与调用。
