【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数
前言
💓作者简介: 加油,旭杏,目前大二,正在学习C++,数据结构等👀
💓作者主页:加油,旭杏的主页👀⏩本文收录在:再识C进阶的专栏👀
🚚代码仓库:旭日东升 1👀
🌹欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖
学习目标:
在上一篇博客中,我们学习了字符串函数,字符串是由字符构成的,那么这篇博客将会为大家讲解字符分类函数,字符转换函数以及内存函数,那么字符就又有了一片新天地。这篇博客还是会很简单的,废话不多说,我们来开始写博客。
学习内容:
通过上面的学习目标,我们可以列出要学习的内容:
- 字符分类函数
- 字符转换函数
- 内存函数
一、字符分类函数
先来看一下全部字符分类函数的大纲,总共有12个,请看下面表格:
| 函数 | 如果他的参数符合下列条件就返回真 |
| 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 | 任何可打印的字符,包括圆形字符和空白字符 |
1.1 iscntrl字符函数
1.1.1 控制字符的概念(了解一下)
在小编刚听到这个函数时,我在纳闷控制字符是什么?控制字符的概念简单来讲,就是出现于特定的信息文本中,表示某一控制功能的字符。
精确来讲,就是在ASCII码中,第0~31号及第127号(共33个)是控制字符或通讯专用字符,如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)、BEL(振铃)等;通讯专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等。
1.1.2 iscntrl函数的作用

其功能就是检查字符c是否为控制字符,如果是,则返回真(非0的数,有可能是负数),如果不是,则返回假。
1.2 isspace字符函数

其功能是检查字符c是否为空白字符,空白字符的概念在上面表格已经写的很详细了,当然在图中也很清楚。
1.3 isdigit字符函数
这个函数还是用的比较多的,因为其功能是检查字符c是否为十进制数字,十进制数字想必大家都很清楚,所以这个函数还算能用的上(大家还是要重视一下)。

1.4 isxdigit字符函数
这个函数的范围和上面的isdight字符函数差不多,所以小编推断这个函数应该会用的很少,但还是要看一下,有个印象。这个函数的功能是检查字符c是否为十六进制数字,包括所有的十进制数字,小写字母 a~f,大写字母 A~F。

1.5 islower字符函数
这个函数就有点意思,功能是检查字符c是否为小写字母,在一些题目中可能会用到这个函数,这个函数还是要记住为好。

举个例子:
题目:请回答出你所你输入的字符串中小写字母的个数为多少?
代码:
#include <stdio.h> #include <ctype.h> int main() {int n = 0;scanf("%d", &n);char arr[20];for (int i = 0; i < n; i++){scanf("%c", &arr[i]);}int count = 0;for (int i = 0; i < n; i++){if (islower(arr[i])){count++;}}printf("%d\n", count);return 0; }
1.6 isupper字符函数
有了检查是否为小写字母的函数,那必然会有检查大写字母的字符函数,同样,我们在网站来看看这个函数吧!这个用法是和上面的字符函数的用法是基本一样的,这里就不在赘述。

1.7 isalpha字符函数
这个函数就是将 islower 字符函数和 isupper 字符函数结合起来,其功能是将检查是否为26个英文字母。个人感觉不是很好用,因为其的范围实在是太大了。

二、字符转换函数
字符转换函数一共有两个,一个是 tolower 字符函数,一个是 toupper 字符函数。这两个字符还是比较重要的,因为在题目的求解中会用到这两个字符函数。我们需要先来了解这两个字符函数的功能之后,我们再来用一个习题进行巩固练习。
2.1 tolower字符函数
2.1.1 函数功能
这个函数将判断所选的字符c是否为大写字母,如果是大写字母的话,将这个字符c转换为小写字母;如果不是大写字母,将不会转换这个字符c。大致工作原理就是利用 islower 字符函数进行判断,然后将这个字符函数进行处理即可。

2.1.2 函数例题
题目:
将一个字符串中的所有大写字母变成对应的小写字母,其它字母不变。例如:对字符串“ABC12! EF”执行函数后输出结果为“abc12! ef”。
代码:
这道题目的代码, 我们用两种方式进行解决,一种是运用库函数tolower,一种是不运用这个函数,我们来进行一些区别。
//如果使用库函数, 写的代码 void toUp(char* str) {int len = strlen(str);for (int i = 0; i < len; i++){if (isupper(*(str + i))){*(str + i) = tolower(*(str + i));}} }//如果不用库函数,代码会是什么样子的 void toUp(char* str) {int len = strlen(str);for (int i = 0; i < len; i++){if (str[i] >= 'a' && str[i] <= 'z'){str[i] = str[i] - 32;}} }
2.2 isupper字符函数
2.2.1 函数功能
这个函数将判断所选的字符c是否为小写字母,如果是小写字母的话,将这个字符c转换为大写字母;如果不是小写字母,将不会转换这个字符c。大致工作原理就是利用 isupper 字符函数进行判断,然后将这个字符函数进行处理即可。

2.2.2 函数例题
题目:
将一个字符串中的所有小写字母变成对应的大写字母,其它字母不变。例如:对字符串“abc12! ef”执行函数后输出结果为“ABC12! EF”。
代码:
这道题目的代码, 我们用两种方式进行解决,一种是运用库函数tolower,一种是不运用这个函数,我们来进行一些区别。
//如果使用库函数, 写的代码 void toUp(char* str) {int len = strlen(str);for (int i = 0; i < len; i++){if (islower(*(str + i))){*(str + i) = toupper(*(str + i));}} }//如果不用库函数,代码会是什么样子的 void toUp(char* str) {int len = strlen(str);for (int i = 0; i < len; i++){if (str[i] >= 'a' && str[i] <= 'z'){str[i] = str[i] - 32;}} }
2.3 最后进行总结一下
在这两个函数中,我们可以看见这两个函数的返回类型和形式参数基本是一样的,但是我们返回的是字符,而不是整形数字,为什么这两个函数的返回类型是 int 呢?

三、内存函数
内存函数就是内存相关的函数,这些函数有4个:memcpy,memmove,memset,memcmp。
如果我们将这种函数和上一篇字符串函数是有点相似的,但是我们已经有了字符串函数进行拷贝了,为什么还要用内存函数进行拷贝呢?大家要把视野放宽一下,在内存中不仅仅只有字符串,还有其他类型的数据需要拷贝!那么我们开始进行学习吧!
3.1 memcpy内存函数

3.1.1 函数功能
这个函数的功能是复制内存块,将从源头指向的位置开始往后的num个字节复制到目标指向的内存块中。乍一看,感觉和strcpy字符函数的功能有点像,但是他们两个还是有不同,请看下面的对比图:

3.1.2 函数使用
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() {int arr1[5];int arr2[] = { 0,1,2,3,4 };memcpy(arr1, arr2, 5 * sizeof(int));for (int i = 0; i < 5; i++){printf("%d ", arr1[i]);}return 0; }
3.1.3 模拟实现一下memcpy函数
void my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}
}
当看完模拟实现的过程后,我们可以看出在while循环中指针的变化可能不止一种写法,但是其他的写法会在不同的编译器中会出现漏洞。比如说下面的代码在c文件中可以编译过去,而在cpp文件中编译不过去。
void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;((char*)dest)++;((char*)src)++;}return dest;
}
3.1.4 有关这个函数的一些问题
在这个函数的开头,小编放了一张图片,在其上面我们有一些文字。小编再来解释一下什么意思?在前面我们学习了qsort函数,是不是与这个函数的思想有点相似呢?
- 为什么他的类型是 void* 呢?因为在C语言中,这个函数将会拷贝所有内存块中的数据,所以他的类型必须是void*,这样其就能返回任何类型的数据。
- 为什么 num 的单位是字节呢?因为数据类型中最小的单位是一个字节,如果我们一个字节一个字节的进行拷贝,我们就可以将所有类型的数据进行拷贝,这样的格局就大了。
3.2 memmove内存函数
在前面我们学习了memcpy函数,发现其可以将内存中的数据拷贝到另一个内存中,那么我们现在有一个问题就是:加入一个数组arr,其内容放有1,2,3,4,5,6,7,7,9,10。
如果我们想要将1,2,3,4,5向后移动2格,可不可以用我们自己定义的memcpy函数呢?答案是否定的。我们可以通过调试进行验证。(为什么不用库函数中的memcpy函数,先卖个关子,之后会说)

所以这就引出了这一部分我们要学习的函数——memmove函数,这个函数会将内存块中的数据进行移动,要与memcpy函数区分!接下来,我们来验证一下:

总结:
memcpy函数是用于两个不重叠的内存中,将一个内存中的数据拷贝到另一个内存当中;memmove函数是用于一个重叠的内存中,将这个内存中的一些数据移动位置。
3.2.1 memcpy函数居然也能完成memmove函数的功能?
为什么小编会这样说呢?因为在前言中,小编用的是自己模拟实现的memcpy函数,而用的不是库函数的memcpy函数。如果我们用的是memcpy函数呢?结果是可以实现memmove函数的功能。难道是我们写错了吗,不是,而是VS中的库函数的功能不叫强大(太卷了),现在我们来看一下memcpy函数实现功能:

3.2.2 函数功能

这个函数的功能是从source指针指向的位置开始,拷贝num个字节的内存块到destination中,其是能够对本身进行覆盖拷贝的函数,其又同时兼备了 memcpy函数可做的事。
3.2.3 模拟实现一下memmove内存函数
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src)void* ret = dest;if ((char*)dest < (char*)src){while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;
}
3.3 memset函数

memset函数是用来设置内存的,以字节为单位进行设置内存(更适合字符数组)。但要注意这个memset函数的使用场景,因为场景不同,这个memset函数所实现的功能是不同的。
第一个场景:
如果有一个数组arr,其内容是全为0,如果我们想让其的内容变为1,我们应该怎么办呢?我们如果使用memset函数,其结果又是什么呢?
为什么会是这个样子呢?因为memset函数是一个字节一个字节地进行设置,会将每一个字节的内容都设置为1,所以四个字节的数字的值不会是1,。
第二个场景:
如果我们想使数组的内容全初始化为0,我们可不可以使用memset函数呢?答案是可以的,因为即使每一个字节的内容都为0,那么四个字节的内容还是会等于0的。
3.4 memcmp内存函数

这个函数的功能是比较两个内存块对应字节内容的大小,不过,这个函数一个字节一个字节地比较,所以会有一些不同常理的事情发生:

学习产出:
- 字符分类函数
- 字符转换函数
- 内存函数
相关文章:
【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数
前言 💓作者简介: 加油,旭杏,目前大二,正在学习C,数据结构等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏…...
windows WSL配置cuda,pytorch和jupyter notebook
机器配置 GPU: NVIDIA Quadro K2000 与 NVIDIA 驱动程序捆绑的CUDA版本 但按照维基百科的描述,我的GPU对应的compute capability3.0,允许安装的CUDA最高只支持10.2,如下所示。 为什么本地会显示11.4呢?对此,GPT是这…...
回调地狱的产生=>Promise链式调用解决
常见的异步任务包括网络请求、文件读写、定时器等。当多个异步任务之间存在依赖关系,需要按照一定的顺序执行时,就容易出现回调地狱的情况。例如,当一个网络请求的结果返回后,需要根据返回的数据进行下一步的操作,这时…...
【设计模式】六、建造者模式
文章目录 需求介绍角色应用实例建造者模式在 JDK 的应用和源码分析java.lang.StringBuilder 中的建造者模式 建造者模式的注意事项和细节 需求 需要建房子:这一过程为打桩、砌墙、封顶房子有各种各样的,比如普通房,高楼,别墅&…...
SpringBoot 可以同时处理多少请求
一、前言 首先,在Spring Boot应用中,我们可以使用 Tomcat、Jetty、Undertow 等嵌入式 Web 服务器作为应用程序的运行容器。这些服务器都支持并发请求处理的能力。另外,Spring Boot 还提供了一些配置参数,可以对 Web 服务器进行调…...
嵌入式Linux应用开发-驱动大全-第一章同步与互斥②
嵌入式Linux应用开发-驱动大全-第一章同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1…...
EasyExcel的源码流程(导入Excel)
1. 入口 2. EasyExcel类继承了EasyExcelFactory类,EasyExcel自动拥有EasyExcelFactory父类的所有方法,如read(),readSheet(),write(),writerSheet()等等。 3. 进入.read()方法,需要传入三个参数(文件路径…...
基于 jasypt 实现spring boot 配置文件脱敏
前言 在项目构建过程中,保护敏感信息的安全性至关重要,为了提高系统的安全性能,我们采用了Jasypt来对配置文件中的敏感信息进行加密处理,以确保系统的机密信息不被轻易泄露。 步骤 添加Maven依赖 首先,我们需要添加…...
Python——ASCII编码与Unicode(UTF-8,UTF-16 和 UTF-32)编码
Python3 Python——ASCII编码与Unicode(UTF-8,UTF-16 和 UTF-32)编码 文章目录 Python3一、编码与编码格式二、ASCII编码与UTF-8编码(UTF-16 和 UTF-32编码)三、ASCII 字符串和 Unicode 字符串 最近看Python程序的文件…...
【多媒体技术与实践】音频信息获取和处理——编程题汇总
1:音频信息数据量计算 已知采样频率(单位KHz)、量化位数、声道数及持续时间(单位分钟),求未压缩时的数据量(单位MB). 例如: 输入: 22.05 16 2 3 ÿ…...
堆优化迪氏最短单源路径原理及C++实现
时间复杂度 O(ElogE),E是边数。适用与稀疏图。 使用前提 边的权为正。可以非连通,非连通的距离为-1。 原理 优选队列(小根堆)记录两个数据:当前点到源点距离,当前点。先处理距离小的点;如果…...
Leetcode202. 快乐数
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1࿰…...
【MySQL】MySql常见面试题总结
目录 一、什么是sql注入 二、sql语句的执行流程 三、内连接和外连接的区别 四、Union和Union All 有什么区别 五、MySql如何取差集 六、DELETE和TRUNCATE有什么区别 七、count(*)和count(1)的区别 八、MyISAM和InnoDB的区…...
【Java 进阶篇】JDBC PreparedStatement 详解
在Java中,与关系型数据库进行交互是非常常见的任务之一。JDBC(Java Database Connectivity)是Java平台的一个标准API,用于连接和操作各种关系型数据库。其中,PreparedStatement 是 JDBC 中一个重要的接口,用…...
嵌入式Linux应用开发-驱动大全-第一章同步与互斥①
嵌入式Linux应用开发-驱动大全-第一章同步与互斥① 第一章 同步与互斥①1.1 内联汇编1.1.1 C语言实现加法1.1.2 使用汇编函数实现加法1.1.3 内联汇编语法1.1.4 编写内联汇编实现加法1.1.5 earlyclobber的例子 1.2 同步与互斥的失败例子1.2.1 失败例子11.2.2 失败例子21.2.3 失败…...
【计算机网络】 基于UDP的简单通讯(客户端)
文章目录 客户端流程代码实现添加头文件以及库依赖加载库创建套接字发送接收数据关闭套接字、卸载库 测试 客户端 流程 客户端跟服务端差不多,也要先加载库,在加载库之后也要创建套接字,但是客户端一定是没有绑定ip地址的,之后是…...
【云备份项目】:环境搭建(g++、json库、bundle库、httplib库)
文章目录 1. g 升级到 7.3 版本2. 安装 jsoncpp 库3. 下载 bundle 数据压缩库4. 下载 httplib 库从 Win 传输文件到 Linux解压缩 1. g 升级到 7.3 版本 🔗链接跳转 2. 安装 jsoncpp 库 🔗链接跳转 3. 下载 bundle 数据压缩库 安装 git 工具 sudo yum…...
电脑右键新建记事本不见了--设置恢复篇(无需操作注册表)
电脑右键新建记事本不见了–设置恢复篇(无需修改注册表) 电脑不知怎么想右键新建记事本结果竟然不见了,搜寻网上的都是什么修改注册表,粘贴代码修复(感觉太复杂了),这里介绍通过设置内重新对记…...
JavaScript内置对象 - Array数组(四)- 序列生成器
序列生成器是生成一个指定起始值和结束值的序列,并且根据指定间隔长度,生成序列数组。 完成此功能需要使用到Array内置对象的from()对象,以及类数组相关知识,前面几篇有相关案例进行演示。 地址一:JavaScript内置对象…...
GD32F103x IIC通信
1. IIC通信 1.IIC的介绍 IIC总线有两条串行线,其一是时钟线SCK(同步),其二是数据线SDA。只有一条数据线属于半双工。应用中,单片机常常作为主机,外围器件可以挂载多个。(当然主机也可以有多个。…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...




