C 语言部分字符字符串函数与内存函数库函数
函数组核心差异适用场景strcpy 无长度限制(不安全),strncpy 有长度限制字符串拷贝,优先用 strncpy 保证安全strcat 无长度限制(不安全),strncat 有长度限制字符串追加,优先用 strncatmemcpy 不支持重叠,memmove 支持重叠内存拷贝,有重叠用 memmove,否则均可strcmp 全量比较,strncmp 部分比较全量比较用 strcmp,部分比较
·
一、字符函数:专注单个字符的分类与转换
字符函数主要处理单个字符的属性判断和大小写转换,使用前需包含头文件 <ctype.h>。
1. 字符分类函数:判断字符属性
这类函数的参数是字符(本质是 ASCII 码值,接收int类型),返回非 0 值表示 “符合条件”,返回 0 表示 “不符合”。常用函数及功能如下:
| 函数名 | 功能描述 |
|---|---|
islower |
判断字符是否为小写字母(a-z) |
isupper |
判断字符是否为大写字母(A-Z) |
isdigit |
判断字符是否为十进制数字(0-9) |
isalpha |
判断字符是否为字母(a-z 或 A-Z) |
isalnum |
判断字符是否为字母或数字(a-z、A-Z、0-9) |
isspace |
判断字符是否为空白字符(空格、换行 \n、制表符 \t 等) |
ispunct |
判断字符是否为标点符号(非字母、非数字的可打印图形字符) |
使用示例:将字符串中的小写字母转为大写,其他字符不变
#include <stdio.h>
#include <ctype.h>
int main() {
char str[] = "Test String. 123!";
int i = 0;
while (str[i]) {
if (islower(str[i])) { // 判断是否为小写字母
str[i] = toupper(str[i]); // 转为大写
}
putchar(str[i]);
i++;
}
// 输出:TEST STRING. 123!
return 0;
}
2. 字符转换函数:大小写互转
int toupper(int c):将小写字母转为大写,非小写字母返回原字符;int tolower(int c):将大写字母转为小写,非大写字母返回原字符。
核心注意:函数参数接收int类型(实际是字符的 ASCII 码),返回值也是 ASCII 码,需赋值给字符变量使用。
二、字符串函数:处理字符串的核心工具
字符串函数专注于字符串的长度计算、拷贝、追加、比较、查找、分割等操作,使用前需包含头文件 <string.h>。
1. 字符串长度计算:strlen
- 功能:统计字符串中
'\0'之前的字符个数(不包含'\0'); - 原型:
size_t strlen(const char *str); - 参数:
str指向待统计的字符串(必须以'\0'结束); - 返回值:
size_t(无符号整数),表示字符串长度; - 关键注意:
- 字符串必须以
'\0'结尾,否则会越界查找,结果不确定; - 返回值是无符号数,比较时需注意(如
strlen("a") - strlen("abc")结果是无符号的大正数,而非 - 2)。
- 字符串必须以
模拟实现思路(3 种常用方式):
- 计数器法:遍历字符串,遇到
'\0'停止,统计次数; - 递归法:递归遍历,直到
'\0'返回 0,否则返回1 + 递归结果; - 指针 - 指针法:用两个指针,一个指向字符串首,一个遍历到
'\0',返回两指针差值。
2. 字符串拷贝:strcpy vs strncpy
(1)strcpy(不安全版本)
- 功能:将源字符串(包含
'\0')完整拷贝到目标空间; - 原型:
char *strcpy(char *destination, const char *source); - 注意事项:
- 源字符串必须以
'\0'结束,否则拷贝会越界; - 目标空间必须足够大,能容纳源字符串(含
'\0'); - 目标空间必须可修改(不能是字符串常量,如
char *dest = "abc"); - 返回目标空间起始地址,支持链式调用。
- 源字符串必须以
(2)strncpy(安全版本)
- 功能:最多拷贝
num个字符到目标空间,解决 strcpy 的越界问题; - 原型:
char *strncpy(char *destination, const char *source, size_t num); - 核心差异:
- 多了
num参数,指定最大拷贝长度; - 源字符串无需以
'\0'结束,拷贝num个字符后停止; - 若源字符串长度小于
num,剩余部分会填充'\0'。
- 多了
3. 字符串追加:strcat vs strncat
(1)strcat(不安全版本)
- 功能:将源字符串追加到目标字符串末尾(覆盖目标字符串的
'\0',并在末尾加'\0'); - 原型:
char *strcat(char *destination, const char *source); - 注意事项:
- 源字符串必须以
'\0'结束,目标字符串也需有'\0'(确定追加起始位置); - 目标空间必须足够大,容纳原目标字符串 + 源字符串(含
'\0')。
- 源字符串必须以
(2)strncat(安全版本)
- 功能:最多追加
num个字符到目标字符串,自动在末尾加'\0'; - 原型:
char *strncat(char *destination, const char *source, size_t num); - 优势:指定追加长度,避免越界,更灵活安全。
4. 字符串比较:strcmp vs strncmp
(1)strcmp(全量比较)
- 功能:从字符串第一个字符开始,按 ASCII 码值逐字符比较,直到遇到不同字符或
'\0'; - 原型:
int strcmp(const char *str1, const char *str2); - 返回值:
- 大于 0:str1 大于 str2(第一个不同字符的 ASCII 码差值);
- 等于 0:str1 与 str2 完全相等;
- 小于 0:str1 小于 str2。
(2)strncmp(部分比较)
- 功能:最多比较
num个字符,解决 strcmp 全量比较的冗余问题; - 原型:
int strncmp(const char *str1, const char *str2, size_t num); - 适用场景:只需比较字符串前 n 个字符(如判断文件后缀名、版本号前缀等)。
5. 字符串查找:strstr
- 功能:在字符串
str1中查找子字符串str2第一次出现的位置; - 原型:
char *strstr(const char *str1, const char *str2); - 返回值:
- 找到:返回子字符串首次出现的起始地址;
- 未找到:返回
NULL;
- 特殊情况:若
str2为空字符串,直接返回str1。
6. 字符串分割:strtok
- 功能:按指定分隔符分割字符串(会修改原始字符串);
- 原型:
char *strtok(char *str, const char *delim); - 参数说明:
- 首次调用:
str传入待分割字符串;后续调用:str传入NULL,表示继续分割同一个字符串; delim是分隔符集合(每个字符都是独立分隔符);
- 首次调用:
- 注意事项:
- 会修改原始字符串,将分隔符替换为
'\0',需保留原字符串时先拷贝; - 多个连续分隔符视为单个分隔符,不会返回空字符串;
- 分割完成后返回
NULL。
- 会修改原始字符串,将分隔符替换为
使用示例:分割 IP 地址192.168.6.111
#include <stdio.h>
#include <string.h>
int main() {
char arr[] = "192.168.6.111";
char buf[30];
strcpy(buf, arr); // 拷贝原字符串,避免修改
const char *sep = ".";
char *str = strtok(buf, sep);
while (str != NULL) {
printf("%s\n", str);
str = strtok(NULL, sep); // 后续调用传入NULL
}
// 输出:192、168、6、111
return 0;
}
7. 错误信息获取:strerror
- 功能:将错误码(
errno)转换为对应的错误信息字符串; - 原型:
char *strerror(int errnum); - 使用场景:库函数调用失败时(如
fopen打开不存在的文件),通过errno获取错误码,再用strerror获取可读错误信息; - 辅助函数:
perror(const char *str),直接打印错误信息(先打印str,再打印冒号 + 空格 + 错误信息)。
使用示例:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
FILE *pFile = fopen("nonexist.txt", "r"); // 打开不存在的文件
if (pFile == NULL) {
printf("strerror: %s\n", strerror(errno)); // 输出错误信息
perror("perror"); // 直接打印,格式更简洁
return 1;
}
fclose(pFile);
return 0;
}
三、内存函数:按字节操作的通用工具
内存函数不关注数据类型,按字节对内存块进行拷贝、设置、比较,适用范围更广(可操作 int、float、结构体等),使用前需包含头文件 <string.h>。
1. 内存拷贝:memcpy vs memmove
(1)memcpy(不支持重叠)
- 功能:从源内存块拷贝
num个字节到目标内存块; - 原型:
void *memcpy(void *destination, const void *source, size_t num); - 核心特点:
- 不区分数据类型,按字节拷贝;
- 源内存块和目标内存块重叠时,拷贝结果未定义(可能出错);
- 参数
destination和source为void*,需强制类型转换后操作。
(2)memmove(支持重叠)
- 功能:与 memcpy 一致,但支持源和目标内存块重叠;
- 原型:
void *memmove(void *destination, const void *source, size_t num); - 实现逻辑:
- 若目标地址 <= 源地址 或 目标地址>= 源地址 + num(无重叠):从低地址到高地址拷贝;
- 若存在重叠:从高地址到低地址拷贝,避免覆盖源数据。
使用示例(处理内存重叠):
#include <stdio.h>
#include <string.h>
int main() {
int arr[] = {1,2,3,4,5,6,7,8,9,10};
memmove(arr+2, arr, 20); // 拷贝前5个元素(20字节)到arr[2]开始的位置
for (int i=0; i<10; i++) {
printf("%d ", arr[i]); // 输出:1 2 1 2 3 4 5 8 9 10
}
return 0;
}
2. 内存设置:memset
- 功能:将指定内存块的
num个字节设置为特定值; - 原型:
void *memset(void *ptr, int value, size_t num); - 关键注意:
- 按字节设置,
value会被转换为unsigned char; - 不能直接设置非字符类型的数组(如
int arr[5]; memset(arr, 1, 20),结果是每个字节为 1,每个 int 值为0x01010101,而非 1);
- 按字节设置,
- 适用场景:初始化字符数组、清空内存块等。
使用示例:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "hello world";
memset(str, 'x', 6); // 将前6个字节设为'x'
printf("%s", str); // 输出:xxxxxxworld
return 0;
}
3. 内存比较:memcmp
- 功能:比较两块内存块的前
num个字节(按unsigned char值比较); - 原型:
int memcmp(const void *ptr1, const void *ptr2, size_t num); - 返回值:
- 大于 0:ptr1 的第一个不同字节大于 ptr2;
- 等于 0:前
num个字节完全相等; - 小于 0:ptr1 的第一个不同字节小于 ptr2;
- 优势:可比较任意类型的内存块(如结构体、数组等)。
四、核心函数对比与使用场景总结
| 函数组 | 核心差异 | 适用场景 |
|---|---|---|
| strcpy/strncpy | strcpy 无长度限制(不安全),strncpy 有长度限制 | 字符串拷贝,优先用 strncpy 保证安全 |
| strcat/strncat | strcat 无长度限制(不安全),strncat 有长度限制 | 字符串追加,优先用 strncat |
| memcpy/memmove | memcpy 不支持重叠,memmove 支持重叠 | 内存拷贝,有重叠用 memmove,否则均可 |
| strcmp/strncmp | strcmp 全量比较,strncmp 部分比较 | 全量比较用 strcmp,部分比较用 strncmp |
| 字符串函数 / 内存函数 | 字符串函数依赖'\0',内存函数按字节操作 |
字符串用字符串函数,其他类型用内存函数 |
五、常见误区避坑指南
- strlen 返回值是无符号数:避免直接用
strlen(a) - strlen(b)比较长度,需先转为 int 类型; - 字符串函数依赖
'\0':源字符串必须以'\0'结束,否则会越界; - memset 按字节设置:不要用它设置 int、float 等非字符类型的数组;
- strtok 修改原始字符串:需保留原字符串时,先拷贝到临时缓冲区再分割;
- 目标空间可修改:strcpy、strcat 等函数的目标空间不能是字符串常量(如
char *dest = "abc")。
更多推荐



所有评论(0)