字符串处理
翻译整理自 cppreference - cstring。
1. C 字符串的本质
C 中没有真正的字符串类型,字符串就是以 \0(空字符)结尾的字符数组:
char s[] = "Hello"; // 长度 5,占用 6 字节(含 \0)
sizeof(s); // 6
strlen(s); // 5
2. 字符串字面量
char *a = "Hello"; // 字面量在只读段
char b[] = "Hello"; // 拷贝到栈/数据段,可修改
字符串拼接:
char *s = "Hello, " "world"; // "Hello, world"
转义:
"\n\t\\\0\""3. 字符串初始化
char s[10] = "abc"; // 'a','b','c','\0', 后续 0
char s[10] = {'a','b','c','\0'};
char s[4] = "abc";4. <string.h> 常用函数
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
int strcmp(const char *a, const char *b);
int strncmp(const char *a, const char *b, size_t n);
char *strchr(const char *s, int c);
char *strstr(const char *s, const char *sub);
char *strtok(char *s, const char *delim);5. 拷贝字符串
char dst[10];
strcpy(dst, "hello"); // 安全:源串长度 < 10
strcpy不检查缓冲区,易溢出。推荐strncpy或snprintf:
strncpy(dst, src, sizeof(dst) - 1);
dst[sizeof(dst) - 1] = '\0'; // strncpy 不保证 \0 结尾
snprintf(dst, sizeof(dst), "%s", src); // 推荐
6. 拼接
char buf[64] = "Hello, ";
strncat(buf, "world!", sizeof(buf) - strlen(buf) - 1);
snprintf(buf, sizeof(buf), "%s %s", "Hello,", "world!");7. 比较
if (strcmp(a, b) == 0) {
// 相等
}
// 返回值 < 0 表示 a < b,> 0 表示 a > b
大小写不敏感比较需自行实现或用 strcasecmp(POSIX):
#include <strings.h>
if (strcasecmp("Hello", "HELLO") == 0) { ... }8. 查找
char *p = strchr("Hello, world", ',');
if (p) printf("位置 %ld\n", p - s);
char *sub = strstr("Hello, world", "world");
if (sub) printf("找到子串\n");9. 分割 strtok
char line[] = "name,age,city";
char *tok = strtok(line, ",");
while (tok) {
printf("%s\n", tok);
tok = strtok(NULL, ",");
}
strtok会修改原字符串,且非线程安全;推荐strtok_r(POSIX)或strtok_s(C11)。
10. 字符串转数字
int n = atoi("123");
long l = atol("99999");
double d = atof("3.14");
// 更安全:错误检查
char *end;
long v = strtol("0xff", &end, 16); // 255
11. 字符串数组与 main 参数
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}12. 长字符串处理
如果需要动态构造长字符串,建议用缓冲区或 snprintf:
char buf[256];
snprintf(buf, sizeof(buf),
"name=%s age=%d score=%.2f",
name, age, score);小结
C 字符串全靠库函数和约定维护,注意 \0 结尾与缓冲区大小就能避免绝大多数 bug。