C语言:字符函数 字符串函数 内存函数

C语言:字符函数 & 字符串函数 & 内存函数

    • 字符函数
      • 字符分类函数
      • 字符转换函数
        • tolower
        • toupper
    • 字符串函数
      • strlen
      • strcpy
      • strcat
      • strcmp
      • strstr
      • strtok
    • 内存函数
      • memcpy
      • memmove
      • memset
      • memcmp


字符函数

顾名思义,字符函数就是作用于字符的函数,而字符函数主要分为字符分类函数以及字符转换函数

字符分类函数

字符分类函数,用于判断一个字符是否属于某一个类

函数参数符合条件
isntrl任何字符
isspace空白字符,空格'',换页符'\f',换行符'\n',回车符'\r',制表符'\t',垂直制表符'\v'
isdigit十进制数字0 - 9
isxdigit十六进制数字,包括0 - 9a - fA - F
islower小写字母a - z
isupper大写字母A - Z
isalpha字母a - zA - Z
isalnum字母或数字,a - zA - Z0 - 9
ispunct标点符号,任何不属于字母或数字的可打印字符
isgraph任何图形字符
isprint任何可打印字符

对于以上函数,只要传入的字符符合要求,返回非0数字;否则返回0;


字符转换函数

tolower

将传入的大写字母变成小写字母

toupper

将传入的小写字母变成大写字母


字符串函数

strlen

strlen函数用于求出字符串的长度,其判定结束的标志为\0

大部分情况下,\0出现在字符串的结尾,但是如果\0出现在字符串的中间,那么我们就无法得到字符串的正确长度。


strcpy

在这里插入图片描述
strcpy函数用于拷贝字符串,其参数如下:

destination:拷贝后字符串存放的空间
source:字符串的来源

返回值为char*,指向拷贝后的destination,方便链式访问

  • 对于source来说,其结束的标志依然为'\0',其默认带有的'\0'也会被拷贝到指定字符串的末尾。

  • destination必须指向可以修改的空间,并且足以放置source的字符个数。

strncpy是一个与strcpy功能一致的函数,但是其可以限制拷贝字符的个数
对于strcpy,其拷贝字符的个数就是source'\0'之前字符个数。strncpy可以传入第三个参数,用于规定拷贝字符的个数。

示例:

char arr[100] = { 0 };
strncpy(arr, "hello", 3);

以上代码把"hello"的前三个字符”hel“拷贝进了arr中。

另外,如果字符串的长度不足n,那么少的位置会用\0补充


strcat

在这里插入图片描述
strcat函数用于对字符串进行追加,其会把source追加到destination的末尾。所以destinationsource都必须由\0结尾

示例:

char arr[100] = "hello";
strcat(arr, "world");

追加后,arr内部存储的就是helloworld了。

注意事项:

  • C语言标准没有要求此函数可以自追加,这取决于编译器的实现
  • destination必须是可以修改的

同样的,这个函数也有限制长度的版本strncat。第三个参数用于限定追加字符串的长度:当字符串长度超过n,则只追加n个字符;当字符串长度小于n,那么追加完这个字符串就不再追加


strcmp

在这里插入图片描述
此函数用于比较两个字符串的大小

  • str1大于str2,返回大于0的值
  • str1等于str2,返回0
  • str1小于str2,返回小于0的值

比较的是两个字符串的字典序,而非长度。

同样的,该函数存在一个限制长度的版本strncmp,比较两个字符串的前n个字符。


strstr

在这里插入图片描述
此函数用于进行字符串查找,即在str1中查找str2

如果找到了,返回str1中指向str2的指针
如果没找到,返回NULL


strtok

在这里插入图片描述
strtok函数用于对字符串进行分割,其有两个参数:

str:被分割的字符串
delimiters:分隔符组成的字符串

比如delimiters如果是“@#!”,那么这个字符串遇到#@!时就会将字符串进行分隔。

当在字符串中找到了对应的分隔符:

  1. 将这个分隔符改为\0
  2. 返回指向这个字符的指针

如果没找到字符,或者遇到末尾,此时返回NULL

另外地,strtok如果对str传入了NULL,下一次会从上一次更改的地方开始查找

示例:

char arr[100] = "hello!world?cs@dn";
const char* p = "!?@";for (char* r = strtok(arr, p); r != NULL; r = strtok(NULL, p))
{printf("%s\n", r);
}

以上代码中,第一次调用strtok传入了arr,后续都传入NULL,从而完成整个字符串的分隔:
输出结果:

hello
world
cs
dn

内存函数

C语言中的内存函数用于对内存进行操控,主要包括内存的拷贝,初始化,以及内存数据的比较。

memcpy

在这里插入图片描述

函数用于对内存进行拷贝,此函数包含三个参数:

destination:目的地,即拷贝后的数据存入的地方
source:源,即被拷贝的内存
num:字节数

示例:

int arr1[] = { 1,2,3,4,5 };
int arr2[5] = { 0 };memcpy(arr2, arr1, sizeof(int) * 5);

以上代码,完成了两个数组之间的内存拷贝,拷贝方向为:从arr1拷贝到arr2,共拷贝了sizeof(int) * 5 = 20个字节。

现在我们模拟实现一个memecpy

void* my_memcpy(void* destination, void* source, size_t num)
{void* ret = destination;assert(destination && source);while (num--){*(char*)destination = *(char*)source;destination = (char*)destination + 1;source = (char*)source + 1;}return ret;
}

可以看到,memcpy的拷贝是以字节为单位,将传入的void*指针转为char*指针,然后一个一个字节进行拷贝。这样这个函数就可以处理任何类型的内存拷贝。

但是这个函数存在一个问题,无法拷贝内存发生重叠的函数

看到以下过程:

int arr[6] = { 1,2,3,4 };memcpy(arr + 2, arr, sizeof(int) * 4 ;

此代码希望把arr的前四个元素拷贝到后四位去,即:

1 2 1 2 3 4

实际输出结果:

1 2 1 2 1 2

为什么会这样?

看到以下过程:
在这里插入图片描述
我们要把蓝色区域的数值拷贝到红色区域,从左往右拷贝,第一次进行拷贝,由于内存重叠,1 2会把3 4覆盖,导致后续拷贝3 4时拷贝到的还是1 2

C语言标准库没有要求memcpy对重叠的内存进行处理,但是有的编译器可以处理这种情况,有的不可以。
为处理这个情况,C语言有专门的函数memmove用于处理重叠内存的情况。


memmove

memmove函数也用于进行内存拷贝,与memcpy不同的是,C标准规定其可以处理内存的重叠。

示例:

int arr[6] = { 1,2,3,4 };memmove(arr + 2, arr, sizeof(int) * 4 ;

同样的代码,输出结果为:

1 2 1 2 3 4

这是如何做到的?
其实就是一个简单的拷贝方向的问题:

当我们把以上的重叠拷贝,从右向左拷贝:
在这里插入图片描述
可以看到,虽然发生了内存的重叠,但是我们先把会被覆盖的数据拷贝好,然后再覆盖重叠区域的数据,此时我们的拷贝就正常运行了。

所以memmove的实现中,我们要根据内存的重叠情况,来控制内存的拷贝方向,以保证重叠的数据先被拷贝。

代码如下:

void* my_memmove(void* destination, void* source, size_t num)
{void* ret = destination;assert(destination && source);if (destination < source){while (num--){*(char*)destination = *(char*)source;destination = (char*)destination + 1;source = (char*)source + 1;}}else{while (num--){*((char*)destination + num) = *((char*)source + num);}}return ret;
}

destination指针小于source,我们就从低地址向高地址拷贝
destination指针大于source,我们就从高地址向低地址拷贝


memset

在这里插入图片描述
memset函数用于对内存进行初始化,其包含三个参数:

ptr:指向待初始化内存的指针
value:希望内存被初始化的值
num:想要初始化内存的字节数

此函数只能按照字节初始化内存,比如以下代码:

int arr[5] = { 0 };
memset(arr, 1, sizeof(int) * 5);

以上代码并不是把数组中的五个int元素初始化为1,而是把每个字节都初始化为00000001


memcmp

在这里插入图片描述
此函数用于比较内存中的数据,ptr1ptr2是被比较的内存。
其按照字节进行比较,从前往后,一个一个字节比较ASCII码值,当某一对字节的ASCII码值不同,此时该字节ASCII码值大的内存,就是比较大的。


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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

搜索算法(算法竞赛、蓝桥杯)--双向DFS+二分查找

1、B站视频链接&#xff1a;B26 双向DFS 送礼物_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; int n,m; int g[46];//存储所有物品的质量 int w[1<<23];//存储所有能凑出来的重量 int ans,cnt;//w的个数是cnt//搜索第u个数&#xff0c;和为s; …

揭示预处理中的秘密!(二)

目录 ​编辑 1. #运算符 2. ##运算符 3. 命名约定 4. #undef 5. 命令行定义 6. 条件编译 7. 头文件的被包含的方式 8.嵌套文件包含 9. 其他预处理指令 10. 完结散花 悟已往之不谏&#xff0c;知来者犹可追 …

几道特别难搞的数据库面试题

一、多选题(不定项选择) 在下面所列出的条目中&#xff0c;哪些是数据库管理系统的基本功能&#xff1f; A ‍‍ 数据库定义‍‍ B ‍‍ 数据库的建立和维护‍‍ C ‍‍ 数据库存取‍‍ D 数据库和其他软件系统的通信在Mongodb支持的数据类型中&#xff0c;ObjectId&#xff1…

【web APIs】3、(学习笔记)有案例!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概念其他事件页面加载事件元素滚动事件页面尺寸事件 元素尺寸与位置 二、案例举例电梯导航 前言 掌握阻止事件冒泡的方法理解事件委托的实现原理 一、概念…

设计模式七:责任链模式

文章目录 1、责任链模式2、spring中的责任链模式Spring InterceptorServlet FilterNetty 1、责任链模式 责任链模式为请求创建了一个接收者对象的链&#xff0c;在这种模式下&#xff0c;通常每个节点都包含对另一个节点者的引用。每个节点针对请求&#xff0c;处理自己感兴趣…

鸿蒙应用成企业布局新方向 鸿蒙人才成开年之后“香饽饽”

随着春节假期的结束&#xff0c;职场人也开始返工返岗。与此同时2024年春招季也已拉开帷幕。2月23日&#xff0c;据智联招聘发布的《2024年春招市场行情周报》&#xff08;第一期&#xff09;显示&#xff0c;2024年春节后第一周&#xff0c;依托消费需求释放与制造业返工复产&…

pv、pvc

目录 1、什么是pv和pvc 2、pvc的使用逻辑 3、StorageClass 4、pv和pvc相互作用 5、pv的生命周期中&#xff0c;一般有几种状态&#xff1f; 6、一个pv从创建到销毁的流程 7、nfs使用pv和pvc 7.1、配置nfs存储 7.2这里定义5个PV&#xff0c;并且定义挂载的路径以及访问…

成都规模最大的直播基地为数字经济时代注入新的活力

直播行业近年来在全球范围内迅速崛起&#xff0c;成为了数字经济时代的新业态。作为中国西南地区的中心城市&#xff0c;成都紧跟时代步伐&#xff0c;积极布局直播产业&#xff0c;以成都直播基地为载体&#xff0c;引领直播行业健康、多元发展。 天府锋巢直播产业基地作为成都…

Android和Linux的开发差异

最近开始投入Android的怀抱。说来惭愧&#xff0c;08年就听说这东西&#xff0c;当时也有同事投入去看&#xff0c;因为恶心Java&#xff0c;始终对这玩意无感&#xff0c;没想到现在不会这个嵌入式都快要没法搞了。为了不中年失业&#xff0c;所以只能回过头又来学。 首先还是…

预付费远传水表管理系统

预付费远传水表管理系统是一种为水表计量和管理而设计的先进系统&#xff0c;结合了预付费和远传智能化技术&#xff0c;为用户和水务部门提供了更便捷、高效的水表管理解决方案。通过这种系统&#xff0c;用户能够根据自身需求预付水费&#xff0c;同时水务部门也能实现对水表…

Java 小项目开发日记 01(注册接口的开发)

Java 小项目开发日记 01&#xff08;注册接口的开发&#xff09; 1.项目需求 完成注册接口 2.项目目录 3. 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

Apache Bench(ab )压力测试

目录 参数说明示例1&#xff1a;压力测试示例2&#xff1a;测试post接口post数据文件该如何编写&#xff1f; apr_pollset_poll: The timeout specified has expired (70007)apr_socket_recv: Connection reset by peer (104)参考 参数说明 官方文档参考这里。 ab -c 100 -n …

基础!!!吴恩达deeplearning.ai:神经网络中使用softmax

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai 文章目录 softmax作为输出层的神经网络Tensorflow的实现softmax的改进实现数值舍入误差(Numerical Roundoff Errors)sigmoid修改修改softmax 在上一篇博客中我们了解了有关softmax的原理相关内容…

【mysql版本修改】

1、使用telnet确认当前mysql版本号 telnet <MySQL服务器IP地址> <MySQL端口号> telnet 192.168.38.20 33062、使用strings查看/usr/sbin/mysqld中包含版本号的字符串 # 查看/usr/sbin/mysqld文件中是否包含对应的版本号 strings /usr/sbin/mysqld | grep 5.7.30 …

11. Informer 机制总结

Informer 机制 在 Kubernetes 系统中&#xff0c;组件之间通过 HTTP 协议进行通信&#xff0c;在不依赖任何中间件的情况下需要保证消息的实时性、可靠性、顺序性等。那么 Kubernetes 是如何做到的呢&#xff1f;答案就是 Informer 机制。Kubernetes 的其他组件都是通过 clien…

python|闲谈2048小游戏和数组的旋转及翻转和转置

目录 2048 生成数组 n阶方阵 方阵旋转 顺时针旋转 逆时针旋转 mxn矩阵 矩阵旋转 测试代码 测试结果 翻转和转置 2048 《2048》是一款比较流行​的数字游戏​&#xff0c;最早于2014年3月20日发行。原版2048由Gabriele Cirulli首先在GitHub上发布&#xff0c;后被移…

华为手动ipv6-to-ipv4隧道

中间r2的两个接口配置两个地址就行了&#xff0c;其它什么都不用配置 两边出接口R1和R3手动隧道建立&#xff1a;先把IPV4打通&#xff0c;并配置默认路由 再起隧道接口上进行配置&#xff0c;再配置带隧道的默认路由 PC上和上联接口网关只有IPV6地址 最终两个PC可以ping通 …

node 之 http模块

1.什么是http模块 在网络节点中&#xff0c;负责消费资源的电脑叫做客户端&#xff1b;负责对外提供网络资源的电脑&#xff0c;叫做服务器 http模块是node.js官方提供的&#xff0c;用来创建web服务器的模块&#xff0c;通过http模块提供的http.createServer()方法&#xff0c…

武器大师——操作符详解(上)

目录 一、操作符的分类 二、二进制和进制转换 2.1.二进制与十进制的互相转化 2.1.1 二进制转十进制 2.1.2 十进制转二进制 ​编辑 2.2.二进制转8进制和16进制 2.2.1 转8进制 2.2.2 转16进制 三、原码、反码、补码 四、移位操作符 4.1.左移操作符&#xff08;<…

【C语言】linux内核netdev_start_xmit函数

一、中文注释 static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq, bool more) {// 获取网络设备操作集合const struct net_device_ops *ops dev->netdev_ops;int rc;// 调用实际发送数据包的函数&…