字符串函数能有什么坏心思?

🚀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的指数型递增的一类数据,和二分一样&…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
