【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

结语

关于函数的介绍到这里就结束了,希望你有所收获
之后我们会学习自定义数据类型:结构体,
我们下篇文章见

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

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

相关文章

ES 概念

es 概念 Elasticsearch是分布式实时搜索、实时分析、实时存储引擎&#xff0c;简称&#xff08;ES&#xff09;成立于2012年&#xff0c;是一家来自荷兰的、开源的大数据搜索、分析服务提供商&#xff0c;为企业提供实时搜索、数据分析服务&#xff0c;支持PB级的大数据。 -- …

HTML详解连载(8)

HTML详解连载&#xff08;8&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽浮动-产品区域布局场景 解决方法清除浮动方法一&#xff1a;额外标签发方法二&#xff1a;单伪元素法方法三&#xff1a;双伪元素法方法四&#xff1a;overflow浮动-总结…

GO学习之 数据库(mysql)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

【C++】stack/queue/优先级队列的模拟实现

目录 1. stack/queue1.1 模拟实现 2. 优先级队列2.1 模拟实现2.2 仿函数 1. stack/queue stack文档说明 queue文档说明 stack和queue被称为容器适配器。 容器适配器是什么&#xff1f; 它是一种特殊的容器类型&#xff0c;通过封装已有的容器类型来提供特定功能的接口函数&a…

使用Nginx调用网关,然后网关调用其他微服务

问题前提&#xff1a;目前我的项目是已经搭建了网关根据访问路径路由到微服务&#xff0c;然后现在我使用了Nginx将静态资源都放在了Nginx中&#xff0c;然后我后端定义了一个接口访问一个html页面&#xff0c;但是html页面要用到静态资源&#xff0c;这个静态资源在我的后端是…

关于es中索引,倒排索引的理解

下面是我查询进行理解的东西 也就是说我们ES中的索引就相当于我们mysql中的数据库表&#xff0c;索引库就相当于我们的数据库&#xff0c;我们按照mapping规则会根据相应的字段&#xff08;index为true默认&#xff09;来创建倒排索引&#xff0c;这个倒排索引就相当于我们索引…

QT-Mysql数据库图形化接口

QT sql mysqloper.h qsqlrelationaltablemodelview.h /************************************************************************* 接口描述&#xff1a;Mysql数据库图形化接口 拟制&#xff1a; 接口版本&#xff1a;V1.0 时间&#xff1a;20230727 说明&#xff1a;支…

【ARM Linux 系统稳定性分析入门及渐进12 -- GDB内存查看命令 “x“(examine)】

文章目录 gdb 内存查看命令 examine 上篇文章&#xff1a;ARM Linux 系统稳定性分析入门及渐进11 – GDB( print 和 p 的使用| 和 &#xff1a;&#xff1a;的使用|ptype|{&#xff1c;type&#xff1e;} &#xff1c;addr&#xff1e; ) gdb 内存查看命令 examine examine是…

【数据结构】如何用队列实现栈?图文详解(LeetCode)

LeetCode链接&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 本文默认读者已经掌握栈与队列的基本知识 或者先看我的另一篇博客&#xff1a;【数据结构】栈与队列_字节连结的博客-CSDN博客 做题思路 由于我们使用的是C语言&#xff0c;不能直接使用队…

​Kubernetes的演变:从etcd到分布式SQL的过渡

DevRel领域专家Denis Magda表示&#xff0c;他偶然发现了一篇解释如何用PostgreSQL无缝替换etcd的文章。该文章指出&#xff0c;Kine项目作为外部etcd端点&#xff0c;可以将Kubernetes etcd请求转换为底层关系数据库的SQL查询。 受到这种方法的启发&#xff0c;Magda决定进一步…

react-native-webview RN和html双向通信

rn登录后得到的token需要传递给网页&#xff0c;js获取到的浏览器信息需要传递给rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

【MySQL系列】--初识数据库

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

在ubuntu中将dict.txt导入到数据库sqlite3

将dict.txt导入到数据库 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//创建泵打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…

使用IDM下载视频出现“由于法律原因,IDM无法下载...

一、问题描述 由于法律原因,IDM无法下载..,如图: 二、原因分析 下载该IDM抓取的M3U8文件,查看其中的内容发现 : #EXT-X-KEY 字段已经写明了加密方式是AES-128,包含一个URI和IV值 #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:8 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-KEY:…

Cpp学习——list的模拟实现

目录 一&#xff0c;实现list所需要包含的三个类 二&#xff0c;三个类的实现 1.list_node 2.list类 3.iterator_list类 三&#xff0c;功能实现 1.list类里的push_back() 2.iterator类里的运算符重载 3&#xff0c;list类里面的功能函数 1.insert&#xff08;&#xff…

2023国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

Linux常用命令——dig命令

在线Linux命令查询工具 dig 域名查询工具 补充说明 dig命令是常用的域名查询工具&#xff0c;可以用来测试域名系统工作是否正常。 语法 dig(选项)(参数)选项 <服务器地址>&#xff1a;指定进行域名解析的域名服务器&#xff1b; -b<ip地址>&#xff1a;当主…

Log4net在.Net Winform项目中的使用

引言&#xff1a; Log4net是一个流行的日志记录工具&#xff0c;可以帮助开发人员在应用程序中实现高效的日志记录。本文将提供一个详细的分步骤示例&#xff0c;来帮助您在.Net Winform项目中使用Log4net。 目录 一、安装Log4net二、配置Log4net三、在项目中使用Log4net四、初…

深入探索:Kali Linux 网络安全之旅

目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux&#xff0c;它是一种基于 Debian 的 Linux 发行版&#xff0c;专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…