C语言字符串操作汇总
C语言字符串操作汇总
这里提供C语言字符串操作汇总,AI含量过高,过几天会验证的。
字符串基础操作
字符串的初始化
在 C 语言中字符串本质上是以 \0
结尾的字符数组,因此初始化既可以通过字面量,也可以通过手动赋值构造。
初始化方式 | 示例 | 说明 |
---|---|---|
字面量初始化 | char s[] = "abc"; | 自动分配数组长度为 4,包括末尾 \0 |
指针指向常量区 | const char *p = "abc"; | 指向的是只读字符串常量,不可修改 |
指定长度初始化 | char s[32] = "abc"; | 剩余位置自动填充为 0 |
手动填充字符 | char s[32]; memset(s, 0, 32); strcpy(s,"abc"); | 先清空,再复制 |
初始化为空字符串 | char s[16] = {0}; 或 char s[16] = ""; | 一个只包含 \0 的字符串 |
🔎 注:
char* p = "abc"
中的"abc"
通常存放在 只读段,对其执行p[0] = 'x'
会导致段错误。- 如果需要修改字符串内容,应使用 字符数组(如
char s[]
)而不是指针常量。
✅ 示例
// 字面量初始化
char s1[] = "hello";// 指向常量字符串(只读)
const char *s2 = "hello";// 指定一个更大的缓冲区,为后续拼接做准备
char s3[64] = "hello";// 初始化为空字符串
char s4[32] = {0};// 使用 memset + strcpy
char s5[32];
memset(s5, 0, sizeof(s5));
strcpy(s5, "hello");
字符串的长度
在 C 语言中,字符串以 \0
作为结束标志,因此长度的计算方式是从首字符开始,直到遇到第一个 \0
为止的字符数。
标准库提供了用于计算长度的 API:strlen()
。
API | 头文件 | 功能说明 |
---|---|---|
size_t strlen(const char *s) | <string.h> | 返回字符串中 \0 之前的字符个数 |
⚠️ 注意事项
- 返回值不包含末尾的
\0
。 - 参数必须是以 \0 结尾的合法字符串,否则会造成越界读取。
- 复杂操作中(例如循环里反复调用)建议先保存长度,避免重复遍历。
✅ 示例
#include <stdio.h>
#include <string.h>int main(){char s[] = "hello";size_t len = strlen(s); // len = 5printf("length = %zu\n", len);// 典型用法:遍历字符串for(size_t i = 0; i < strlen(s); i++){ // ❌ 每次都会重新计算putchar(s[i]);}// 更好的写法size_t n = strlen(s);for(size_t i = 0; i < n; i++){ // ✅ 性能更优putchar(s[i]);}return 0;
}
字符串的修改
字符串内容可以通过索引直接修改,也可以通过内存函数批量修改。
场景 | 常用方法 |
---|---|
修改单个字符 | s[i] = 'X' |
批量替换 | memset , memmove , 手动循环 |
大小写转换 | toupper , tolower (需逐字符处理) |
示例
char s[] = "hello";
// 修改第一个字符
s[0] = 'H';// 批量修改
for (int i = 0; s[i]; i++) {if (s[i] >= 'a' && s[i] <= 'z') {s[i] = toupper(s[i]);}
}
字符串的追加
将一个字符串追加到另一个字符串的尾部,可以使用标准库函数或手动追加。
场景 | 方法 |
---|---|
简单追加 | strcat(dest, src) |
指定长度追加 | strncat(dest, src, n) |
手动追加 | memcpy 或逐字符复制 |
注意:dest
必须有足够的空间容纳追加后的内容。
示例
char dest[64] = "hello";
char src[] = " world";
strcat(dest, src); // dest = "hello world"// 指定添加前 3 个字符 => "hello wo"
char shortSrc[] = "world";
strncat(dest, shortSrc, 2);
字符串的删除
字符串没有现成的删除 API,通常通过移动后面的字符覆盖掉要删除的内容完成。
场景 | 方法 |
---|---|
删除某一段字符串 | memmove |
删除末尾字符 | s[len - 1] = '\0' |
示例:删除第 i 个位置开始的 n 个字符
char s[64] = "hello world";
int pos = 5; // 从第5个字符开始删除
int n = 1; // 删除1个字符(删除空格)// 将 "world\0" 移动到原先空格的位置
memmove(s + pos, s + pos + n, strlen(s) - pos - n + 1);// 结果: "helloworld"
场景 | 方法 |
---|---|
复制一个字符串 | strcpy , strncpy |
拼接字符串 | strcat , strncat |
格式化构造 | sprintf , snprintf |
注意事项
strcpy
、strcat
在目标缓冲区长度不足时会导致 越界写入sprintf
没有边界检查,建议使用snprintf
示例
char buf[32] = {0};
strcpy(buf, "hello");
strcat(buf, "_world");// 格式化构造
int id = 10;
snprintf(buf, sizeof(buf), "item_%d", id);
字符串比较与判断
strcmp 判断两个字符串是否相等
原型
int strcmp(const char *s1, const char *s2);
说明
按字典序比较字符串 s1 和 s2:
- 返回 0 表示相等
- 返回 <0 表示 s1 < s2
- 返回 >0 表示 s1 > s2
示例
char a[] = "apple";
char b[] = "banana";if (strcmp(a, b) == 0){printf("equal\n");
} else if (strcmp(a, b) < 0){printf("a < b\n");
} else {printf("a > b\n");
}
strncmp 比较字符串前n个字符是否相等
原型
int strncmp(const char *s1, const char *s2, size_t n);
说明
最多比较 前 n 个字符。常用于判断是否具有某个前缀。
示例
char s[] = "prefix_test";if (strncmp(s, "pre", 3) == 0) {printf("has prefix 'pre'\n");
}
字符串查询与解析
场景 | 方法 |
---|---|
查找字符 | strchr , strrchr |
查找子串 | strstr |
按格式解析 | sscanf |
按分隔符切割 | strtok |
当然,下面按照和之前一致的方式,以函数名为标题,依次补充 API 说明和示例。
strchr
原型
char *strchr(const char *s, int c);
说明
在字符串中查找第一次出现的字符 c
,返回指针;如果没找到,返回 NULL
。
示例
char s[] = "a:b:c";
char *p = strchr(s, ':');
if (p != NULL) {printf("first ':' at position %ld\n", p - s);
}
strrchr
原型
char *strrchr(const char *s, int c);
说明
在字符串中查找最后一次出现的字符 c
。
示例
char s[] = "a:b:c";
char *p = strrchr(s, ':');
if (p) {printf("last ':' at position %ld\n", p - s);
}
strstr
原型
char *strstr(const char *haystack, const char *needle);
说明
查找子串 needle
在 haystack
中第一次出现的位置,返回指针;找不到返回 NULL
。
示例
char s[] = "hello world";
char *p = strstr(s, "lo");
if (p) {printf("found at index %ld\n", p - s);
}
sscanf
原型
int sscanf(const char *str, const char *format, ...);
说明
按照 format
从字符串中解析数据,返回成功匹配的字段个数。
示例
char s[] = "10,3.14";
int i; float f;
if (sscanf(s, "%d,%f", &i, &f) == 2) {printf("i=%d, f=%f\n", i, f);
}
strtok
原型
char *strtok(char *str, const char *delim);
说明
按指定分隔符把字符串分成一段一段,每次调用返回一个 token。
⚠️ 注意:该函数会修改原始字符串。
示例
char s[] = "a,b,c";
char *p = strtok(s, ",");
while (p != NULL) {printf("%s\n", p);p = strtok(NULL, ",");
}
数值与字符串之间的转换
场景 | 方法 |
---|---|
int→string | snprintf , itoa |
string→int | atoi , strtol |
注意事项
atoi
没有错误检测,建议使用strtol
strtol
需要检查 errno 和 endptr
数值到字符串
sprintf / snprintf
char buf[32];
int n = 123;
snprintf(buf, sizeof(buf), "%d", n); // 十进制
itoa(十进制 / 十六进制 / 任意进制)
注意:
itoa
是扩展函数,不是标准 C,但在多数编译器中可用。
char buf[32];
int n = 255;
itoa(n, buf, 10); // 十进制 => "255"
itoa(n, buf, 16); // 十六进制 => "ff"
字符串到数值
atoi / strtol(十进制)
char *s = "123";
int n = atoi(s); // => 123// 推荐方式(可检测错误)
char *endptr;
long val = strtol(s, &endptr, 10);
strtol(任意进制)
char *s = "ff";
long v = strtol(s, NULL, 16); // => 255
atof / strtof(浮点)
char *s = "3.14";
float f = strtof(s, NULL); // => 3.14
double d = atof(s); // 同样支持
字符串输出
场景 | 方法 |
---|---|
输出到终端 | printf |
输出到缓冲区 | snprintf |
注意事项
- 输出到 char* 时 始终 指定缓冲区大小
- 避免使用未初始化的 char* 作为输出缓冲区
示例
char out[64];
snprintf(out, sizeof(out), "Name:%s Age:%d", name, age);
printf("%s\n", out);
字符串数组
好的,以下是**“字符数组(即存放多个 char*
的数组)”**这一部分的追加内容,只包含你要求的 4 个操作示例:
字符数组常用操作示例(char *arr[]
)
初始化字符串数组
// 静态初始化
char *arr[] = { "apple", "banana", "orange" };// 动态添加(提前申请空间)
char *arr2[10];
arr2[0] = "alpha";
arr2[1] = "beta";
获取数组大小
int count = sizeof(arr) / sizeof(arr[0]);
printf("size = %d\n", count);
增删改查
// 增加(假设当前已有3项)
arr2[3] = "gamma"; // append// 修改
arr2[1] = "new_beta";// 删除(把后面的元素向前移动)
int pos = 1; // 删除下标 1
int total = 4; // 当前数组元素个数
for(int i = pos; i < total - 1; i++){arr2[i] = arr2[i + 1];
}
total--;// 查找
for(int i = 0; i < total; i++){if(strcmp(arr2[i], "gamma") == 0){printf("found at %d\n", i);}
}
排序
#include <stdlib.h>
#include <string.h>// 比较函数
int cmp_str(const void *a, const void *b){const char *sa = *(const char **)a;const char *sb = *(const char **)b;return strcmp(sa, sb);
}int main(){char *arr[] = { "orange", "apple", "banana" };int n = sizeof(arr) / sizeof(arr[0]);qsort(arr, n, sizeof(char*), cmp_str);for(int i = 0; i < n; i++){printf("%s\n", arr[i]);}return 0;
}