当前位置: 首页 > news >正文

C语言:字符函数和字符串函数—及模拟实现

目录

1. 字符分类函数

2. 字符转换函数

3. 字符串相关函数

3.1 strlen

3.2 strcpy 和 strncpy

3.2.1 strcpy

3.2.2 strncpy

3.3 strcat 和 strncat

3.3.1 strcat

3.3.2 strncat

3.4 strcmp 和 strncmp

3.4.1 strcmp

3.4.2 strncmp

3.5 strstr

3.6 strtok

3.7 strerror


1. 字符分类函数

顾名思义,字符分类函数就是用于分类各种类型的字符,以便于后续操作。以下是一些常见的字符分类函数:

  1. iscntrl(控制字符)
  2. isspace(空白字符,如:空格 ' ' ,换行 '\n',制表符 '\t',换页 '\f',回车 '\r',垂直制表符 '\v')
  3. isdigit(十进制数)
  4. isxdigit(十六进制数)
  5. isalpha(大、小写字母)
  6. islower(小写字母)
  7. isupper(大写字母)
  8. isalnum(字母或数字)
  9. ispunct(标点符号,任何不属于字母或数字的图形字符)
  10. isgraph(任何图形字符)
  11. isprint(任何可打印字符,包括图形字符和空白字符)

2. 字符转换函数

在C语言中,除了将小写字母的ASCII码值减去32得到对应大写字母的ASCII码值,我们还可以用以下两个函数实现大小写转换:

int tolower(int a); //大写转小写 int toupper(int b); //小写转大写

需要注意的是,函数的返回值为对应字母的ASCII码值。

3. 字符串相关函数

3.1 strlen

使用前须添加头文件<string.h>

size_t strlen (const char * str);
  1. 用法:统计字符串中 '\0' 之前的字符个数。
  2. 参数:str为需要统计长度的字符串指针。
  3. 返回值:返回str指向的字符串长度,为无符号整数(size_t)。

注意事项:

  1. 字符串必须有结束标志 '\0' 。
  2. strlen统计的是 '\0' 之前的字符个数,包括任何有效字符(如空格),不包括'\0' 。
  3. 返回值size_t类型是无符号的。

使用示例:

#include<stdio.h> #include<string.h> int main() { char arr[20] = {"hello world"}; int sz = strlen(arr); printf("%d", sz); return 0; }

* 模拟实现strlen:

  • 方法一:指针位移
int my_strlen(const char * str) { assert(str); int cnt = 0; while(*str) { cnt++; str++; } return cnt; }
  • 方法二:递归

int my_strlen(const char * str) { assert(str); if(*str == '\0') return 0; else { return 1 + my_strlen(str + 1); //可以写前置++str,但不可用后置str++ } }

3.2 strcpy 和 strncpy

3.2.1 strcpy

使用前须添加头文件<string.h>

char * strcpy (char * destination, const char * source);
  1. 用法:可以对指定的字符串进行拷贝存放。
  2. 参数:destination为存放目标处的指针,source为拷贝源头的指针。
  3. 返回值:拷贝完成时返回目标空间的起始地址。

注意事项:

  1. 拷贝源头的字符串必须以 '\0' 作为结束标志。
  2. 拷贝源头字符串的 '\0' 也会一并拷贝。
  3. 目标空间必须足够大,可被修改。

使用示例:

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

* 模拟实现strcpy:

char * my_strcpy(char * dst, const char * src) { assert(dst); assert(src); char * dst2 = dst; while(*src != '\0') { *dst = *src; dst++; src++; } //记得在dst末尾补充src所指向的'\0' *dst = *src; return dst2; }

3.2.2 strncpy

使用前须添加头文件<string.h>

char * strncpy(char * destination, const char * source, size_t num);
  1. 用法:可以对指定长度的字符串进行拷贝存放。
  2. 参数:在strcpy的基础上增加了需要拷贝的字节数num。

其余部分与strcpy的用法大致相同,这里不作过多赘述。

与strcpy相比,strncpy指定了拷贝的长度,使得即使拷贝源头没有 '\0' 也可以正常使用,更加安全。

使用示例:

#include<stdio.h> #include<string.h> int main() { char arr1[15] = {"hello worldxx"}; char arr2[20] = {0}; strncpy(arr2, arr1, 11); printf("%s", arr2); return 0; }

3.3 strcat 和 strncat

3.3.1 strcat

使用前须添加头文件<string.h>

char * strcat (char * destination, const char * source);
  1. 用法:将源字符串追加到指定的字符串后。
  2. 参数:destination为追加目标处的指针,source为源头数据的指针。
  3. 返回值:追加完成时返回目标空间的起始地址。

注意事项:

  1. 源字符串必须以 '\0' 结尾,否则会有越界风险。
  2. 目标空间必须也有 '\0' ,否则无法确定追加起点;追加时,源字符串的第一个元素会覆盖追加起点的 '\0' 。
  3. 目标空间必须足够大,可被修改。

使用示例:

#include<stdio.h> #include<string.h> int main() { char arr1[15] = {"hello world"}; char arr2[30] = {"haha "}; strcat(arr2, arr1); printf("%s", arr2); return 0; }

3.3.2 strncat

使用前须添加头文件<string.h>

char * strncat (char * destination, const char * cource, size_t num);
  1. 用法:可以对指定长度的字符串进行追加。
  2. 参数:在strcpy的基础上增加了需要追加的字符数num。
  3. 返回值:追加完成时返回目标空间的起始地址。

注意事项:

  1. 追加结束会自动添加 '\0' ,即使未主动追加 '\0' 。
  2. 如果num超出了源字符串长度则会忽略掉。

使用示例:

#include<stdio.h> #include<string.h> int main() { char arr1[15] = {"hello world"}; char arr2[30] = {"haha "}; strncat(arr2, arr1, 5); printf("%s", arr2); return 0; }

3.4 strcmp 和 strncmp

3.4.1 strcmp

使用前须添加头文件<string.h>

int strcmp (const char * str1, const char * str2);
  1. 用法:比较两个字符串,从两个字符串的第一个字符开始比较,如果两个字符的ASCII码值相等,就比较下一个字符,直至遇到不相等的字符或者字符串结束。

  2. 参数:str1,str2为两个字符串对应的指针。

  3. 返回值:若str1大于str2,返回大于0的整数;若str1等于str2,返回0;若str1小于str2,返回小于0的整数。

使用示例:

#include<stdio.h> #include<string.h> int main() { char str1[15] = {"hello C"}; char str2[15] = {"hello world"}; int ret = strcmp(str1, str2); printf("%d", ret); //由于C的ASCII码值小于w,所以打印结果为负整数 return 0; }

3.4.2 strncmp

使用前须添加头文件<string.h>

int strncmp (char * str1, char * str2, size_t num);
  1. 用法:比较两个字符串中指定长度的大小。
  2. 参数:在strcmp的基础上增加了num,是比较的字符数。
  3. 返回值:与strcmp的规则相同。

与strcmp相比,strncmp指定了比较的长度,更加灵活、安全。

使用示例:

#include<stdio.h> #include<string.h> int main() { char str1[15] = {"hello C"}; char str2[15] = {"hello world"}; int ret = strncmp(str1, str2, 5); printf("%d", ret); //由于两个字符串的前5个字符相同,故返回0 return 0; }

3.5 strstr

使用前须添加头文件<string.h>

char * strstr (const char * str1, const char * str2);
  1. 用法:在一个字符串中查找子字符串。
  2. 参数:str1为被查找的字符串指针,str2为需要查找的子字符串指针。
  3. 返回值:若查找成功,则返回第一次出现位置的指针,否则返回NULL。

若要以%s输出返回值的指针,则将会打印 '\0' 之前的所有字符。

使用示例:

#include<stdio.h> #include<string.h> int main() { char str2[15] = {"hello"}; char str1[15] = {"hello world"}; char * ret = strstr(str1, str2); if(ret != NULL) { printf("%s\n", ret); } else { printf("您所查找的字符串不存在。\n"); } //输出结果为hello world return 0; }

3.6 strtok

使用前须添加头文件<string.h>

char * strtok (char * str, const char * delim);
  1. 用法:根据指定的分割字符delim,将str分割成一个个子字符串,并且原字符串中的分割符会用 '\0' 代替。
  2. 参数:str为需要分割的字符串,delim为指定的分割字符(可连续传入多个字符)。
  3. 返回值:成功时返回当前子字符串的指针,否则返回NULL。
  4. 使用步骤:首次调用需要传入待分割字符和分隔符,后续调用传入NULL和分隔符,当返回NULL时分割完成。

注意事项:

  1. 调用过程中会修改原字符串,可通过拷贝原字符串避免。
  2. 对于连续的分隔符,strtok会一并跳过。
  3. 不可传入空指针作为字符串。

使用示例:

#include<stdio.h> #include<string.h> int main() { char arr[] = "hello@.#world@@ni hao C yu.yan."; const char * str = NULL; //置空避免野指针 char cpy[30] = {0}; strcpy(cpy, arr); //将str中的字符串拷贝到cpy中,方便后续对cpy进行切割 const char * sep = "@#. "; //确定切割字符 for(str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep)) { printf("%s\n",str); } return 0; }

值得一提的是,如果子字符串较多,上述for循环的使用方式可以大大减少代码量:

  • 初始化部分对arr进行首次传参;
  • 判断条件部分设置为当str为NULL的时候停止循环;
  • 增量部分将arr的部分用NULL取代,保证了后续调用时传参的准确性。

3.7 strerror

使用前须添加头文件<string.h>

char * strerror (int errnum);
  1. 用法:当库函数调用发生错误时,可以查看错误信息。
  2. 参数:errnum表示错误信息对应的整数,一般使用C语言程序中自带的全局变量errno。
  3. 返回值:错误信息字符串中首字符的地址。

注意事项:

  1. 关于errno:调用时须添加头文件<errno.h>,初始值为0,程序运行过程中若出错,则会更新为错误码。一般有以下几种错误码和对应的错误信息:
  • 0:No error
  • 1:Operation not permitted
  • 2:No such file on dictionary
  • 3:No such process
  • 4:Interrupted function call
  • 5:Input/output error
  • 6:No such divice or address
  • 7:Arg list too long
  • 8:Exec format error
  • 9:Bad file descriptor
  • 10:No child processes

2. strerror仅支持在标准库中的函数出错后进行错误码转换。

3. 更加便捷的方式:perror函数。可以省去引用errno和strerror,直接输出对应的错误信息。返回值为参数部分的字符串,一个冒号加一个空格,错误信息。

使用示例:

#include<stdio.h> #include<string.h> #include<errno.h> int main() { FILE * pfile = NULL; pfile = fopen("unexist.ent","r") //以只读模式打开文件unexist.ent if(pfile == NULL) { printf("错误信息是:%s\n", strerror(errno)); //或者替换为: //perror("错误信息是"); return 1; } return 0; }
http://www.jsqmd.com/news/496809/

相关文章:

  • 广柔扁平电缆在机器人AI技术创新应用中的前景探索 - 资讯焦点
  • PyQt:从图像文件或字节流生成QImage的速度测试
  • JMeter实战2--阶梯线程组及计算逻辑
  • 链接脚本优化(lsl或ld),Map文件解析,内存分析软件MapSee免费下载
  • ROS2的核心概念A-节点
  • Windows如何阻止应用程序联网
  • 灵芝孢子粉哪个牌子好?从破壁率、成分、口碑分析.
  • 计算机毕业设计源码:Python基于大数据的租房价格分析平台 Django框架 Requests爬虫 可视化 房子 房源 大数据 大模型(建议收藏)✅
  • VMware安装教程带资料完整版
  • 【愚公系列】《剪映+DeepSeek+即梦:短视频制作》009-剪辑:把碎片素材串联成片(画面调整)
  • 2026年地方招投标新规密集出台:火眼审阅标书查重,精准响应政策要求的合规利器 - 资讯焦点
  • 红外热像仪优质厂家推荐:工业巡检机器人、手持红外热像仪、热成像相机、热成像红外夜视仪、电力巡视、管道巡检机器人选择指南 - 优质品牌商家
  • NMN哪个产品最好?2026选哪个NMN牌子性价最高?高活NMN推荐理由:转化NAD+吸收率高 - 资讯焦点
  • vue基于springboot高校教材管理网站_47nia
  • 2026云南钢材一站式供应权威之选:五大综合服务商全链赋能,省心之选 - 深度智识库
  • 2026UHPC构件板厂家推荐:UHPC外墙挂板/UHPC装饰板/UHPC挂板定制/UHPC挂板厂家精选 - 品牌推荐官
  • 2026不锈钢方型水箱专业品牌推荐指南 - 优质品牌商家
  • Windows上使用scp安装OpenSSH服务端 客户端
  • 二分查找(在排序数组查找元素)(2)
  • mysql事务以及MVCC相关原理
  • ubuntu工具之可视化录制的bag数据——PlotJuggler(ROS1版本下载安装)
  • 2026 年国内优质靠谱化工原料直销厂家实力盘点 - 深度智识库
  • 告别熬夜苦写论文:8款AI工具10分钟出万字,降重改稿全搞定 - 麟书学长
  • 代码随想录算法训练营day15| 110.平衡二叉树 (优先掌握递归)、 257. 二叉树的所有路径 (优先掌握递归)、 404.左叶子之和 (优先掌握递归)、 222.完全二叉树的节点个数(优先掌握
  • 第4章,[标签 Win32] :加入滚动条的 SysMets
  • 2026年玻璃钢盐酸储罐厂家推荐:玻璃钢酸碱储罐/卧式玻璃钢储罐/FRP/PP储罐/现场缠绕玻璃钢储罐/大型玻璃钢储罐专业供应商精选 - 品牌推荐官
  • 2026年合肥寻猫服务费用构成与价值解析 - 2026年企业推荐榜
  • 一篇关于mysql迁移达梦后相关sql的优化记录
  • [工具] 影子去除工具,可以批量去除影子,自动裁切透明,自动更新偏移坐标
  • Vue2框架基础配置逻辑和表单双向绑定