news 2026/4/15 8:50:08

C语言——字符与字符串处理函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言——字符与字符串处理函数

在C语言开发中,字符串与字符处理是基础且高频的需求。从字符分类、大小写转换,到字符串的拷贝、比较、分割,再到错误信息的定位与输出,<ctype.h>与<string.h>中的一系列标准库函数,构成了我们处理文本与调试问题的核心工具链。本文将带你快速掌握这些函数的用法、核心要点与实战场景,让你在开发中更高效地处理字符串与字符问题。


一、字符分类函数

这类函数用于判断字符的类型,需要包含头文件 <ctype.h>。

函数名如果他的参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符(空格、换页\f、换行\n、回车\r、制表符\t、垂直制表符\v)
isdigit十进制数字 0~9
isxdigit

十六进制数字(0~9、a~f、A~F)

islower小写字母 a~z
isupper大写字母 A~Z
isalpha字母 a~z 或 A~Z
isalnum字母或数字(a~z、A~Z、0~9)
ispunct标点符号(非数字/字母的可打印图形字符)
isgraph任何图形字符
isprint任何可打印字符(含图形字符和空白字符)

示例:判断小写字母并转换为大写

#include <stdio.h> #include <ctype.h> int main() { int i = 0; char str[] = "Test String.\n"; char c; while (str[i]) { c = str[i]; if (islower(c)) c -= 32; // 利用ASCII码差值转大写 putchar(c); i++; } return 0; }

二、字符转换函数

用于字母的大小写转换,需要包含头文件 <ctype.h>。

函数名功能
tolower将大写字母转为小写
toupper将小写字母转为大写

示例:用 toupper 实现小写转大写

#include <stdio.h> #include <ctype.h> int main() { int i = 0; char str[] = "Test String.\n"; char c; while (str[i]) { c = str[i]; if (islower(c)) c = toupper(c); putchar(c); i++; } return 0; }

三、strlen 函数

用于计算字符串长度(统计 \0 之前的字符个数),需要包含头文件 <string.h>。

函数原型

size_t strlen(const char *str);

核心要点

• 返回值类型是 size_t(无符号整数),比较时需注意避免负数错误。

• 字符串必须以 \0 结尾,否则结果未定义。

示例:strlen 的使用

#include <stdio.h> #include <string.h> int main() { const char* str = "abcdef"; printf("%zd\n", strlen(str)); // 输出:6 return 0; }

模拟实现

1. 计数器方式

int my_strlen(const char *str) { int count = 0; assert(str); while (*str) { count++; str++; } return count; }

2. 递归方式(无临时变量)

int my_strlen(const char *str) { assert(str); if (*str == '\0') return 0; else return 1 + my_strlen(str+1); }

3. 指针-指针方式

int my_strlen(char *s) { assert(str); char *p = s; while (*p != '\0') p++; return p - s; }

四、strcpy 函数

用于字符串拷贝(从源字符串拷贝到目标空间,包含 \0),需要包含头文件 <string.h>。

函数原型

char* strcpy(char *destination, const char *source);

核心要点

• 源字符串必须以 \0 结尾。

• 目标空间必须足够大且可修改。

示例:strcpy 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[10] = {0}; char arr2[] = "hello"; strcpy(arr1, arr2); printf("%s\n", arr1); // 输出:hello return 0; }

模拟实现

#include <stdio.h> #include <assert.h> char* my_strcpy(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while((*dest++ = *src++)) { ; } return ret; } int main() { char arr1[10] = {0}; char arr2[] = "hello"; my_strcpy(arr1, arr2); printf("%s\n", arr1); // 输出:hello return 0; }

五、strcat 函数

用于字符串追加(将源字符串追加到目标字符串末尾),需要包含头文件 <string.h>。

函数原型

char *strcat(char *destination, const char *source);

核心要点

• 源字符串必须以 \0 结尾。

• 目标字符串必须以 \0 结尾,且空间足够大。

示例:strcat 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[20] = "hello "; char arr2[] = "world"; strcat(arr1, arr2); printf("%s\n", arr1); // 输出:hello world return 0; }

模拟实现

#include <stdio.h> #include <assert.h> char* my_strcat(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while(*dest) { dest++; } while((*dest++ = *src++)) { ; } return ret; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; my_strcat(arr1, arr2); printf("%s\n", arr1); // 输出:hello world return 0; }

六、strcmp 函数

用于字符串比较(按 ASCII 码逐字符比较),需要包含头文件 <string.h>。

函数原型

int strcmp(const char *str1, const char *str2);

返回值规则

• > 0:str1 大于 str2

• = 0:str1 等于 str2

• < 0:str1 小于 str2

示例:strcmp 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[] = "abcdef"; char arr2[] = "abq"; int ret = strcmp(arr1, arr2); printf("%d\n", ret); // 输出:负数('c' < 'q') if(ret > 0) printf("arr1 > arr2\n"); else if(ret == 0) printf("arr1 == arr2\n"); else printf("arr1 < arr2\n"); return 0; }

模拟实现

int my_strcmp(const char *str1, const char *str2) { int ret = 0 ; assert(str1 != NULL); assert(str2 != NULL); while(*str1 == *str2) { if(*str1 == '\0') return 0; str1++; str2++; } return *str1-*str2; }

七、strncpy 函数

strcpy 的安全版本,可指定拷贝的最大字符数,需要包含头文件 <string.h>。

函数原型

char *strncpy(char *destination, const char *source, size_t num);

核心要点

• 最多拷贝 num 个字符,源字符串无需以 \0 结尾。

• 若源字符串长度不足 num,剩余位置用 \0 填充。

示例:strncpy 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[20] = {0}; char arr2[] = "abcdefghi"; char* str = strncpy(arr1, arr2, 5); printf("%s\n", arr1); // 输出:abcde printf("%s\n", str); // 输出:abcde return 0; }

八、strncat 函数

strcat 的安全版本,可指定追加的最大字符数,需要包含头文件 <string.h>。

函数原型

char *strncat(char *destination, const char *source, size_t num);

示例:strncat 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[20] = "hello "; char arr2[] = "world"; char* str = strncat(arr1, arr2, 5); printf("%s\n", arr1); // 输出:hello world printf("%s\n", str); // 输出:hello world return 0; }

九、strncmp 函数

strcmp 的安全版本,可指定比较的最大字符数,需要包含头文件 <string.h>。

函数原型

int strncmp(const char *str1, const char *str2, size_t num);

示例:strncmp 的使用

#include <stdio.h> #include <string.h> int main() { char arr1[] = "abcdef"; char arr2[] = "abcqw"; int ret1 = strncmp(arr1, arr2, 3); printf("%d\n", ret1); // 输出:0(前3个字符相等) int ret2 = strncmp(arr1, arr2, 4); printf("%d\n", ret2); // 输出:负数('d' < 'q') return 0; }

十、strstr 函数

用于在字符串中查找子字符串首次出现的位置,需要包含头文件 <string.h>。

函数原型

char *strstr(const char *str1, const char *str2);

返回值

• 找到子串:返回首次出现位置的指针

• 未找到:返回 NULL

示例:strstr 的使用

#include <stdio.h> #include <string.h> int main() { char str[] = "This is a simple string"; char *pch; pch = strstr (str,"simple"); if (pch != NULL) printf("%s\n", pch); // 输出:simple string else printf("查找的字符串不存在\n"); return 0; }

模拟实现(暴力匹配

char * strstr (const char * str1, const char * str2) { char *cp = (char *) str1; char *s1, *s2; if ( !*str2 ) return((char *)str1); while (*cp) { s1 = cp; s2 = (char *) str2; while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++; if (!*s2) return(cp); cp++; } return(NULL); }

十一、strtok 函数

用于分割字符串(根据分隔符拆分),需要包含头文件 <string.h>。

函数原型

char *strtok(char *str, const char *delim);

核心要点

• 首次调用:传入待分割字符串和分隔符。

• 后续调用:传入 NULL 和相同分隔符,继续分割。

• 会修改原字符串(将分隔符替换为 \0),建议先拷贝原串。

示例:strtok 的使用(分割IP地址)

#include <stdio.h> #include <string.h> int main() { char arr[] = "192.168.6.111"; const char* sep = "."; const char* str = NULL; char buf[30] = {0}; strcpy(buf, arr); for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep)) { printf("%s\n", str); } return 0; }

十二、strerror 与 perror 函数

用于获取和打印错误信息,需要包含头文件 <string.h> 和 <errno.h>。

1. strerror

char* strerror(int errnum);

头文件依赖

• <string.h>:提供 strerror 函数声明

• <errno.h>:提供全局错误码变量 errno 的定义

核心功能

1. 错误码转字符串
接收一个整数错误码 errnum,返回该错误码对应的人类可读的错误信息字符串首地址。

2. 仅处理标准库错误码
该函数只针对 C 标准库函数执行失败后设置的错误码进行转换。

3. 全局错误码 errno 的配合
C 程序启动时,全局变量 errno 初始化为 0(表示无错误)。当标准库函数调用出错时,系统会自动将对应的错误码存入 errno,再通过 strerror(errno) 即可获取错误描述。

参数与返回值

部分说明
参数 errnum传入的错误码,通常是全局变量 errno 的值
返回值指向错误信息字符串的首字符地址,该字符串由系统维护,无需手动释放

示例:strerror 的使用

#include <errno.h> // 包含系统错误码的宏定义(如EINVAL、ENOENT等) #include <string.h> // 包含strerror()函数的声明,用于错误码转字符串 #include <stdio.h> // 包含printf()函数的声明,用于控制台输出 int main() { // 循环遍历错误码0~10 for (int i = 0; i <= 10; i++) { // 打印:错误码 + 对应的错误描述 printf("%d: %s\n", i, strerror(i)); } return 0; }

关键函数说明

char *strerror(int errnum):

• 接收一个整数错误码作为参数,返回该错误码对应的人类可读的错误描述字符串。

• 错误码0通常表示无错误(Success),不同系统(Linux/Windows)对1~10的错误码定义略有差异。

Windows 11 + VS2022 环境运行结果

0: No error 1: Operation not permitted 2: No such file or directory 3: No such process 4: Interrupted function call 5: Input/output error 6: No such device or address 7: Arg list too long 8: Exec format error 9: Bad file descriptor 10: No child processes

常见应用场景

在文件操作、网络通信等场景中,结合 errno 和 strerror 可以快速定位问题:

#include <errno.h> #include <string.h> #include <stdio.h> int main() { // 尝试打开一个不存在的文件 FILE *fp = fopen("non_exist.txt", "r"); if (fp == NULL) { // 打印错误码和对应的错误信息 printf("文件打开失败,错误码:%d,原因:%s\n", errno, strerror(errno)); return -1; } fclose(fp); return 0; }

运行结果示例:

文件打开失败,错误码:2,原因:No such file or directory

核心逻辑

• 当 fopen 打开不存在的文件时,会将全局错误码变量 errno 设置为 2。

• strerror(errno) 会将错误码 2 转换为对应的错误描述字符串:No such file or directory。

• 该方式的优势是可以灵活控制错误信息的输出格式。

跨平台说明

• Linux 与 Windows 对部分错误码的定义不同,例如:

◦ 错误码 5 在 Linux 中是 Input/output error,在 Windows 中是 Access is denied

• 实际开发中,建议以当前运行环境的输出为准

2. perror

void perror(const char *str);

头文件依赖

• <stdio.h>:提供 perror 函数声明。

核心功能

• perror 会直接打印错误信息,无需额外调用 printf。

• 它会先打印参数 str 中的字符串,然后自动添加冒号和空格,最后输出 errno 对应的错误描述。

示例:perror 的使用

#include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE *pFile = NULL; pFile = fopen ("unexist.ent", "r"); if (pFile == NULL) { perror("错误信息是"); return 1; } return 0; }

运行输出:

错误信息是: No such file or directory

strerror 与 perror 对比

特性strerrorperror
返回值返回错误信息字符串的首地址无返回值,直接打印
输出方式需要配合 printf 等函数输出自动完成打印
灵活性高,可自定义输出格式低,输出格式固定
适用场景需要对错误信息进行二次处理时快速打印错误信息时

常见应用场景

场景1:文件操作错误排查

FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("文件打开失败"); return -1; }

输出:

文件打开失败: No such file or directory

场景2:自定义错误信息格式

FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { printf("[ERROR] 打开文件失败,原因:%s\n", strerror(errno)); return -1; }

输出:

[ERROR] 打开文件失败,原因:No such file or directory

C语言的字符串与字符处理函数,看似基础却贯穿了开发的各个场景。从字符的类型判断到字符串的复杂操作,再到错误信息的精准定位,这些工具函数正是C语言灵活性与高效性的体现。

熟练掌握它们不仅能让你写出更健壮的代码,更能在调试与问题定位时事半功倍。希望本文的梳理能成为你开发路上的实用手册,也期待你在实践中探索出更多巧妙的用法。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 19:36:50

translategemma-4b-it保姆级教学:Windows/macOS/Linux三平台统一部署路径

translategemma-4b-it保姆级教学&#xff1a;Windows/macOS/Linux三平台统一部署路径 1. 准备工作与环境搭建 在开始部署translategemma-4b-it之前&#xff0c;我们需要先准备好基础环境。这个轻量级翻译模型可以在Windows、macOS和Linux三大主流操作系统上运行&#xff0c;部…

作者头像 李华
网站建设 2026/4/14 23:38:02

新手必看!verl安装常见报错解决方案

新手必看&#xff01;verl安装常见报错解决方案 verl 是一个专为大语言模型后训练设计的强化学习框架&#xff0c;由字节跳动火山引擎团队开源&#xff0c;也是 HybridFlow 论文的工程落地实现。它不是视觉强化学习环境&#xff08;如 DeepMind Lab 或 CARLA&#xff09;&…

作者头像 李华
网站建设 2026/4/14 19:04:57

完整操作流程:从图片上传到魔法施放的全过程解析

完整操作流程&#xff1a;从图片上传到魔法施放的全过程解析 1. 认识AI魔法修图师 InstructPix2Pix是一款革命性的AI图像编辑工具&#xff0c;它彻底改变了传统修图的工作方式。与Photoshop等专业软件不同&#xff0c;这款工具不需要你掌握复杂的图层、蒙版或笔刷技巧&#x…

作者头像 李华
网站建设 2026/4/15 6:10:10

Qwen3-VL-8B电力巡检:变电站设备图→缺陷识别→检修工单自动生成

Qwen3-VL-8B电力巡检&#xff1a;变电站设备图→缺陷识别→检修工单自动生成 1. 项目概述 电力巡检是保障电网安全运行的重要环节&#xff0c;传统的人工巡检方式存在效率低、成本高、易漏检等问题。Qwen3-VL-8B AI系统通过计算机视觉和自然语言处理技术&#xff0c;实现了变…

作者头像 李华
网站建设 2026/4/4 10:02:50

Local AI MusicGen精彩案例:复古80年代合成器流行曲AI创作实录

Local AI MusicGen精彩案例&#xff1a;复古80年代合成器流行曲AI创作实录 1. 引言&#xff1a;你的私人AI作曲家 想象一下&#xff0c;你正在制作一个怀旧风格的短视频&#xff0c;需要一段充满80年代风情的背景音乐。传统方式可能需要花费数百元购买版权音乐&#xff0c;或…

作者头像 李华
网站建设 2026/4/12 11:56:38

Chandra OCR应用场景:电商产品说明书OCR→多语言Markdown生成

Chandra OCR应用场景&#xff1a;电商产品说明书OCR→多语言Markdown生成 1. 电商产品说明书的数字化痛点 在电商运营中&#xff0c;产品说明书是连接用户与产品的重要桥梁。然而&#xff0c;传统纸质或PDF格式的说明书存在诸多问题&#xff1a; 多语言障碍&#xff1a;跨境…

作者头像 李华