在编程的过程中,我们经常会遇到需要处理字符和字符串的情况,为了方便操作字符和字符串,C语言标准库中提供了一系列库函数,接下来我们就学习一下这些函数。


目录

1. 字符分类函数

2. 字母转换函数

3. strlen函数的使用和模拟实现

4. strcpy函数的使用和模拟实现

5. strcat函数的使用和模拟实现


1. 字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含一个头文件是<ctype.h>

一共有下面这些函数,当这些函数处理的字符满足条件时返回值就为真:

iscntrl:任何控制字符

isspace:空白字符:空格' ',换页符'\f',换行符'\n',回车'\r',制表符'\t'或者垂直制表符'\v'

isdigit:十进制字符'0'~'9'

isxdigit:十六进制字符:包括十进制所有字符,小写字母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:任何可打印字符,包括图形字符和空白字符

这些函数的使用方法非常相似,我们就只列举一个函数的使用方法:

int islower(int c);

通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。

例如:将字符串中的小写字母转换为大写字母

#include <ctype.h>
#include <stdio.h>
int main()
{int i = 0;char s[] = "Hello World";while(s[i]){if(islower(s[i]))s[i] -= 32;i++;}printf("%s\n",s);return 0;
}
HELLO WORLD

当返回值为非0值时,将字符的数值减去32,将小写字母转换为对应的大写字母,最后将修改后的字符串打印出来,查看结果是否符合预期。

2. 字母转换函数

C语言提供了2个字符转换函数:

int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写     
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

上面的代码中,我们是利用islower函数来判断字符是否为小写字母,若是,则让其减去32,实现小写字母转化为大写字母的效果。而现在,我们可以直接使用toupper函数将小写字母转化为大写字母,例如:

#include <ctype.h>
#include <stdio.h>
int main()
{int i = 0;char s[] = "Hello World";while(s[i]){if(islower(s[i]))s[i] = toupper(s[i]);i++;}printf("%s\n",s);return 0;
}

3. strlen函数的使用和模拟实现

strlen函数原型为:

 size_t strlen ( const char * str );

字符串以字符'\0'为结束标志,strlenm函数返回的值是字符串中字符'\0'前的字符个数(不包括'\0')

参数指向的字符串必须要以'\0'结束

注意函数的返回值类型为size_t,是无符号的

strlen的使用需要包含头文件<string.h>

#include <string.h>
#include <stdio.h>
int main()
{char s[] = "Hello World";printf("%d\n", strlen(s));return 0;
}
11

我们在前面指针的内容中就已经讲解过怎么模拟实现strlen函数,这里不再重复:

因为会使用到指针,这里加上assert,防止使用空指针

#include <assert.h>
size_t my_strlen(char* s)
{assert(s);size_t len = 0;while(*s++){len++;}return len;
}

这里再给处一种不创建临时变量的方法:

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

利用递归与指针的方式,在不创建临时变量的情况下,模拟实现strlen函数,不过这种方法的运行效率比较低,运行会上面的代码慢

4. strcpy函数的使用和模拟实现

strcpy函数的原型为:

char* strcpy(char * destination, const char * source );
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).

简单来说就是将一个字符串的内容复制到另一个字符串中,进行这个操作要满足这些条件:

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

会将源字符串中的'\0'拷贝到目标空间。

目标空间必须足够大,以确保能存放源字符串。

目标空间必须可修改。

了解这些后,我们可以尝试将一个字符串的内容复制到另一个字符串中:

#include <string.h>
#include <stdio.h>
int main()
{char s1[20] = "Hello World";char s2[] = "Good morning";printf("%s\n", strcpy(s1,s2));printf("%s\n",s1);return 0;
}
Good morning
Good morning

了解了使用方法后,我们现在来思考如何模拟实现strcpy函数:

由于C语言自带的strcpy函数无法检测目标字符串大小是否能够放下源字符串内容,我们在模拟实现时加上这一步判断。

首先,我们要让函数接收目标字符串dest和源字符串src的地址。

接着,我们要保证传递的两个字符串的地址是有效的,我们要使用assert函数;而且,也要保证字符串dest足够放下字符串src中的内容,那就需要比较两个字符串的大小。考虑到目标字符串中可能出现'\0'提前出现的情况,我们不能使用strlen来计算目标字符串的大小,因此,我们需要用sizeof来计算目标字符串大小;相对地,源字符串不需要考虑这个问题,但是字符'\0'也是需要占据空间地,因此在比较时需要让其+1。但是,由于字符数组dest地址在传递给函数时会转化为数组首元素的地址,在函数内部中使用时只能找到该元素而无法找到整个字符数组,因此在传递参数时我们还有额外传递参数size_dest,用于比较大小。

然后,我们就需要考虑如何将一个字符串的内容复制到另一个字符串中。

这里我们就要使用指针方法逐个访问字符串dest和src中的内容,并将src中的内容赋值给dest,直到访问到src中的'\0'。

最后,返回目标字符串的地址,但是现在有个问题,那就是指针dest指向的地址在我们复制操作结束后已经不是指向dest首字符的地址了。因此,我们需要在赋值前创建一个指针变量来存储该地址,用于最后返回。

分析完毕,代码形式如下:

char* my_cpy(char* dest,const char* src,size_t size_dest)
{assert(dest && src);if(size_dest < strlen(src) + 1){printf("目标字符串空间大小不足");return NULL;}char* origin_dest = dest;while((*dest++ = *src++));return origin_dest;
}

我们尝试使用一下函数my_cpy:

int main()
{char s1[20] = "Hello World";char s2[] = "Good morning";printf("%s\n", my_cpy(s1,s2, sizeof(s1)));printf("%s\n",s1);return 0;
}
Good morning
Good morning

我们可以发现,打印结果符合我们预期,代码成功模拟实现了strcpy函数的效果。

5. strcat函数的使用和模拟实现

函数strcat原型如下:

char *strcat(char *dest, const char *src);
Appends a copy of the source string to the destination string. 
The terminating null character in destination is overwritten by the first character of source, 
and a null-character is included at the 
end of the new string formed by the concatenation of both in destination

简单来说就是,将一个字符串的内容追加到另一个字符串的末尾,进行这个操作要满足这些条件:

源字符串必须以'\0'结束

目标字符串中也得有'\0',否则无法知道从哪里开始追加

目标空间必须有足够的大,能容纳下源字符串的内容。

目标空间必须可修改。

了解这些后,我们可以尝试使用一下strcat函数:

#include <string.h>
#include <stdio.h>
int main()
{char s1[20] = "Hello ";char s2[] = "World";printf("%s\n", strcat(s1,s2));printf("%s\n",s1);return 0;
}
Hello World
Hello World

我们可以看到,strcat函数成功将字符串s2的内容追加到了字符串s1末尾。

现在,我们来思考一下如何模拟实现strcat函数:

同样的,由于C语言自带的strcat函数无法检测目标字符串大小是否能够放下源字符串内容,我们在模拟实现时加上这一步判断。

首先,我们需要函数接收两个字符串dest和src的地址,以及字符串dest的大小size_dest。

接着,就是相同的操作,检验指针的有效性以及字符串dest的空间是否符合要求。若是条件都满足,创建一个指针变量来存储dest的地址。

然后,就是追加的操作,这一步和上面my_cpy的操作一样。只不过我们需要先找到dest中第一个'\0'的位置,然后再开始追加操作。

最后,返回dest的地址。

代码形式如下:

char* my_cat(char* dest,const char* src,size_t size_dest)
{assert(dest && src);size_t need = strlen(dest) + strlen(src) + 1;if(size_dest < need){printf("目标空间不足,实际需要空间为%zd\n",need);return NULL;}char* origin_dest = dest;while(*dest) dest++;while((*dest++ = *src++));return origin_dest;
}

我们尝试使用一下函数my_cat:

int main()
{char s1[20] = "Hello ";char s2[] = "World";printf("%s\n", my_cat(s1,s2, sizeof(s1)));printf("%s\n",s1);return 0;
}
Hello World
Hello World

我们可以发现,打印结果符合我们预期,代码成功模拟实现了strcat函数的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93733.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93733.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/93733.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法系列(大白话模式)小学生起点(一)

出身&#xff0c;并不重要 &#xff01;&#xff01;&#xff01;&#xff01;只要有恒心&#xff0c;有毅力&#xff0c;肯于付出与学习&#xff0c;皆会取得相应的成就&#xff01;天道酬勤&#xff0c;天行健&#xff0c;君子当自强不息&#xff01;道可道&#xff0c;非常道…

计算机视觉第一课opencv(二)保姆级教学

目录 简介 一、边界填充 1.函数说明 2.案例分析 二、图像运算 1.号运算 2.cv2.add()函数 3.图像加权运算 三、阈值处理 四、图像平滑处理 1.椒盐噪声 2.均值滤波&#xff08;Mean Filtering&#xff09; 3.方框滤波 4. 高斯滤波&#xff08;Gaussian Filtering&am…

DINOv3

一、摘要 https://arxiv.org/pdf/2508.10104 自监督学习有望消除对人工数据标注的需求&#xff0c;使模型能够轻松扩展到大规模数据集和更大规模的架构。由于不针对特定任务或领域进行定制&#xff0c;这种训练范式具有从各种来源学习视觉表示的潜力&#xff0c;能够使用单一…

​​pytest+yaml+allure接口自动化测试框架

高薪必备&#xff01;18K接口自动化测试框架落地全流程&#xff5c;零基础到实战通关前言# 自动化测试&#xff0c;是目前测试行业一项比较普遍的测试技术了&#xff0c;之前的以UI自动化测试为主&#xff0c;现在的以接口自动化测试为主&#xff0c;无论技术更迭&#xff0c;…

LeetCode每日一题,2025-8-20

统计全为1的正方形子矩阵 这题是正方形&#xff0c;比较简单 暴力就是二维前缀和。 或者用dp&#xff0c;dp[i][j]表示以i&#xff0c;j为右下角的最大正方形的边长&#xff0c;它由(i-1,j),(i,j-1),(i-1,j-1)三者共同决定&#xff0c;通过找规律可知&#xff0c;由三个的最小值…

在Excel启动时直接打开多个Excel文件

如果我们这段时间每天都要打开几个相同的Excel文件开展工作&#xff0c;可以把这几个文件放到一个文件夹&#xff08;如果原来就在不同的文件夹&#xff0c;就把快捷方式放到同一个文件夹&#xff09;&#xff0c;然后在Excel选项中设置启动时打开这个文件夹中的文件即可。注&a…

对象存储 COS 端到端质量系列 —— 终端网络诊断工具

背景 在COS终端SDK的众多功能中&#xff0c;文件上传功能的使用颇为频繁。鉴于此&#xff0c;提升文件上传的成功率便显得至关重要。众多导致上传失败的因素里&#xff0c;由网络问题引发的故障无疑是其中影响上传成功率的关键因素之一&#xff0c;同时也是最难以把控的要素。…

Flask高效数据库操作指南

Flask-SQLAlchemy 数据库操作关于Flask数据库Flask中没有指定使用的数据库&#xff0c;可以自由选择不管你是使用关系型数据库&#xff0c;还是非关系型数据库都可以&#xff0c;不像django提供了orm 数据库抽象层&#xff0c;可以直接采用对象的方式操作数据库。但是为了开发效…

Camera相机人脸识别系列专题分析之十九:MTK ISP6S平台FDNode原生代码

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、问题背景 二、MTK ISP6S平台FDNodeImp.cpp 2.1:原生代码

S32K3 的图形化配置和EB配置mcal差异

32K3系列的图形化配置工具&#xff08;如S32 Design Studio, S32DS&#xff09;与EB配置工具&#xff08;基于EB tresos Studio&#xff09;在配置MCAL&#xff08;Microcontroller Abstraction Layer&#xff09;时存在关键差异&#xff0c;主要体现在工具环境、配置流程、代码…

Meta 再次重组人工智能部门

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

在nodejs中 有哪些是 “假值“和怎么写 “双重否定”

1.在 Node.js&#xff08;以及 JavaScript&#xff09;中&#xff0c;以下值在布尔上下文&#xff08;例如 if 语句、while 循环条件等&#xff09;中被视为 “假值”&#xff1a;false&#xff1a;布尔类型的 false 值&#xff0c;这是最直接的假值。if (false) {console.log(…

车载软件架构 --- 赢得汽车软件开发竞赛

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

机器学习总复习

这段时间学习了 KNN&#xff0c;线性回归&#xff0c;逻辑回归&#xff0c;贝叶斯&#xff0c;聚类&#xff08;K-means,DBSCAN&#xff09;&#xff0c;决策树&#xff0c;集成学习&#xff08;随机森林&#xff0c;XGboost&#xff09;&#xff0c;SVM支持向量机&#xff0c;…

深入解析EventPoller:Disruptor的轮询式事件处理机制

EventPoller 是什么&#xff1f;EventPoller 是 Disruptor 框架中一种 基于轮询&#xff08;poll-based&#xff09; 的事件消费机制。它与我们更常见的 BatchEventProcessor&#xff08;基于独立的消费者线程&#xff09;形成了对比。核心区别在于&#xff1a;BatchEventProce…

K8S-Secret资源对象

目录 一、Secret概述 二、Secret 类型 kubectl 创建类型 三、Secret 使用 Opaque 类型 Secret 的使用 创建 yaml 一、Secret概述 k8s secrets用于存储和管理一些敏感数据&#xff0c;比如密码&#xff0c;token&#xff0c;密钥等敏感信息。它把 Pod 想要访问的加密数据…

lua入门以及在Redis中的应用

1.基本语法1.1变量lua的变量有&#xff1a;无效值nil&#xff0c;布尔值boolean&#xff0c;数字number、字符串string、函数function、自定义类型userdata、线程thread、表table&#xff08;key-value结构&#xff09;1.2循环数值循环for i起始值, 结束值 ,间隔值 do---option…

淘宝电商大数据采集【采集内容||采集方法|工具||合规性||应用】

淘宝电商大数据采集是指通过技术手段、工具或平台&#xff0c;系统性收集淘宝&#xff08;及旗下天猫等&#xff09;生态内的各类数据&#xff0c;用于分析市场趋势、用户行为、商品表现、竞品动态等&#xff0c;为电商运营、决策提供数据支持。以下从采集内容、工具方法、合规…

ROS2核心模块

1.创建工作空间先创建工作空间ws01_plumbing&#xff0c;终端下进入工作空间的src目录&#xff0c;执行如下命令&#xff1a;ros2 pkg create --build-type ament_cmake base_interfaces_demo2.话题通信话题通信是ROS中使用频率最高的一种通信模式&#xff0c;话题通信是基于发…

Mac 上安装并使用 frpc(FRP 内网穿透客户端)指南

一、先装好 Homebrew&#xff08;macOS 的包管理器&#xff09;打开终端&#xff08;Terminal&#xff09;&#xff0c;先装命令行开发工具 xcode-select --install弹窗点“安装”&#xff0c;等待 3~5 分钟。一键安装 Homebrew /bin/bash -c "$(curl -fsSL https://raw.g…