【C语言】字符分类函数、字符转换函数、内存函数
前言
之前我们用两篇文章介绍了strlen、strcpy、stract、strcmp、strncpy、strncat、strncmp、strstr、strtok、streeror这些函数
第一篇文章strlen、strcpy、stract
第二篇文章strcmp、strncpy、strncat、strncmp
第三篇文章strstr、strtok、streeror
今天我们就来学习字符分类函数、字符转换函数、内存访问函数
话不多说,我们直接开始
字符分类函数
这些函数需要包含头文件<ctype.h>
例子(islower)
用islower函数作为例子
当字符是小写字母时,返回一个非零的整数,
当不是小写字母时,返回0
int main()
{char ch = 'w';int ret = islower(ch);printf("%d\n", ret);return 0;
}
字符转换函数
int tolower(int a)
int toupper(int b)
一般使用
转换单个字符
int main()
{char ch = 'W';char ret = tolower(ch);printf("%c\n", ret);return 0;
}
转换字符串
int main()
{char arr[] = "HELLO WORLD";int i = 0;while (arr[i]){if (isupper(arr[i])){arr[i] = tolower(arr[i]);}i++;}printf("%s\n", arr);return 0;
}
内存访问函数
我们接下来会学习:memcmp、memmove、memcmp、memset函数
引入
小明提出疑问:
我们之前已经学习了那么多的字符串函数:strlen、strcpy、stract、strcmp、strncpy、strncat、strncmp…为什么还要学习内存函数呢
那是因为,上面的那些函数,操作对象都是字符串,也大多需要用到’\0’
而当我们要对整型数组或者结构体的数组,这时我们在用之前的那些函数就做不到了
下面看一段代码,它能达到我们预想的结果吗
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[5] = { 0 };strcpy(arr1, arr2);return 0;
}
程序警告:
“函数”: 从“int [5]”到“char *”的类型不兼容
“函数”: 从“int [5]”到“const char *”的类型不兼容
原因
上面我们学习过:strcpy函数的参数是:char* dest, const char* src
而下面这行代码:
strcpy(arr1, arr2);
就是在把一个整型元素传给一个char*指针的元素
并且,我们知道strcpy在遇到’\0’就停止拷贝以及strcpy的操作单位大小是一个字节
那么如图,整型数据在小端模式下存储的方式如图:
当拷贝完01后,遇到了00,我们都知道’\0’的ASCII码值是0,所以这就相当于拷贝结束,所以对于非字符数组,strcpy是无法使用的
这时,我们就要使用上文提到的内存函数了
memcmp
内存拷贝函数:可以拷贝任何类型的数据
此处联系之前学习的知识,就可以知道参数的类型是void*,
后面的num是需要拷贝的字节数
void * memcpy ( void * destination, const void * source, size_t num );
使用示例
下面介绍两个例子:拷贝整型数据、拷贝结构体类型数据
-struct Stu
{char name[20];int name;
};int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[5] = { 0 };struct Stu arr3[] = { {"zhang", 20}, {"wang", 15},{"li", 25} };struct Stu arr4[] = { 0 };memcpy(arr1, arr2, sizeof(arr1));memcpy(arr3, arr4, sizeof(arr3));return 0;
}
模拟实现
问题:
因为是void*类型的参数,所以我们这里既不能解引用、又不能与整数运算
所以我们就从第三个参数num入手,既然我不知道要拷贝的元素类型是什么,那么就以字节为单位进行拷贝,这样肯定就没问题了
*(char*)dest = *(char*)src;//处理赋值问题
++(char*)dest;//处理运算问题++(char*)src;
初步代码
void* my_memcpy(void* dest, const void* src, int num)
{assert(dest && src);//断言好习惯void* ret = dest;//存储首元素,方便拷贝之后打印while (num--){*(char*)dest = *(char*)src;++(char*)dest;//强制类型转换的优先级比++要低,所以++要写在前面++(char*)src;}return dest;
}
一些重点提示
特殊使用
在下面这个字符串中,我想要将1,2,3,4,5拷贝到3,4,5,6,7的位置上,怎么实现呢(使用my_memcpy函数)
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
像下面这么写可以吗?
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;my_memcpy(arr1 + 2, arr1, 20);for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}
运行结果:
咦?那这是为什么?
原因
初步说明:
源数据和目的地数据有关系:当想将3复制到5的地址处时,3已经在之前被替换成1了,所以结果就不对
解决方法
那么如果我们从后向前复制,是不是就可以解决了,先将5复制到7,4复制到6,以此类推
但这种方法也是有漏洞的,当要拷贝的源数据,在目的地数据之前时,程序也会出问题
所以,要根据实际情况来判断,但是有另外的函数来处理这种重叠拷贝的问题
下面我们就来学习memmove函数
注意
虽然使用memcpy函数去执行上面的操作也是可以实现的
但C语言标准中规定,memcpy函数只用来处理内存不重叠的拷贝
memmove函数是用来处理重叠内存的拷贝的
memmove
void * memmove ( void * destination, const void * source, size_t num );
使用示例
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;memmove(arr1 + 2, arr1, 20);return 0;
}
运行结果:
模拟实现
思路分析
分三种情况讨论
1
dest的地址小于src,也就是dest指向的元素在src指向的元素的左边
就从前向后拷贝
2
dest的地址大于src,也就是dest指向的元素在src指向的元素的右边
就从后向前拷贝
3
拷贝的内容无内存重叠,怎么拷贝都可以
最终代码
此处只提供一种分类方式,还有其他的分类方式,都可以
(就是需要注意在进行整数运算的时候,需要进行强制类型转换)
void* my_memmove(void* dest, const void* src, size_t count)
{assert(dest && src);void* ret = dest;if (dest < src)//从前向后{while (count--){*(char*)dest == *(char*)src;++(char*)dest;++(char*)src;}}else//从后向前{while (count--)//count改变,dest和src就不用改变了{*((char*)dest + count) = *((char*)src + count);}}return ret;
}int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;my_memmove(arr1 + 2, arr1, 20);for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}
memcmp
简单了解一下即可
介绍
定义如下
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
num是比较的字节个数
返回值
返回值与strcmp函数的返回值判定方式相同,
如果字符串1小于字符串2,返回值小于0
如果字符串1等于字符串2,返回值为0
如果字符串1大于字符串2,返回值大于0
memset
内存设置函数
介绍
作用:设置缓冲区作为特殊的字符
参数:
dest:目的地,即要修改哪块空间
c:要设置的字符是什么
count:要设置的字符数,单位是字节
使用
int main()
{char arr[10] = "";memset(arr, '#', 10);return 0;
}
运行过程:
注意事项
观察下面这段代码,运行结果是什么?
int main()
{int arr[10] = { 0 };memset(arr, 1, 10);printf("%d\n", arr[0]);return 0;
}
输出结果:
这是因为,参数中count单位是字节
上面的代码是将前十个字节改成了1,也就是十六进制的01 01 01 01
结语
关于函数的介绍到这里就结束了,希望你有所收获
之后我们会学习自定义数据类型:结构体,
我们下篇文章见
相关文章:

【C语言】字符分类函数、字符转换函数、内存函数
前言 之前我们用两篇文章介绍了strlen、strcpy、stract、strcmp、strncpy、strncat、strncmp、strstr、strtok、streeror这些函数 第一篇文章strlen、strcpy、stract 第二篇文章strcmp、strncpy、strncat、strncmp 第三篇文章strstr、strtok、streeror 今天我们就来学习字…...

Deep Learning With Pytorch - 最基本的感知机、贯序模型/分类、拟合
文章目录 如何利用pytorch创建一个简单的网络模型?Step1. 感知机,多层感知机(MLP)的基本结构Step2. 超平面 ω T ⋅ x b 0 \omega^{T}xb0 ωT⋅xb0 or ω T ⋅ x b \omega^{T}xb ωT⋅xb感知机函数 Step3. 利用感知机进行决策…...

测试工具coverage的高阶使用
在文章Python之单元测试使用的一点心得中,笔者介绍了自己在使用Python测试工具coverge的一点心得,包括: 使用coverage模块计算代码测试覆盖率使用coverage api计算代码测试覆盖率coverage配置文件的使用coverage badge的生成 本文在此基础上…...
安卓监听端口接收消息
文章目录 其他文章监听端口接收消息 建立新线程完整代码 其他文章 下面是我的另一篇文章,是在电脑上发送数据,配合本篇文章,可以实现电脑与手机的局域网通讯。直接复制粘贴就能行,非常滴好用。 点击连接 另外,如果你不…...
「Node」下载安装配置node.js
以下是Node.js的下载、安装和配置的全面教程: 下载 Node.js 打开 Node.js 官方网站:Previous Releases在主页上,您会看到两个版本可供选择:LTS(长期支持版本)和最新版(Current)。如…...

NOIP2014普及组,提高组 比例简化 飞扬的小鸟 答案
比例简化 说明 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有1498 人,反对的有 902人,那么赞同与反对的比例可以简单的记为1498:902。 不过,如果把调查结果就以这种…...
【Java】使用Apache POI识别PPT中的图片和文字,以及对应的大小、坐标、颜色、字体等
本文介绍如何使用Apache POI识别PPT中的图片和文字,获取图片的数据、大小、尺寸、坐标,以及获取文字的字体、大小、颜色、坐标。 官方文档:https://poi.apache.org/components/slideshow/xslf-cookbook.html 官方文档和网上的资料介绍的很少…...

根据源码,模拟实现 RabbitMQ - 实现消息持久化,统一硬盘操作(3)
目录 一、实现消息持久化 1.1、消息的存储设定 1.1.1、存储方式 1.1.2、存储格式约定 1.1.3、queue_data.txt 文件内容 1.1.4、queue_stat.txt 文件内容 1.2、实现 MessageFileManager 类 1.2.1、设计目录结构和文件格式 1.2.2、实现消息的写入 1.2.3、实现消息的删除…...
找到所有数组中消失的数(C语言详解)
题目:找到所有数组中消失的数 题目详情: 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1,n] 内。请你找出所以在 [1,n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。 示例1: 输入…...

计算机毕设项目之基于django+mysql的疫情实时监控大屏系统(前后全分离)
系统阐述的是一款新冠肺炎疫情实时监控系统的设计与实现,对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计,描述,实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体…...

Unity UI内存泄漏优化
项目一运行,占用的内存越来越多,不会释放,导致GC越来越频繁,越来越慢,这些都是为什么呢,今天从UI方面谈起。 首先让我们来聊聊什么是内存泄漏呢? 一般来讲内存泄漏就是指我们的应用向内存申请…...

学习笔记:Opencv实现图像特征提取算法SIFT
2023.8.19 为了在暑假内实现深度学习的进阶学习,特意学习一下传统算法,分享学习心得,记录学习日常 SIFT的百科: SIFT Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客…...
【golang】接口类型(interface)使用和原理
接口类型的类型字面量与结构体类型的看起来有些相似,它们都用花括号包裹一些核心信息。只不过,结构体类型包裹的是它的字段声明,而接口类型包裹的是它的方法定义。 接口类型声明中的这些方法所代表的就是该接口的方法集合。一个接口的方法集…...

【Linux操作系统】Linux系统编程中的共享存储映射(mmap)
在Linux系统编程中,进程之间的通信是一项重要的任务。共享存储映射(mmap)是一种高效的进程通信方式,它允许多个进程共享同一个内存区域,从而实现数据的共享和通信。本文将介绍共享存储映射的概念、原理、使用方法和注意…...

2235.两整数相加:19种语言解法(力扣全解法)
【LetMeFly】2235.两整数相加:19种语言解法(力扣全解法) 力扣题目链接:https://leetcode.cn/problems/add-two-integers/ 给你两个整数 num1 和 num2,返回这两个整数的和。 示例 1: 输入:num…...

中国剩余定理及扩展
目录 中国剩余定理解释 中国剩余定理扩展——求解模数不互质情况下的线性方程组: 代码实现: 互质: 非互质: 中国剩余定理解释 在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二&#x…...

数据在内存中的存储(deeper)
数据在内存中的存储(deeper) 一.数据类型的详细介绍二.整形在内存中的存储三.浮点型在内存中的存储 一.数据类型的详细介绍 类型的意义: 使用这个类型开辟内存空间的大小(大小决定了使用范围)如何看待内存空间的视角…...
算法修炼Day52|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组
LeetCode:300.最长递增子序列 300. 最长递增子序列 - 力扣(LeetCode) 1.思路 dp[i]的状态表示以nums[i]为结尾的最长递增子序列的个数。 dp[i]有很多个,选择其中最大的dp[i]Math.max(dp[j]1,dp[i]) 2.代码实现 1class Solution {2 pub…...

使用 HTML、CSS 和 JavaScript 创建实时 Web 编辑器
使用 HTML、CSS 和 JavaScript 创建实时 Web 编辑器 在本文中,我们将创建一个实时网页编辑器。这是一个 Web 应用程序,允许我们在网页上编写 HTML、CSS 和 JavaScript 代码并实时查看结果。这是学习 Web 开发和测试代码片段的绝佳工具。我们将使用ifram…...

百望云联合华为发布票财税链一体化数智解决方案 赋能企业数字化升级
随着数据跃升为数字经济关键生产要素,数据安全成为整个数字化建设的重中之重。为更好地帮助企业发展,中央及全国和地方政府相继出台了多部与数据相关的政策法规,鼓励各领域服务商提供具有自主创新的软件产品与服务,帮助企业在合规…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...