字符串函数能有什么坏心思?
🚀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的指数型递增的一类数据,和二分一样&…...

Java线程池中submit() 和 execute()方法有什么区别
点个关注,必回关 文章目录一. execute和submit的区别与联系1、测试代码的整体框架如下:2、首先研究Future<?> submit(Runnable task)和void execute(Runnable command),3、submit(Runnable task, T result) 方法可以使submit执行完Run…...

Vue.extend和VueComponent的关系源码解析
目录 0.概念解释 前言 需求分析 Vue.extend 编程式的使用组件 源码分析 0.概念解释 Vue.extend和VueComponent是Vuejs框架中创建组件的两种不同方式。Vue.extend方法能够让你根据Vue对象(继承)来定义一个新的可重用的组件构造器。而VueComponent方…...

【动态规划】01背包问题(滚动数组 + 手画图解)
01背包除了可以用形象的二维动态数组表示外,还可以使用空间复杂度更低的一维滚动数组。 目录 文章目录 前言 一、滚动数组的基本理解 二、确定dp及其下标含义 三、确定递推公式 四、确定初始化 五、确定遍历顺序 1.用物品(正序)遍历背…...

javaEE 初阶 — 超时重传机制
文章目录超时重传机制1. 数据重复传输问题2. 如何解决数据重复传输问题3. 重传次数问题TCP 的工作机制:确认应答机制 超时重传机制 如果传输数据的时候丢包了该怎么办? 利用 超时重传,也就是超过了一定的时间,如果还没响应就重新…...

小米5x wlan无法打开解决
诱因:想要利用空置设备做节点服务器或者边缘计算,因此解锁并刷了magisk,印象中在刷之前wlan已经无法打开无法进行wifi联网 表现: 1 WLAN开关无法打开,或者虚假打开,无法扫描wifi 2 设置->我的设备->全…...

负载均衡之最小活跃数算法
文章目录[toc]一、概念二、场景与设计思路三、实现四、代码下载一、概念 活跃数 集群中各实例未处理的请求数。 最小活跃数 集群中各个实例,哪个实例未处理的请求数据最小,就称之为最小活跃数。 二、场景与设计思路 场景 以获取微服务地址为场景。 设计…...

JavaScript 评测代码运行速度的几种方法
一、使用 performance.now() API 在 JavaScript 中,可以使用 performance.now() API 来评测代码的运行速度。该 API 返回当前页面的高精度时间戳,您可以在代码执行前后调用它来计算代码执行所需的时间。 例如: let t0 performance.now();…...

Linux 编译器 gcc/g++
本文已收录至《Linux知识与编程》专栏! 作者:ARMCSKGT 演示环境:CentOS 7 目录 前言 正文 gcc/g常用命令 自定义可执行程序名命令-o 预处理指令-E 编译指令-S 汇编指令-c 链接指令gcc 命令巧记口诀 链接库 动态库-动态链接 静态库…...

2.Java基础【Java面试第三季】
2.Java基础【Java面试第三季】前言推荐2.Java基础01_字符串常量Java内部加载-上58同城的java字符串常量池面试code讲解intern()方法---源码解释02_字符串常量Java内部加载-下whyOpenJDK8底层源码说明递推步骤总结考查点03_闲聊力扣算法第一题字节跳动两数求和题目说明面试题解法…...

Java高级-多线程
本篇讲解java多线程 基本概念: 程序、进程、线程 **程序(program)**是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程…...