C++字符数组与字符串 #
一、字符数组概述 #
字符数组用于存储字符序列,是C风格字符串的基础。
1.1 声明字符数组 #
cpp
char str[10]; // 声明可存储9个字符的数组(最后一个存'\0')
char name[20];
char buffer[100];
1.2 初始化字符数组 #
cpp
// 逐个字符初始化
char str[5] = {'H', 'e', 'l', 'l', 'o'};
// 字符串字面量初始化
char str2[6] = "Hello"; // 自动添加'\0'
// 省略大小
char str3[] = "Hello"; // 大小为6
// 部分初始化
char str4[10] = "Hi"; // {'H', 'i', '\0', '\0', ...}
二、C风格字符串 #
2.1 字符串结束符 #
C风格字符串以空字符 \0 结尾:
cpp
char str[] = "Hello";
// 实际存储:'H' 'e' 'l' 'l' 'o' '\0'
// 数组大小为6,字符串长度为5
2.2 字符串长度 #
cpp
#include <cstring>
char str[] = "Hello";
size_t len = strlen(str); // 5
// 手动计算长度
int length = 0;
while (str[length] != '\0') {
length++;
}
三、字符串输入输出 #
3.1 输出字符串 #
cpp
char str[] = "Hello";
// 使用cout
std::cout << str << std::endl;
// 使用printf
printf("%s\n", str);
// 逐字符输出
for (int i = 0; str[i] != '\0'; i++) {
std::cout << str[i];
}
3.2 输入字符串 #
cpp
char name[50];
// cin(遇到空格停止)
std::cout << "输入姓名: ";
std::cin >> name;
// cin.getline(读取整行)
std::cout << "输入地址: ";
std::cin.getline(name, 50);
// fgets(C风格)
fgets(name, 50, stdin);
3.3 输入问题 #
cpp
char name[50], city[50];
std::cin >> name; // 输入 "Zhang San"
// name = "Zhang","San"留在缓冲区
std::cin >> city; // city = "San"
// 解决:使用getline
std::cin.getline(name, 50); // 读取整行
四、字符串函数 #
4.1 字符串长度 #
cpp
#include <cstring>
char str[] = "Hello";
size_t len = strlen(str); // 5
4.2 字符串复制 #
cpp
#include <cstring>
char dest[20];
char src[] = "Hello";
// strcpy:复制字符串
strcpy(dest, src); // dest = "Hello"
// strncpy:指定长度复制
strncpy(dest, src, 3); // dest = "Hel"
dest[3] = '\0'; // 手动添加结束符
4.3 字符串连接 #
cpp
#include <cstring>
char str1[20] = "Hello";
char str2[] = " World";
// strcat:连接字符串
strcat(str1, str2); // str1 = "Hello World"
// strncat:指定长度连接
char str3[20] = "Hello";
strncat(str3, str2, 3); // str3 = "Hello Wo"
4.4 字符串比较 #
cpp
#include <cstring>
char str1[] = "Hello";
char str2[] = "World";
char str3[] = "Hello";
// strcmp:比较字符串
int result1 = strcmp(str1, str2); // < 0(str1 < str2)
int result2 = strcmp(str1, str3); // 0(相等)
int result3 = strcmp(str2, str1); // > 0(str2 > str1)
// strncmp:比较前n个字符
int result4 = strncmp(str1, str3, 3); // 0
4.5 字符串查找 #
cpp
#include <cstring>
char str[] = "Hello World";
// strchr:查找字符
char* p1 = strchr(str, 'o'); // 指向第一个'o'
if (p1) std::cout << "找到: " << p1 << std::endl; // "o World"
// strrchr:从后查找字符
char* p2 = strrchr(str, 'o'); // 指向最后一个'o'
// strstr:查找子串
char* p3 = strstr(str, "World");
if (p3) std::cout << "找到子串" << std::endl;
4.6 其他函数 #
cpp
#include <cstring>
char str[] = "Hello";
// strcpy + strcat 的组合
char dest[50];
sprintf(dest, "%s %s", "Hello", "World"); // "Hello World"
五、字符处理函数 #
5.1 字符分类 #
cpp
#include <cctype>
char c = 'A';
isalpha(c); // 是否字母
isdigit(c); // 是否数字
isalnum(c); // 是否字母或数字
isspace(c); // 是否空白字符
isupper(c); // 是否大写
islower(c); // 是否小写
ispunct(c); // 是否标点符号
isprint(c); // 是否可打印字符
5.2 字符转换 #
cpp
#include <cctype>
char c = 'A';
tolower(c); // 转小写:'a'
toupper(c); // 转大写:'A'
5.3 字符串大小写转换 #
cpp
#include <cctype>
#include <cstring>
void toUpperString(char* str) {
for (int i = 0; str[i]; i++) {
str[i] = toupper(str[i]);
}
}
void toLowerString(char* str) {
for (int i = 0; str[i]; i++) {
str[i] = tolower(str[i]);
}
}
六、字符串转换 #
6.1 字符串转数字 #
cpp
#include <cstdlib>
char numStr[] = "12345";
int i = atoi(numStr); // 12345
long l = atol(numStr); // 12345L
double d = atof("3.14"); // 3.14
// 更安全的转换
char* end;
long val = strtol("12345abc", &end, 10); // val = 12345, end指向"abc"
double val2 = strtod("3.14abc", &end); // val2 = 3.14
6.2 数字转字符串 #
cpp
#include <cstdio>
char buffer[50];
// 使用sprintf
int num = 12345;
sprintf(buffer, "%d", num); // "12345"
sprintf(buffer, "%f", 3.14); // "3.140000"
sprintf(buffer, "%x", 255); // "ff"
七、字符串数组 #
7.1 字符串数组 #
cpp
// 二维字符数组
char names[3][20] = {
"Alice",
"Bob",
"Charlie"
};
// 指针数组
const char* fruits[] = {
"Apple",
"Banana",
"Cherry"
};
// 访问
std::cout << names[0] << std::endl; // "Alice"
std::cout << fruits[1] << std::endl; // "Banana"
7.2 命令行参数 #
cpp
int main(int argc, char* argv[]) {
std::cout << "程序名: " << argv[0] << std::endl;
for (int i = 1; i < argc; i++) {
std::cout << "参数" << i << ": " << argv[i] << std::endl;
}
return 0;
}
八、安全操作 #
8.1 缓冲区溢出 #
cpp
char buffer[10];
// 危险:可能导致溢出
strcpy(buffer, "This is a very long string");
// 安全:使用strncpy
strncpy(buffer, "This is a very long string", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
8.2 安全函数(可选) #
cpp
// 某些编译器提供安全版本
// strcpy_s, strcat_s 等
#ifdef _WIN32
strcpy_s(buffer, sizeof(buffer), "Hello");
#else
strncpy(buffer, "Hello", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
#endif
九、std::string vs C风格字符串 #
9.1 对比 #
| 特性 | C风格字符串 | std::string |
|---|---|---|
| 内存管理 | 手动 | 自动 |
| 大小获取 | strlen() | size() |
| 拼接 | strcat() | + 或 append() |
| 比较 | strcmp() | == |
| 安全性 | 易溢出 | 安全 |
9.2 相互转换 #
cpp
#include <string>
// std::string 转 C风格字符串
std::string cppStr = "Hello";
const char* cStr = cppStr.c_str();
// C风格字符串转 std::string
char cStr2[] = "World";
std::string cppStr2 = cStr2;
9.3 推荐使用std::string #
cpp
// C风格
char str1[50] = "Hello";
strcat(str1, " World");
// C++风格(推荐)
std::string str2 = "Hello";
str2 += " World";
十、实际应用 #
10.1 字符串分割 #
cpp
#include <cstring>
void splitString(const char* str, char delimiter) {
char buffer[100];
strcpy(buffer, str);
char* token = strtok(buffer, &delimiter);
while (token != nullptr) {
std::cout << token << std::endl;
token = strtok(nullptr, &delimiter);
}
}
// 使用
splitString("Hello,World,C++", ',');
10.2 去除空白 #
cpp
#include <cctype>
void trim(char* str) {
// 去除前导空白
char* start = str;
while (isspace(*start)) start++;
// 去除尾部空白
char* end = str + strlen(str) - 1;
while (end > start && isspace(*end)) end--;
// 移动字符串
memmove(str, start, end - start + 1);
str[end - start + 1] = '\0';
}
十一、总结 #
C风格字符串函数 #
| 函数 | 作用 |
|---|---|
| strlen | 获取长度 |
| strcpy | 复制 |
| strcat | 连接 |
| strcmp | 比较 |
| strchr | 查找字符 |
| strstr | 查找子串 |
最佳实践 #
- 优先使用std::string
- 注意缓冲区大小
- 使用安全的字符串函数
- 检查返回值
下一步,让我们学习函数!
最后更新:2026-03-26