【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

相关文章

Redis中6种缓存更新策略详解

《Redis中6种缓存更新策略详解》Redis作为一款高性能的内存数据库,已经成为缓存层的首选解决方案,然而,使用缓存时最大的挑战在于保证缓存数据与底层数据源的一致性,本文将介绍Redis中6种缓存更... 目录引言策略一:Cache-Aside(旁路缓存)策略工作原理代码示例优缺点分析适用场景策略二:Re

Flutter实现文字镂空效果的详细步骤

《Flutter实现文字镂空效果的详细步骤》:本文主要介绍如何使用Flutter实现文字镂空效果,包括创建基础应用结构、实现自定义绘制器、构建UI界面以及实现颜色选择按钮等步骤,并详细解析了混合模... 目录引言实现原理开始实现步骤1:创建基础应用结构步骤2:创建主屏幕步骤3:实现自定义绘制器步骤4:构建U

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

在.NET平台使用C#为PDF添加各种类型的表单域的方法

《在.NET平台使用C#为PDF添加各种类型的表单域的方法》在日常办公系统开发中,涉及PDF处理相关的开发时,生成可填写的PDF表单是一种常见需求,与静态PDF不同,带有**表单域的文档支持用户直接在... 目录引言使用 PdfTextBoxField 添加文本输入域使用 PdfComboBoxField

Git可视化管理工具(SourceTree)使用操作大全经典

《Git可视化管理工具(SourceTree)使用操作大全经典》本文详细介绍了SourceTree作为Git可视化管理工具的常用操作,包括连接远程仓库、添加SSH密钥、克隆仓库、设置默认项目目录、代码... 目录前言:连接Gitee or github,获取代码:在SourceTree中添加SSH密钥:Cl

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Windows系统宽带限制如何解除?

《Windows系统宽带限制如何解除?》有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文就跟大家一起来看看Windows系统解除网络限制的操作方法吧... 有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文

MySQL数据库约束深入详解

《MySQL数据库约束深入详解》:本文主要介绍MySQL数据库约束,在MySQL数据库中,约束是用来限制进入表中的数据类型的一种技术,通过使用约束,可以确保数据的准确性、完整性和可靠性,需要的朋友... 目录一、数据库约束的概念二、约束类型三、NOT NULL 非空约束四、DEFAULT 默认值约束五、UN