欢迎来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就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。