字符串函数能有什么坏心思?
🚀write in front🚀
📝个人主页:认真写博客的夏目浅石.
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:夏目的C语言宝藏
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊
✉️如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn
文章目录
- 前言
- 函数介绍以及模拟实现
- 1.1 strlen函数
- 1.2 strcpy函数
- 1.3 strcat函数
- 1.4 strcmp函数
- 1.5 strncpy函数
- 1.6 strncat函数
- 1.7 strncmp函数
- 1.8 strstr函数
- 1.9 strtok函数
- 1.10 strerror函数
- 1.11 memcpy函数
- 1.12 memmove函数
- 1.13 memcmp函数
- 总结
前言
函数的学习离不开这些
提示:以下是本篇文章正文内容,下面案例可供参考
函数介绍以及模拟实现
1.1 strlen函数
size_t strlen ( const char * str );
- 字符串已经
'\0'
作为结束标志,strlen
函数返回的是在字符串中'\0'
前面出现的字符个数(不包含'\0'
)。 - 参数指向的字符串必须要以
'\0'
结束。 - 注意函数的返回值为
size_t
,是无符号的
设置为
size_t
的原因介绍:
strlen
是求字符串长度的,求出的长度是不可能为负数的
所以返回类型设置为size_t
也是合情合理的
typedef unsigned int size_t
验证代码:
#include<stdio.h>
#include<string.h>int main()
{//数学上:3-6=-3;//实际上:size_t所以俩差值是一个很大的数 if(strlen("abc") - strlen("abcdef") > 0){printf(">\n");}else{printf("<=\n");}return 0;
}
运行图示:
strlen
函数的模拟实现
方法一:遍历法
#include<stdio.h>
#include<assert.h>
int my_strlen(char* str)
{assert(str != NULL);int cnt=0;while(*str!='\0'){cnt++;str++;}return cnt;
}
int main()
{char arr[]="abcdef";int len=my_strlen(arr);printf("%d\n",len);return 0;
}
方法二:递归法
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)
{assert(str!=NULL);if(*str!='\0')return 1+my_strlen(str+1);else return 0;
}
int main()
{char arr[]="abcdef";int len=my_strlen(arr);printf("%d\n",len);return 0;
}
方法三:减指法
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)
{assert(str!=NULL);if(*str!='\0')return 1+my_strlen(str+1);else return 0;
}
int main()
{char arr[]="abcdef";int len=my_strlen(arr);printf("%d\n",len);return 0;
}
1.2 strcpy函数
char* strcpy(char * destination, const char * source );
- Copies the C string pointed by source into the array pointed by destination, including theterminating null character (and stopping at that point).
- 源字符串必须以
'\0'
结束。 - 会将源字符串中的
'\0'
拷贝到目标空间。 - 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
strcpy
函数的模拟实现
方法一:遍历法
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest , const char* src)
{char *ret=dest;assert(dest&&src);while(*dest++ = *src++){;}return ret;
}int main()
{char arr[]="xxxxxxxxxx";char a[]="abcdef";my_strcpy(arr,a);printf("%s",arr);return 0;
}
方法二:遍历法
#include<stdio.h>
#include<assert.h>
void my_strcpy(const char*str,char* ptr)
{assert(str!=NULL);assert(ptr!=NULL);while(*str!='\0'){*ptr=*str;str++;ptr++;}
}
int main()
{char arr[]="xxxxxxxxxx";char a[]="abcdef";my_strcpy(arr,a);printf("%s",arr);return 0;
}
1.3 strcat函数
char * strcat ( char * destination, const char * source );
- Appends a copy of the source string to the destination string. The terminating null characterin destination is overwritten by the first character of source, and a null-character is includedat the end of the new string formed by the concatenation of both in destination.
- 源字符串必须以
'\0'
结束。 - 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
函数的使用:
#include<stdio.h>
#include<assert.h>
#include<string.h>int main()
{char arr[20]="hello ";strcat(arr,"world");printf("%s",arr); return 0;
}
strcat
函数的模拟实现
#include<stdio.h>
#include<assert.h>
#include<string.h>char* my_strcat(char* dest,const char* src)
{assert(dest && src);char* start= dest;//1.寻找'\0'while(*dest){dest++;}//2.追加while(*dest++ = *src++){;}return start;
}int main()
{char arr[20]="hello ";my_strcat(arr,"world");printf("%s",arr); return 0;
}
1.4 strcmp函数
int strcmp ( const char * str1, const char * str2 );
- This function starts comparing the first character of each string. If they are equal to eachother, it continues with the following pairs until the characters differ or until a terminatingnull-character is reached.
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
strcmp
函数的模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>int my_strcmp(const char* str1,const char* str2)
{assert(str1 && str2);while(*str1 == *str2){if(*str1=='\0')return 0;str1++;str2++;}
// if(*str1 > *str2)
// return 1;
// else
// return -1;return *str1 - *str2;
}int main()
{char arr1[]="ab";char arr2[]="abcde";int ret=my_strcmp(arr1,arr2);printf("%d\n",ret);return 0;
}
1.5 strncpy函数
char * strncpy ( char * destination, const char * source, size_t num );
- Copies the first num characters of source to destination. If the end of the source C string(which is signaled by a null-character) is found before num characters have been copied,destination is padded with zeros until a total of num characters have been written to it.
- 拷贝
num
个字符从源字符串到目标空间。 - 如果源字符串的长度小于
num
,则拷贝完源字符串之后,在目标的后边追加0
,直到num
个。
函数的使用:
#include<stdio.h>
#include<string.h>
#include<assert.h>int main()
{char arr1[20]="xxxxxxxxxx";strncpy(arr1,"abcdef",3);printf("%s\n",arr1);return 0;
}
1.6 strncat函数
char * strncat ( char * destination, const char * source, size_t num );
- Appends the first num characters of source to destination, plus a terminating null-character.
- If the length of the C string in source is less than num, only the content up to the terminatingnull-character is copied
函数的使用:
#include <stdio.h>
#include <string.h>
int main ()
{char str1[20];char str2[20];strcpy (str1,"To be ");strcpy (str2,"or not to be");strncat (str1, str2, 6);puts (str1);return 0;
}
1.7 strncmp函数
int strncmp ( const char * str1, const char * str2, size_t num );
函数的使用:
#include <stdio.h>
#include <string.h>
int main ()
{char str[][5] = { "R2D2" , "C3PO" , "R2A6" };int n;puts ("Looking for R2 astromech droids...");for (n=0 ; n<3 ; n++)if (strncmp (str[n],"R2xx",2) == 0){printf ("found %s\n",str[n]);}return 0;
}
1.8 strstr函数
char * strstr ( const char *str1, const char * str2);
- Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
函数的使用:
#include<stdio.h>
#include<string.h>
#include<assert.h>int main()
{char arr1[]="abbbbcdef";char arr2[]="bbcd";char* ret=strstr(arr1,arr2);if(ret==NULL){printf("找不到\n");} else{printf("%s\n",ret); }return 0;
}
模拟实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>char* my_strstr(char* str1,char* str2)
{assert(str1&&str2);if(*str2=='\0'){return str1;}char* s1=str1;char* s2=str2;char* cp=str1;while(*cp){s1=cp;s2=str2;while(*s1!='\0' && *s2!='\0' && *s1==*s2){++s1;++s2;}if(*s2=='\0'){return cp;}cp++;}return NULL;
}int main()
{char arr1[]="abbbbcdef";char arr2[]="bbcd";char* ret= my_strstr(arr1,arr2);if(ret==NULL){printf("找不到\n");} else{printf("%s\n",ret); }return 0;
}
1.9 strtok函数
char * strtok ( char * str, const char * sep );
sep
参数是个字符串,定义了用作分隔符的字符集合- 第一个参数指定一个字符串,它包含了
0个
或者多个
由sep
字符串中一个或者多个分隔符分割的标记。 strtok
函数找到str
中的下一个标记,并将其用\0
结尾,返回一个指向这个标记的指针。(注:
strtok
函数会改变被操作的字符串,所以在使用strtok
函数切分的字符串一般都是临时拷贝的内容
并且可修改。)strtok
函数的第一个参数不为NULL
,函数将找到str
中第一个标记,strtok
函数将保存它在字符串中的位置。strtok
函数的第一个参数为NULL
,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。- 如果字符串中不存在更多的标记,则返回
NULL
指针。
#include<stdio.h>
#include<string.h>int main()
{char arr[]="192#168.120.85";char* p="#.";char buf[20]={0};strcpy(buf,arr);char* ret=NULL;for(ret=strtok(buf,p);ret!=NULL;ret=strtok(NULL,p)){printf("%s\n",ret);}return 0;
}
1.10 strerror函数
char * strerror ( int errnum );
- 返回错误码,所对应的错误信息。
1.11 memcpy函数
void * memcpy ( void * destination, const void * source, size_t num );
- 函数
memcpy
从source
的位置开始向后复制num
个字节的数据到destination
的内存位置。 - 这个函数在遇到
'\0'
的时候并不会停下来。 - 如果
source
和destination
有任何的重叠,复制的结果都是未定义的。
模拟实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>void* my_memcpy(void* dest,const void* src,size_t num)
{void* ret=dest;assert(dest&&src);while(num--){*(char*)dest=*(char*)src;dest=(char*)dest+1;src=(char*)src+1;}return ret;
}int main()
{int arr1[]={1,2,3,4,5,6,7,8,9,10};int arr2[10]={0};my_memcpy(arr2,arr1+2,20);return 0;
}
1.12 memmove函数
void * memmove ( void * destination, const void * source, size_t num );
- 和
memcpy
的差别就是memmove
函数处理的源内存块和目标内存块是可以重叠的。 - 如果源空间和目标空间出现重叠,就得使用
memmove
函数处理。
模拟实现:
#include<stdio.h>
#include<assert.h>void* my_memmove(void* dest,const void* src,size_t num)
{void* ret=dest;assert(dest&&src);if(dest<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;
}int main()
{int arr[]={1,2,3,4,5,6,7,8,9,10};my_memmove(arr,arr+2,20);for(int i=0;i<10;i++){printf("%d ",arr[i]);}puts("");return 0;
}
1.13 memcmp函数
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
- 比较从ptr1和ptr2指针开始的num个字节
- 返回值如下:
#include<stdio.h>
#include<string.h>int main()
{int arr1[]={1,2,6};int arr2[]={1,2,5};int ret=memcmp(arr1,arr2,9);printf("%d\n",ret);return 0;
}
总结
本期学习了很多字符串相关的函数,包括基本用法和模拟实现,都给大家书写了出来,希望大家可以多敲一遍,加深对于函数的印象。
我是夏目浅石,希望和你一起学习进步,刷题无数!!!希望各位大佬能一键三连支持一下博主,hhhh~我们下期见喽
如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn
✨原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力!\textcolor{9c81c1}{点赞,你的认可是我创作的动力!}点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!\textcolor{ed7976}{收藏,你的青睐是我努力的方向!}收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!\textcolor{98c091}{评论,你的意见是我进步的财富!}评论,你的意见是我进步的财富!
相关文章:

字符串函数能有什么坏心思?
🚀write in front🚀 📝个人主页:认真写博客的夏目浅石. 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:夏目的C语言宝藏 💬总结:希望你看完之…...

Vue3 组件之间的通信
组件之间的通信 经过前面几章的阅读,相信开发者已经可以搭建一个基础的 Vue 3 项目了! 但实际业务开发过程中,还会遇到一些组件之间的通信问题,父子组件通信、兄弟组件通信、爷孙组件通信,还有一些全局通信的场景。 …...

多路查找树
1.二叉树与 B 树 1.1二叉树的问题分析 二叉树的操作效率较高,但是也存在问题, 请看下面的二叉树 二叉树需要加载到内存的,如果二叉树的节点少,没有什么问题,但是如果二叉树的节点很多(比如 1 亿), 就 存在如下问题:问…...
Mybatis——注入执行sql查询、更新、新增以及建表语句
文章目录前言案例dao和mapper编写XXXmapper.xml编写编写业务层代码,进行注入调用额外扩展--创建表语句前言 在平时的项目开发中,mybatis应用非常广泛,但一般都是直接CRUD类型sql的执行。 本片博客主要说明一个另类的操作,注入sq…...

即时通讯系列-4-如何设计写扩散下的同步协议方案
1. 背景信息 上篇提到了, IM协议层是主要解决会话和消息的同步, 在实现上, 以推模式为主, 拉模式为辅. 本文Agenda: (How)如何同步(How)如何设计同步位点如何设计 Gap过大(SyncGapOverflow) 机制如何设计Ack机制总结 提示: 本系列文章不会单纯的给出结论, 希望能够分享的是&…...

tui-swipe-action组件上的按钮点击后有阴影的解决方法
大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。 目录 前言问题描述问题解决前言 一直未敢涉足电商领域,总觉得这里面的道道很多,又是支付、又是物流的,还涉及到金钱,所以我们所做的项目,一直都是XXXX管理系统,XXX考核系统,移动端的也是,XX健康管理平台…… 但…...

【大数据Hadoop】Hadoop 3.x 新特性总览
Hadoop 3.x 新特性剖析系列11. 概述2. 内容2.1 JDK2.2 EC技术2.3 YARN的时间线V.2服务2.3.1 伸缩性2.3.2 可用性2.3.3 架构体系2.4 优化Hadoop Shell脚本2.5 重构Hadoop Client Jar包2.6 支持等待容器和分布式调度2.7 支持多个NameNode节点2.8 默认的服务端口被修改2.9 支持文件…...

Python-第三天 Python判断语句
Python-第三天 Python判断语句一、 布尔类型和比较运算符1.布尔类型2.比较运算符二、if语句的基本格式1.if 判断语句语法2.案例三、 if else 语句1.语法2.案例四 if elif else语句1.语法五、判断语句的嵌套1.语法六、实战案例一、 布尔类型和比较运算符 1.布尔类型 布尔&…...

失手删表删库,赶紧跑路?!
在数据资源日益宝贵的数字时代公司最怕什么?人还在,库没了是粮库、车库,还是小金库?实际上,这里的“库”是指的数据库Ta是公司各类信息的保险柜小到企业官网和客户信息大到金融机构的资产数据和国家秘密即便没有跟数据…...

技术树基础——16排它平方数(Bigdecimal,int,string,数组的转换)
题目:03879 * 203879 41566646641这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。具有这样特点的6位数还有一个,请你…...
04动手实践:手把手带你实现gRPC的Hello World
这篇文章就从实践的角度出发,带大家一起体验一下gRPC的Hello World。文中的代码将全部使用Go语言实现,使用到的示例也是GitHub上提供的grpc-go,下面我们开始: Hello World官方示例 首先我们要clone GitHub上gRPC的源代码到我们本地 git clone https://github.com/grpc/g…...
区块链技术与应用1——BTC-密码学原理
文章目录比特币中的密码学原理1. 哈希函数2. 数字签名3. 比特币中的哈希函数和数字签名简单介绍:比特币与以太坊都是以区块链技术为基础的两种加密货币,因为他们应用最广泛,所以讲区块链技术一般就讲比特币和以太坊。比特币中的密码学原理 1…...
PyTorch学习笔记:data.WeightedRandomSampler——数据权重概率采样
PyTorch学习笔记:data.WeightedRandomSampler——数据权重概率采样 torch.utils.data.WeightedRandomSampler(weights, num_samples, replacementTrue, generatorNone)功能:按给定的权重(概率)[p0,p1,…,pn−1][p_0,p_1,\dots,p_{n-1}][p0,p1,…,pn…...
SpringMVC对请求参数的处理
如何获取SpringMVC中请求中的信息 ? 默认情况下,可以直接在方法的参数中填写跟请求参数一样的名称,此时会默认接受参 数 ,如果有值,直接赋值,如果没有,那么直接给空值 。Controller RequestMapp…...

12年老外贸的经验分享
回想这12年的经历,很庆幸自己的三观一直是正确的,就是买家第一不管什么原因,只要你想退货,我都可以接受退款。不能退给上级供应商,我就自己留着,就是为了避免因为这个拒收而失去买家。不管是什么质量原因&a…...

电子电路中的各种接地(接地保护与GND)
前言多年以前,雷雨天气下,建筑会遭遇雷击,从而破坏建筑以及伤害建筑内的人,为了避免雷击的伤害,人们发明了避雷针,并将避雷针接地线,从而引导雷击产生的电流经过地线流入到地下。地线࿱…...
php实现农历公历日期的相互转换
农历(Lunar calendar)和公历(Gregorian calendar)是两种不同的日历系统。公历是基于太阳和地球的运动来计算时间的,而农历是基于月亮的运动来计算时间的。农历中的月份是根据月亮的相对位置来确定的,而公历…...

基于SpringBoot的房屋租赁管理系统的设计与实现
基于SpringBoot的房屋租赁管理系统的设计与实现 1 绪论 1.1 课题来源 随着社会的不断发展以及大家生活水平的提高,越来越多的年轻人选择在大城市发展。在大城市发展就意味着要在外面有一处安身的地方。在租房的过程中,大家也面临着各种各样的问题&…...

一文带你为PySide6编译MySQL插件驱动
1.概述 最近使用PySide6开发程序,涉及与MySQL的数据交互。但是qt官方自pyqt5.12(记不太清了)以后不再提供MySQL的插件驱动,只能自己根据qt的源码编译。不过网上大部分都是qt5的MySQL驱动的编译教程。后来搜到了一个qt6的编译教程…...

图论算法:树上倍增法解决LCA问题
文章目录树上倍增法: LCA问题树上倍增法: LCA问题 树上倍增法用于求解LCA问题是一种非常有效的方法。 倍增是什么? 简单来说,倍增就是 1 2 4 8 16 … 2^k 可以发现倍增是呈 2的指数型递增的一类数据,和二分一样&…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...