[C语言]string.h常用字符串库函数详解+模拟实现


目录

字符串函数

strlen

strcpy

strcat

strcmp

strstr

内存函数

memcpy

memmove


人生百态,苦事之多。烦恼穿心,何来解脱?打开博客,吸取干货。

以码消愁,以串解忧。泱泱年轮,唯有生活。一起撸串,快乐几何。

字符串函数

strlen

在C语言中,我们通过字符数组的方式来存储字符串,也可以直接使用常量字符串,如何去判断字符串的长度便是一个问题。比如char ch[100] = "abcdef";  难道长度就是100吗?显然不对,我只有abcdef这六个字母,长度应该为6才对,所谓上天有好生之德,留下了一个库函数strlen可以求得字符串的长度。

#include <stdio.h>
#include <string.h>
int main()
{
    char ch[100] = "abcdef";
    int len = strlen(ch);
    printf("%d\n", len);//结果为6
    len = strlen("abcdef")
    printf("%d\n", len);//结果依然为6
    return 0;
}

strlen使用起来竟如此方便,只需把数组名或常量字符串往里一掷,它便会自己返回字符串长度。

如何模拟实现计算字符串长度?我们需要知道,C语言是如何打印字符串的。

char ch[] = "abcdef";
printf("%s\n", "abcdef");
printf("%s\n", ch);

放一个字符串以%s打印显然没问题,但是放一个数组名用%s打印也没问题,而数组名是什么?数组名是数组首元素地址(除开sizeof和&的特殊情况)那是否常量字符串也是首元素地址

printf("%p\n", "abcdef");

由此可以得知,其实C语言打印字符串是根据它的首元素地址一直往下找,找到一个打印一个,那么何时停止?根据我们扎实的C语言基础知识,我们都知道字符串以\0结尾,所以找到\0的时候便不用再打印了

知道了原理,接下来就是模拟实现了。既然字符串是根据地址找的,我们就传入首地址,既然是以\0结尾的,我们就把\0之前的字符全部统计一遍,这样就能得到字符串长度了。

int my_strlen(const char* str)//因为只需要统计个数 不需要改变字符 所以用const
{
    assert(str); //防止传NULL指针 引用头文件assert.h进行断言
    int len = 0;
    while(*str != '\0')
    {
        str++;
        len++;
    }
    return len;
}

strcpy

strcpy函数用于把一个字符串拷贝到另一个字符串中。但要在使用的时候注意一些事项:

1. 目标空间必须足够大   2. 源空间必须存在\0   3.目标空间必须可以更改

char ch[100];//目标空间可更改 且足够大
char cpy[] = "abcdef";//源空间存在\0
strcpy(ch, cpy);//将cpy的内容拷贝到ch中
printf("%s\n", ch);

既然我们知道字符串以\0结尾,那我们只需要知道他们两个字符串的首元素地址,然后到被拷贝字符串的\0为止全部拷贝进去即可。

模拟实现:

char* my_strcpy(char* dest, const char* src)
{
    assert(dest && src);//断言
    char* ret = dest;//用于返回给用户拷贝完后的地址 方便用户操作
    while(*dest++ = *src++);//当src不为\0时拷贝到dest中 并后移一位
    return ret;
}

strcat

strcat(str1, str2);会把str2的内容追加到str1后面。​但也有一些注意事项:

1.目标空间必须足够大   2.目标空间必须存在\0   3.源空间必须存在\0  4.目标空间必须可更改

char ch1[100] = "I love";//目标空间足够大且存在\0且可更改
char ch2[] = " You";//源空间存在\0
strcat(ch1, ch2);
printf("%s\n", ch1);

模拟实现:(找到目标空间\0之后和strcpy实现方式类似)

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while(*dest)
	{
		dest++;
	}
	while(*dest++ = *src++);
	return ret;
}

strcmp

当我们需要比较两个字符串是否一致时,许多小白都会直接用 == 进行比较,但我们之前提到过,字符串本质上是首元素地址, ==进行比较时比较的也是首元素的地址,所以答案会与我们的期待的不符,实际上C语言有一个库函数strcmp可以比较两个字符串,相等返回0,不相等时返回值根据第一个不等的字符词典序进行返回(大于返回>0 小于返回<0) 如: a 和 b   显然 词典序中a<b则返回一个<0的数。

char ch1[] = "abc";
char ch2[] = "abc";
char che3[] = "abd";
int flag1 = strcmp(ch1, ch2);//0
int flag2 = strcmp(ch1, ch3);//<0

模拟实现:从头开始比较,相等继续比较,不等根据词典序返回,比到\0返回0

int my_strcmp(const char* str1, const char* str2)
{
	while(*str1 == *str2 && *str1 && *str2)
	{
		if(*str1 == '\0')
			return 0;
		str1++,str2++;
	}
	return *str1 - *str2;
}

strstr

strstr的作用是在一个字符串中查找子串并返回地址。

char ch[] = "I love you";
char* low = strstr(ch, "love");//在ch中查找 love  找到返回love的首地址 找不到返回NULL
printf("%s\n", low);//love you

模拟实现:既然是找子串,那么主串没找完且长度大于子串的情况下都得继续找,所以为了方便我们就多创建一个指针指向当前主串要找的起始位置,然后循环比较。

char* my_strstr(const char* str1, const char* str2)
{
	char* s1 = str1;
	char* s2 = str2;
	char* cp = str1;
	while(*cp)
	{
		s1 = cp;
		s2 = str2;
		while(*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if(*s2 == '\0')
			return cp;
		cp++;
	}
	return NULL;
}

内存函数

既然干货都发出来了,何不再来了解了解string.h中的内存函数?

memcpy

内存函数的优点就在于可以自己指定字节数,且兼容所有的指针类型。

int a = 4;
inb b;
memcpy(&b, &a, 4);//把a地址开始到后面4个字节复制给b(a为整型 4个字节 即把a复制给b)

实现:我们需要知道要兼容所有的地址类型,我们需要void*指针 由于又是按字节复制 所以我们将void*使用时强制类型转换为char*即可。

void* my_memcpy(void* dest, const void* src, int size)
{
    assert(dest && src);
    void* ret = dest;
    while(size--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;//不用++的原因是 void*指针直接++只有在某些编译器上才可以
        src = (char*)src + 1;
    }
    return ret;
}

memmove

memmove相比memcpy啥的可厉害太多了,memcpy如果自己复制给自己就有可能因为重叠覆盖而出错,而memmove就修复了这一点。

memmove是如何弥补这一点的?比如 12345  你要复制45 到34的位置 如果我们先复制5 那么就会把4覆盖 复制4的时候就会出现问题, 但我们先复制4便可以解决。所以memmove可以根据你复制的目标位置和源位置作比较得到的结果,来判断先复制左端还是右端,避免重叠空间被覆盖。

用法与memcpy一致 所以不再演示。

模拟实现:

void* memmove(void* dest, const void* src, int size)
{
    assert(dest && src);
    void* ret = dest;
    if(dest <= src || (char*)dest >= (char*)src + size)//即没有重叠空间或目标空间在左方时
    {
        while(size--)
        {
            *(char*)dest = *(char*)src;
            dest = *(char*)dest + 1;
            src = *(char*) + 1;
        }
    }
    else//当重叠时 dest在右方时
    {
        dest = *(char*)dest + size;
        src = *(char*)src + size;
        while(size--)
        {
            *(char*)dest = *(char*)src;
            dest = *(char*)dest - 1;
            src = *(char*) - 1;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

〖Python网络爬虫实战⑩〗- 正则表达式实战(一)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付费…

2023 年男生还推荐报计算机专业吗?

计算机专业确实是一个非常热门的专业&#xff0c;就业前景也很广阔。 但是&#xff0c;近些年随着各个大学对计算机专业及其相关专业疯狂扩招&#xff0c;而且每年的毕业人口都在增多&#xff0c;行业是根本容纳不下的&#xff0c;就业竞争力度也急剧上升。因此&#xff0c;选…

Mac平台上有哪些好用的常用软件?

我大概分几类给你介绍一下吧。 一、办公类 1.微软的office系列&#xff0c;在mac平台也有office的全家桶&#xff0c;习惯用微软office的也可以安装。 2.wps office&#xff0c;wps可以说是国产最好用的office软件&#xff0c;最重要的是wps可以跨平台&#xff0c;并且云文档…

IT审计黄金标准“CISA”备考经验分享-529分成功上岸

激动的心&#xff0c;先晒下成绩单 考证建议以及职业规划 对于IT人士来说证书是一个非常有效的敲门砖&#xff0c;尤其是想跨到新的领域&#xff0c;一个证书往往能给自己在面试官留下一个深刻的印象&#xff0c;尤其是一些在专业领域含金量很高的证书。作为一个14年的IT人士&…

81-82-83-84-85-86 - 文件系统设计与实现

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;深入浅出操作系统 - 目录 文章目录1. 问题1.1 硬盘上最最最简单的文件系统支持方式1.2 改进思路1.3 更多细节问题1.4 文件系统概要设计1.5 硬盘数据逻辑示意图1.6 硬盘数据物理组…

​2023年十大目标检测模型!

“目标检测是计算机视觉中最令人兴奋和具有挑战性的问题之一&#xff0c;深度学习已经成为解决该问题的强大工具。”—Dr. Liang-Chieh Chen目标检测是计算机视觉中的基础任务&#xff0c;它涉及在图像中识别和定位目标。深度学习已经革新了目标检测&#xff0c;使得在图像和视…

微服务架构-服务网关(Gateway)-路由功能详解

路由功能详解 这一节我们看一看Gateway中的路由是怎么工作的&#xff1b;GateWay网关的路由功能可不是简简单单的 “转发" 请求&#xff0c;在请求到达网关要流转到指定服务之间发生了很多事儿&#xff0c;它不光可以拒绝请求&#xff0c;甚至可以"篡改” 请求的参数…

Java 在线编程编译工具上线,直接运行Java代码

前言 大家好&#xff0c;我是小哈~ 周末没出去浪&#xff0c;花了点时间&#xff0c;在我的个人网站上线了一款小工具。啥工具呢&#xff1f;一款可以在线编译 Java 代码并运行输出结果的小工具。 大家都知道&#xff0c;甲骨文刷 Java 版本号非常积极&#xff0c;这不上个月…

web综合

一&#xff0c;基于域名访问www.openlab.com 在文件当中写入IP与域名的映射关系 在windows中写入 也可以在客户端的/etc/hosts下写入映射关系 创建目录 [rootserver ~]# mkdir -pv /www/openlab 将所需要的内容写入对应目录当中 [rootserver ~]# echo welcome to openlab ! &…

大一被忽悠进了培训班

大家好&#xff0c;我是帅地。 最近我的知识星球开始营业&#xff0c;不少大一大二的小伙伴也是纷纷加入了星球&#xff0c;并且咨询的问题也是五花八门&#xff0c;反正就是&#xff0c;各种迷茫&#xff0c;其中有一个学弟&#xff0c;才大一&#xff0c;就报考培训班&#…

2023/4/6总结

题解 Problem - A - Codeforces 1.这道题很简单&#xff0c;找出将当前数字放入字符串的最大值。 2.分情况讨论&#xff0c;有俩种情况&#xff0c;一种是大于等于数字d&#xff0c;那么这个数字d需要插入到最后字符串的位置。否则这个数字需要插入到第一次比它小的位置。 …

2023年4月的编程语言排行榜,有你中意的开发语言吗?

编程世界变幻莫测&#xff0c;编程语言也是层出不穷&#xff0c;每隔一段时间就有新的风口出现。2023年的风口非人工智能莫属&#xff0c;人工智能领域中不可获取的编程语言就是Python&#xff0c;作为在算法、数据方面有独特优势的编程语言&#xff0c;从去年开始就展现了它不…

算法学习|动态规划 LeetCode 392.判断子序列 、115.不同的子序列

动态规划一、判断子序列思路实现代码二、不同的子序列思路实现代码(还是蛮开心的&#xff09; 一、判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相…

腾讯云8核16G18M轻量服务器CPU带宽流量性能测评

腾讯云轻量应用服务器8核16G18M带宽&#xff0c;18M公网带宽下载速度峰值可达2304KB/秒&#xff0c;相当于2.25M/s&#xff0c;系统盘为270GB SSD盘&#xff0c;3500GB月流量&#xff0c;折合每天116GB流量。腾讯云百科分享腾讯云轻量服务器8核16G18M配置、CPU型号、公网带宽月…

【Pytorch】搭建网络模型的实战

【Pytorch】搭建网络模型的实战CIFAR10 model structure搭建网络使用Sequential进行搭建网络模型使用tensorboard查看网络结构对CIFAR10数据集进行分类&#xff0c;根据图片内容识别这是哪一类 CIFAR10 model structure 输入input:3通道的32 x 32 图片卷积操作的通道数不变 那…

应用信息资源管理(张士玉、董焱)——第一章 总论

第一章 总论 1.1 信息社会 1.1.1 信息社会的形成 信息社会是指以信息技术为基础&#xff0c;信息产业为支撑&#xff0c;信息化为主要特征的社会形态。其形成经历了以下几个阶段&#xff1a; 信息化初期&#xff1a;20世纪60年代至70年代&#xff0c;电子计算机的出现和发展…

人工智能会取代人工翻译吗?

当今社会正处于语言和技术高速发展的阶段&#xff0c;因此语言和技术的碰撞是不可避免的——甚至有些人说这种碰撞已经发生了&#xff0c;我们只是在等待尘埃落定。数字化、物联网、人工智能和机器学习&#xff0c;以及更进一步——智能手机、语音识别&#xff0c;以及互联网和…

机器视觉检测技术在工业零部件的应用

众所周知&#xff0c;在工业生产中&#xff0c;传统的检测技术需要大量的检测工作者&#xff0c;不仅影响生产效率&#xff0c;而且带来不可靠的因素。 视觉检测技术克服了传统检测技术的缺点&#xff0c;确保了检测的安全性。 可靠性和自动化程度高&#xff0c;已成为当前检测…

第六章 信息资源安全管理

信息资源安全管理内涵 信息在开发利用过程中面临的问题&#xff1a; 可用性&#xff1b;合法用户对信息的使用不会被不正当拒绝保密性也称机密性&#xff1b;保证机密信息不被窃取&#xff0c;或窃取者不能了解信息的真实含义认证性也称真实性&#xff1b;对信息的来源进行判断…

zabbix创建自定义监控模板

目录 第一章先行配置zabbix 第二章配置自定义 2.1.案列&#xff1a;自定义监控客户端服务器登录的人数需求&#xff1a;限制登录人数不超过 3 个&#xff0c;超过 3 个就发出报警信息 2.2.在 Web 页面创建自定义监控项模板 2.3.zabbix 自动发现与自动注册 总结 自定义监控…