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 查找子串

最佳实践 #

  1. 优先使用std::string
  2. 注意缓冲区大小
  3. 使用安全的字符串函数
  4. 检查返回值

下一步,让我们学习函数!

最后更新:2026-03-26