C++: C风格字符串
最后更新:2026-08-26
C++ 有两种字符串:
- C 风格字符串(字符数组)
- C++ string(后面会学)
这一课先学 C 风格字符串——它是 C++ 兼容 C 语言的遗产,理解它有助于理解字符串的底层原理。
1. 什么是 C 风格字符串?
(1) 1.1 本质:字符数组 + 结束符
C 风格字符串就是一个字符数组,但有个特殊规定:
- 最后一个字符必须是
\0(空字符,ASCII 码是 0) \0用来标记字符串的结束
"Hello" 在内存里是:
+---+---+---+---+---+----+
| H | e | l | l | o | \0 |
+---+---+---+---+---+----+
0 1 2 3 4 5 ← 下标
💡 重点: C 风格字符串的长度是 5(Hello),但数组大小至少是 6(要存 \0)。
2. 声明与初始化
(1) 2.1 声明 C 风格字符串
语法:
char 字符串名[大小];
示例:
▶ 示例 2:基础编程实践(难度⭐)
#include <iostream>
int main() {
char name[20]; // 能存 19 个字符 + 1 个 \0
name[0] = 'H';
name[1] = 'e';
name[2] = 'l';
name[3] = 'l';
name[4] = 'o';
name[5] = '\0'; // 别忘了结束符!
std::cout << "名字:" << name << std::endl; // Hello
return 0;
}
输出:
名字:Hello
💡 提示: 手动加 \0 很麻烦,后面会学更简单的方法。
(2) 2.2 初始化 C 风格字符串
方法一:用字符串字面量初始化
#include <iostream>
int main() {
char name = "Hello"; // ✅ 编译器自动加 \0,数组大小是 6
std::cout << "名字:" << name << std::endl;
return 0;
}
💡 重点: 用字符串字面量初始化时,不用写数组大小——编译器会自动计算(包括 \0)。
3. 常用字符串函数
C 风格字符串的函数都在 cstring 头文件里。
(1) 3.1 strlen:计算字符串长度
#include <iostream>
#include <cstring> // 必须引入这个头文件
int main() {
char name = "Hello";
std::cout << "字符串:" << name << std::endl;
std::cout << "长度:" << std::strlen(name) << std::endl; // 5(不包括 \0)
return 0;
}
💡 提示: std::strlen 返回的是有效字符数(不包括 \0),而 sizeof 返回的是数组大小(包括 \0)。
char name = "Hello";
std::cout << sizeof(name) << std::endl; // 6(数组大小)
std::cout << std::strlen(name) << std::endl; // 5(有效字符数)
(2) 3.2 strcpy:复制字符串
#include <iostream>
#include <cstring>
int main() {
char src = "Hello";
char dest[20];
std::strcpy(dest, src); // 把 src 复制到 dest
std::cout << "src:" << src << std::endl;
std::cout << "dest:" << dest << std::endl;
return 0;
}
⚠️ 警告: std::strcpy 不会检查目标数组的大小,如果 dest 太小,会缓冲区溢出!
更安全的函数(C++11 之后):
std::strncpy(dest, src, sizeof(dest) - 1); // 最多复制 sizeof(dest)-1 个字符
dest[sizeof(dest) - 1] = '\0'; // 手动加结束符
(3) 3.3 strcat:连接字符串
#include <iostream>
#include <cstring>
int main() {
char greeting[50] = "Hello, ";
char name = "World";
std::strcat(greeting, name); // 把 name 连接到 greeting 后面
std::cout << greeting << std::endl; // Hello, World
return 0;
}
(4) 3.4 strcmp:比较字符串
#include <iostream>
#include <cstring>
int main() {
char str1 = "Hello";
char str2 = "Hello";
char str3 = "World";
std::cout << "strcmp(str1, str2) = " << std::strcmp(str1, str2) << std::endl;
std::cout << "strcmp(str1, str3) = " << std::strcmp(str1, str3) << std::endl;
return 0;
}
返回值:
0:两个字符串相等< 0:第一个字符串小于第二个> 0:第一个字符串大于第二个
💡 提示: 不要用 == 比较 C 风格字符串!== 比较的是地址,不是内容。
char str1 = "Hello";
char str2 = "Hello";
if (str1 == str2) { // ❌ 错误:比较的是地址,不是内容
// ...
}
if (std::strcmp(str1, str2) == 0) { // ✅ 正确:用 strcmp 比较内容
// ...
}
4. 用 cin 和 cout 处理 C 风格字符串
(1) 4.1 读取字符串
#include <iostream>
int main() {
char name[20];
std::cout << "请输入名字:";
std::cin >> name; // ✅ 可以读取字符串(但不能有空格)
std::cout << "你好," << name << "!" << std::endl;
return 0;
}
💡 问题: cin >> 遇到空格就停止!如果输入 "John Smith",只能读到 "John"。
解决方法:用 std::cin.getline
#include <iostream>
int main() {
char name[50];
std::cout << "请输入全名:";
std::cin.getline(name, 50); // ✅ 读取整行(包括空格)
std::cout << "你好," << name << "!" << std::endl;
return 0;
}
5. 实战:简单的字符串处理
▶ 示例 1:统计字符串中元音的个数(难度⭐⭐)
#include <iostream>
#include <cstring>
int main() {
char str[100];
std::cout << "请输入一个字符串:";
std::cin.getline(str, 100);
int vowels = 0;
for (int i = 0; i < std::strlen(str); i++) {
char c = str[i];
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
vowels++;
}
}
std::cout << "元音个数:" << vowels << std::endl;
return 0;
}
输出:
请输入一个字符串:
元音个数:
运行效果:
请输入一个字符串:Hello World
元音个数:3
6. 常见错误
(1) 6.1 忘记留空间给 \0
错误示例:
#include <iostream>
int main() {
char name[5] = "Hello"; // ❌ 错误:"Hello" 需要 6 个字符(包括 \0),但数组大小只有 5
std::cout << name << std::endl;
return 0;
}
修复:
char name[6] = "Hello"; // ✅ 正确:数组大小至少是 6
(2) 6.2 用 = 赋值字符串
错误示例:
#include <iostream>
int main() {
char str1[20];
char str2 = "Hello";
str1 = str2; // ❌ 错误:不能给数组赋值
str1 = "World"; // ❌ 错误:不能给数组赋值
return 0;
}
修复:用 strcpy
#include <iostream>
#include <cstring>
int main() {
char str1[20];
char str2 = "Hello";
std::strcpy(str1, str2); // ✅ 正确:用 strcpy 复制
std::cout << str1 << std::endl;
return 0;
}
❓ 常见问题
Q:什么时候用 C 风格字符串,什么时候用 C++ string? A:优先用 C++ string(后面会学),除非: > 1. 你在维护旧代码(C 语言代码) > 2. 你在做极底层的优化(C 风格字符串效率更高)
C++ string 更安全、更易用,推荐新手使用。
Q:为什么 char name = "Hello" 可以,但 int arr = {1, 2, 3} 不行? A:只有字符串字面量能直接用来初始化字符数组。
CPPchar name = "Hello"; // 可以 int arr = {1, 2, 3}; // 可以(这是初始化列表,不是字符串字面量)
Q:怎么把 C 风格字符串转换成 C++ string?
A: 可以直接赋值(C++ string 的构造函数会自动转换)。
CPP#include `<iostream>` #include `<string>` int main() { char cstr[] = "Hello"; std::string cppStr = cstr; // 自动转换 std::cout << cppStr << std::endl; return 0; }
▶ 示例 3:字符串长度与复制(难度⭐)
#include <iostream>
#include <cstring>
int main() {
char src[] = "Hello";
char dest[20];
std::cout << "src长度:" << strlen(src) << std::endl;
strcpy(dest, src);
std::cout << "复制后:" << dest << std::endl;
return 0;
}
输出:
src长度:5
复制后:Hello
strlen() 获取长度,用 strcpy() 复制。注意目标数组要足够大!
📖 小节
- C 风格字符串是字符数组,以
\0结束 - 常用函数:
strlen(长度)、strcpy(复制)、strcat(连接)、strcmp(比较) - 不要用
==比较 C 风格字符串,用strcmp - 不要用
=赋值 C 风格字符串,用strcpy - C 风格字符串不安全(容易缓冲区溢出),优先用 C++ string
📝 作业
-
基础题 (Difficulty ⭐): 声明一个 C 风格字符串
char str = "Hello, World!",输出它的长度和每个字符。 -
进阶题 (Difficulty ⭐⭐): 写一个程序,让用户输入两个字符串,比较它们是否相等(用
strcmp)。 -
挑战题 (Difficulty ⭐⭐⭐): 写一个程序,实现"字符串反转":
-
让用户输入一个字符串
-
把它反转(如
"Hello"变成"olleH") -
用 C 风格字符串实现(不能用 C++ string)
- C 风格字符串:字符数组以 \0 结尾
- 常用函数:strlen/strcpy/strcat/strcmp
- C 字符串用双引号初始化,char 数组要预留 \0 空间
- 缺点:不安全(缓冲区溢出)、操作麻烦
- 现代 C++ 推荐用 std::string 替代 C 风格字符串
7. 🚀 下一步
学会了 C 风格字符串,接下来我们学习 C++ string(第19课)—— 更安全、更易用的字符串类!