【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数

前言

💓作者简介: 加油,旭杏,目前大二,正在学习C++数据结构等👀
💓作者主页:加油,旭杏的主页👀

⏩本文收录在:再识C进阶的专栏👀

🚚代码仓库:旭日东升 1👀

🌹欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖

学习目标:

       在上一篇博客中,我们学习了字符串函数,字符串是由字符构成的,那么这篇博客将会为大家讲解字符分类函数字符转换函数以及内存函数,那么字符就又有了一片新天地。这篇博客还是会很简单的,废话不多说,我们来开始写博客。


学习内容:

通过上面的学习目标,我们可以列出要学习的内容:

  1. 字符分类函数
  2. 字符转换函数
  3. 内存函数 

一、字符分类函数

先来看一下全部字符分类函数的大纲,总共有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个:memcpymemmovememsetmemcmp

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

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内存函数

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


学习产出:

  1. 字符分类函数
  2. 字符转换函数
  3. 内存函数 

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

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

相关文章

全网最全面最精华的设计模式讲解,从程序员转变为工程师的第一步

前言 现代社会&#xff0c;技术日新月异&#xff0c;要想跟上技术的更新就必须不断学习&#xff0c;而学习技术最有效方式就是阅读优秀的源码&#xff0c;而优秀的源码都不是简单的逻辑堆积&#xff0c;而是有很灵活的设计模式应用其中&#xff0c;如果我们不懂设计模式&#…

单例模式:饿汉式

单例模式全局仅一个实例&#xff0c;用于获取公共的内容 头文件mglobalinfomgr.h class MGlobalInfoMgr {MGlobalInfoMgr();~MGlobalInfoMgr(); public:static MGlobalInfoMgr* GetInstance(); private:static MGlobalInfoMgr* _instance; }; 源文件mglobalinfomgr.cpp MGl…

idea2023根据表自动生成+springboot跑起来

idea安装插件 idea中显示数据库连接 就可以看到如下界面 选中你想生成的表&#xff0c;右键如下操作 如上就有了所有需要的后端代码 生成后&#xff0c;要查看一下mapper.xml中的文件是否 正确&#xff0c;若有误请先去修改&#xff0c;例如我的版本下生成了xml文件中缺乏…

基于SpringBoot的银行账目账户管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

51单片机用IIc控制OLED显示数组内容

为了能够看到51单片机接收到的串口数据&#xff0c;我选择了用oled显示收到的数据&#xff0c;特此花重金买了一块oled屏128X64的屏幕大概10来块钱吧&#xff01;首先要达成的小目标就是能够显示数组的内容&#xff0c;建立一个字符数组&#xff0c;用来接收串口收到的数据&…

基于SpringBoot的古典舞在线交流平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 系统主界面 用户注册界面 论坛交流界面 课程详情界面 购物车界面 我的订单界面 管理员登录界面 会员用户管理界面 服饰管理界面 课程管理界面 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着互联网技术…

Python函数:chr()和ord()

两个函数是基于Unicode编码表进行进行字符与字码之间的转换。 chr()函数是通过字码转换成字符: 如图,坐标(1,4e10)丑 使用chr需要线将坐标相加得到&#xff1a;4e11 chr默认传入10进制的字码. 如图是各进制的字码。 也可以传入其他进制&#xff0c;不过需要在前面传入的参数最前…

Docker学习_镜像和容器篇

简介 Docker是一种容器化的技术&#xff0c;可以实现在一台宿主机电脑上运行多个不同的容器&#xff0c;每个容器之间都相互独立&#xff0c;具有完整的一套文件&#xff0c;网络和端口。 可以将其理解为一种虚拟机技术&#xff0c;只不过和VMware等虚拟化技术不同&#xff0…

LM小型可编程控制器软件(基于CoDeSys)笔记三十一:保持变量和非保持变量

所谓变量&#xff0c;就是用字母、数字和下划线组成的一个标识符。 按照数据类型的不同&#xff0c;变量可以分为标准类型和用户自定义类型。其中标准类型包括布尔型 &#xff08; BOOL &#xff09;、整型&#xff08; INT &#xff09;、实型&#xff08; REAL &#xff09…

18.备忘录模式(Memento)

意图&#xff1a;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff0c;这样就可以在以后将该对象恢复到原先保存的状态。 上下文&#xff1a;某些对象的状态在转换过程中&#xff0c;可能由于某种需要&#xff0c;要求…

ChunJun: 自定义插件

序言 Chunjun的版本兼容可能会有问题,在我们了解了自定义插件后,在修改源码以应对不同的场景就会得心应手了,针对Chunjun1.12.Release版本说明cuiyaonan2000163.com 自定义插件整体流程 从数据流的角度来看ChunJun&#xff0c;可以理解为不同数据源的数据流通过对应的ChunJu…

搭建自己的搜索引擎之三

一、前言 接上一篇 搭建自己的搜索引擎之二&#xff0c;本篇主要讲一下我们如何操作ElasticSearch&#xff0c;就是最简单的增删改查命令怎么写。 二、几个概念 搭建自己的搜索引擎之一 这篇文章我们对比搜索引擎在做海量数据实时查询优于关系型数据库的一些原因&#xff0c…

java 根据身份证号码判断性别

在Java中&#xff0c;您可以根据身份证号码的规则来判断性别。中国的身份证号码通常采用的是以下规则&#xff1a; 第17位数字代表性别&#xff0c;奇数表示男性&#xff0c;偶数表示女性。 通常&#xff0c;男性的出生日期的第15、16位数字是01&#xff0c;女性是02。 请注意&…

银行卡号识别

# 导入工具包 from imutils import contours import numpy as np import argparse import cv2 import myutils# 设置参数 # ap = argparse.ArgumentParser() # ap.add_argument("-i", "--image", required=True, # help="path to input image")…

【深度学习】实验18 自然语言处理

文章目录 自然语言处理分词技术1. 正向最大匹配算法2. HanLP常用方法3. Jieba常用方法 构建词向量1. 基于sklearn构建One-hot词向量2. 基于gensim构建word2vec词向量 附&#xff1a;系列文章 自然语言处理 自然语言处理(Natural Language Processing, NLP)是一种计算机科学和人…

常见的密码学算法都有哪些?

密码学算法是用于保护信息安全的数学方法和技术。它们可以分为多个类别&#xff0c;包括对称加密、非对称加密、哈希函数和数字签名等。以下是一些常见的密码学算法&#xff1a; 1、对称加密算法&#xff1a; AES&#xff08;高级加密标准&#xff09;&#xff1a;一种广泛使…

项目实战第四十六讲:财务经营看板

项目实战第四十六讲:财务经营看板 本文是项目实战第四十六讲,财务经营看板。财务模块划分为两类:① 财务工具(执行和业务财务闭环)② 财务报表,本期需求为新增财务看板,共增加4个看板 文章目录 项目实战第四十六讲:财务经营看板1、需求背景2、流程图3、技术方案4、相关…

DevExpress WinForms图表组件 - 直观的数据信息呈现方式!(二)

在上文中&#xff08;点击这里回顾>>&#xff09;&#xff0c;我们为大家介绍了DevExpress WinForms图表控件的互动图表、图标设计器及可定制功能等&#xff0c;本文将继续介绍DevExpress WinForms图表控件的数据分析、大数据功能等&#xff0c;欢迎持续关注我们哦~ Dev…

【Ubuntu18.04】Autoware.ai安装

Autoware.ai安装 引言1 ROS安装2 Ubuntu18.04安装Qt5.14.23 安装GCC、G4 Autoware.ai-1.14.0安装与编译4.1 源码的编译4.1.1 python2.7环境4.1,2 针对Ubuntu 18.04 / Melodic的依赖包安装4.1.3 先安装一些缺的ros依赖4.1.4 安装eigen3.3.74.1.5 安装opencv 3.4.164.1.6 编译4.1…

vim 工具的使用

注&#xff1a;以下操作都在普通模式下进行 光标的移动操作 gg 定位到代码的第一行 shiftg 定位到代码的最后一行 nshiftg 定位到第n行 shift6: 特定一行的开始 shift4 特定一行的结尾 上下左右的移动光标 h: 向左移动光标 j: 向下移动光标 k: 向上移动光标 l: 向右移动光标 …