【C语言】长篇详解,字符系列篇2-----受长度限制的字符串函数,字符串函数的使用和模拟实现【图文详解】

本文主要是介绍【C语言】长篇详解,字符系列篇2-----受长度限制的字符串函数,字符串函数的使用和模拟实现【图文详解】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎来CILMY23的博客喔,本期系列为【【C语言】长篇详解,字符系列篇2-----“混杂”的字符串函数,字符串函数的使用和模拟实现【图文详解】,图文讲解各种字符串函数,带大家更深刻理解C语言中各种字符串函数的应用,感谢观看,支持的可以给个赞哇。

前言

上一篇说到,在C语言中,我们常常碰见各种字符,也需要对字符进行处理,那C语言提供了一系列的库函数,来帮助我们处理各种情况。字符函数有字符串函数,字符分类函数,还有字符转换函数……本期我们将深入了解各种字符串函数(strcpy,strcat,strcmp,strncpy,strncat)

目录

 一、strcat函数

二、strcmp函数

三、strncpy函数

四、strncat函数

五、strncmp函数


一、strcat函数

 该函数可以在cplusplus网站查询到,strcat - C++ Reference (cplusplus.com)

 函数原型如下:

char * strcat ( char * destination, const char * source );

函数介绍如下: 

 返回值和使用案例:

 

先简单了解一下strcat函数吧,strcat函数它的功能是Concatenate strings,意思是连接字符串。concatenate它的意思如下

了解完这个功能后,我们大致也清楚了,strcat的作用就是拼接字符串啦,那函数的使用如下:

#include<stdio.h>
#include<string.h>int main()
{char str1[50] = "hello ";char str2[] = "CILMY23";strcat(str1, str2);printf("%s ", str1);return 0;
}

我们可以把第二个字符串拼接到第一个字符串末尾,这样就concatenate起来了。 

结果如下:

总结:

1.strcat的功能是拼接字符串,目标空间要有'\0',并且源字符串要有'\0'。

2.strcat的使用需要包括头文件string.h

3.strcat的返回地址是destnation的地址

4.目标空间要足够大,并且可以修改

   strcat的模拟实现 

我们看以下这段最简单粗暴的代码,思路是比较直接的,先遍历所需要追加的字符串空间,找到'\0'的位置,然后从'\0'的位置开始用新的字符串覆盖,最后添加'\0'就行。 

char* my_strcat(char * dest, const char* src)
{assert(dest);assert(src);char* ret = dest;while (*dest != '\0'){dest++;}while (*src != '\0'){*dest = *src;dest++;src++;}*dest = '\0';return ret;
}

 逻辑图如下所示:

代码还可以进行优化,那如何优化呢?实际上我们可以发现,后面一段有点类似于把str2给它复制到str1当中,这不就是我们字符篇1学到的strcpy嘛,(不懂可以跳转连接http://t.csdnimg.cn/CvvpI) 

所以第二步的优化就可以写成这样

char* my_strcat(char * dest, const char* src)
{assert(dest && src);char* ret = dest;while (*dest != '\0'){dest++;}strcpy(dest, src);return ret;
}0

二、strcmp函数

该函数可以在cplusplus查找到:strcmp - C++ Reference (cplusplus.com)

函数原型如下:

int strcmp ( const char * str1, const char * str2 );

 函数介绍如下:

函数返回值和使用案例:

简单了解一下strcmp函数吧,它的功能是Compare two strings,Compares the C string str1 to the C string str2.,比较两个字符串,它的返回值是如果是第一个字符串小于第二个字符串就返回一个小于0的值,如果第一个字符串和第二个字符串相等就返回0,如果第一个字符串大于第二个字符串,就返回一个大于0的值。

strcmp的使用:

#include<stdio.h>
#include<string.h>int main()
{char str1[] = "hello ";char str2[] = "CILMY23";int ret = strcmp(str1, str2);printf("%d ", ret);return 0;
}

 解析:因为h是在ASCII码比C大的,所以返回了1

 总结:

1.strcmp实际是按照两个字符串对应位置一个个进行比较的,而且是按照字典序(ASCII码值)比较的

2.strcmp的使用需要包括头文件string.h

3.返回值:

◦    第⼀个字符串大于第二个字符串,则返回大于0的数字
◦    第⼀个字符串等于第二个字符串,则返回0
◦    第⼀个字符串小于第二个字符串,则返回小于0的数字

strcmp的模拟实现

字符串相对比的三种情况,相等,大于,和小于,如果字符串两个相对比是相等的话,那指针就需要往后走,它们结束的标志是‘\0’,如果走到了这个‘\0’,那说明两个字符串是相等的,出了循环后,那说明二者不相等,就进行判断,根据判断后写返回值。

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;elsereturn -1;
}

 当然后面的返回值也可以用指针解引用后相减得到的值,不固定,主要是灵活使用,

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

这是当str1和str2相等的情况下:注意图片中红色的是字符数组,而黑色的str1和str2是指针。 

当二者不相等的时候: 

 

就会马上比对出结果。

我写的几个测试用例也给大家放这了:

int main()
{char str1[] = "CILMY23";char str2[] = "CILMY23";char str3[] = "";char str4[] = "helllo ";int ret = my_strcmp(str1, str2);printf("%d \n", ret);ret = my_strcmp(str3, str2);printf("%d \n", ret);ret = my_strcmp(str4, str2);printf("%d \n", ret);ret = my_strcmp(str3, str4);printf("%d \n", ret);return 0;
}

三、strncpy函数

如果讲完以上三个函数相信大家对其都有个大致的了解了,那以上三个(strcpy,strcat,strcmp)都是长度不受限制的字符串函数,它们只会一股脑的走到尾巴,我想要只复制几个字符,链接几个字符,比较几个字符,这时候库函数就给我们提供了三个加n的字符串函数,它们分别是strncpy,strncat,strncmp函数,有了这三个函数,我们就可以指定几个字符来进行相对应的操作。 它们都在相对于的原型基础上,增加了一个形参size_t num。

首先我们先来认识一下strncpy这个函数,strncpy - C++ Reference (cplusplus.com)

函数原型如下:

char * strncpy ( char * destination, const char * source, size_t num );

函数介绍如下: 

  函数返回值和使用案例如下:

 函数的使用呢,重点还是如果字符串不够怎么办?

#include<stdio.h>
#include<string.h>int main()
{char str1[] = "CILMY23";char str2[50];strncpy(str2, str1, 9);printf("%s ", str2);return 0;
}

 我们知道九个复制是远超过str1的数量的,那内存里复制了什么过去呢?

通过下图我们可以看到在23后面放的是'\0',所以如果num超过源字符串之后,就会不停的拷贝'\0',直到复制结束。

总结:

•    拷贝num个字符从源字符串到目标空间。
•    如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。 

strncpy的模拟实现

char* my_strncpy(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);while (*dest++ = *src++){if (num == 1){*dest = '\0';break;}num--;}while (num > 1){*dest++ = '\0';num--;}return ret;
}

 上述代码是我第一种思路,根据原先代码改造的,其实跟原来差不多,只是这里多了个num操作,因为我的循环它会先赋值,后判断,所以在我已经把C赋值给str2空间的时候,num还是3,I赋值给完str2的时候,num--后才是2,我L又复制完了,num--后1了,这个时候我已经操作三次赋值了,但是num并不为0,所以此刻等于1的时候要将0赋值进去,然后跳出循环再进行赋值‘\0’操作。

我的第二种思路就是通过判断num,num如果为0就结束了。因为源字符串的结束标志是'\0',那不是'\0',那我就是在复制'\0'之前的字符。那我就先赋值,把src的内容复制进去,因为复制进去后,dest和src都指向下一个位置了,这时候我把*dest直接用‘\0’覆盖,如果num--后为0,这个时候我就刚好只拷贝一个字符,那如果num是大于源字符串函数的,那么在复制完源字符串后,*src就停留在‘\0’ 了,这时候只要不断给dest添加'\0'就完事了。

char* my_strncpy(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);while (num--){if (*src != '\0'){*dest++ = *src++;}*dest = '\0';}return ret;
}

测试部分:这里我是把原先的Cplusplus网站中的案例扣过来用了结果是一样的

int main()
{char str1[] = "To be or not to be";char str2[40];char str3[40];/* copy to sized buffer (overflow safe): */my_strncpy(str2, str1, sizeof(str2));/* partial copy (only 5 chars): */my_strncpy(str3, str2, 5);str3[5] = '\0';   /* null character manually added */puts(str1);puts(str2);puts(str3);return 0;
}

 我的逻辑可能会比较复杂,如果你有其他的方法欢迎在评论区探讨。

四、strncat函数

函数原型如下:strncat - C++ Reference (cplusplus.com)

char * strncat ( char * destination, const char * source, size_t num );

函数介绍如下:

 函数返回值和使用案例如下:

 strncat的模拟实现

首先我仍然按照之前strncpy的第二种思路进行实现,我们需要先找到需要拼接的dest的尾巴'\0',然后从'\0'开始拼接。拼接的数量还是由num来决定。

char* my_strncat(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);//找尾while (*dest != '\0'){dest++;}while (num--){if (*src != '\0'){*dest++ = *src++;}*dest = '\0';}return ret;
}

 测试用例以及结果如下:

int main()
{char str1[20];char str2[20];strcpy(str1, "To be ");strcpy(str2, "or not to be");my_strncat(str1, str2, 6);puts(str1);return 0;
}

 五、strncmp函数

 strncmp:strncmp - C++ Reference (cplusplus.com)

函数原型如下:

int strncmp ( const char * str1, const char * str2, size_t num );

函数介绍如下:

函数返回值和使用案例如下: 

 strncmp的模拟实现

int my_strncmp(const char* str1, const char* str2, size_t num)
{assert(str1 && str2);while (num--){if(*str1 == *str2){if (*str1 == '\0')return 0;str1++;str2++;}elsereturn *str1 - *str2;}
}

该思路来自之前写过的,我们只需要将不等于的返回即可 

感谢各位同伴的支持,本期字符函数篇2就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。  

这篇关于【C语言】长篇详解,字符系列篇2-----受长度限制的字符串函数,字符串函数的使用和模拟实现【图文详解】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/727577

相关文章

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连