zl程序教程

您现在的位置是:首页 >  其他

当前栏目

字符串常见函数介绍及模拟实现

2023-02-25 18:21:49 时间

作者的话

本文介绍字符串常用的函数如何使用及其模拟实现~


strlen介绍

原型:unsigned strlen(const char * str)

用法: 从str开始向后遍历,遇到第一个'\0'后停止,返回从str到此的字符数量,不包含'\0'。

注意事项:

  • 因返回值是unsigned int型,如果将两个strlen的返回值相减,不会得到负数,因此通过正负判断两个字符串哪个更长时,往往会出现BUG。 如果您不知道为何如此:整型在内存中的存储详解
  • strlen模拟实现: 法一:循环

代码详解: 创建一个变量,每遍历一个字符便让这个变量自增1即可。

法二:递归

代码详解: 将字符串一点一点蚕食,剩下'\0'时返回0即可。

法三:指针-指针

代码详解: 指针减去指针所得结果是两个指针之间的元素个数(不是字节个数)。 如果您不知为何如此:指针类型详解

效果图: 返回字符串的长度,仅仅是一个数,在此不在展示。


strcpy介绍

原型:char strcpy(char target,const char * source)

用法: 将source的字符串拷贝到target的字符串,包括最后的'\0'。

注意事项:

  • target的空间必须足够大,不然会导致'\0'在target数组之外。
  • target不能是const和char*修饰的常量字符串,因为target需要被修改。
  • strcpy模拟实现:

代码详解: 遍历,依次覆盖即可。

效果图:


strcat介绍

原型:char strcat(char target,const char * source)

用法: 将从source开始到'\0'结束的字符串接到target的'\0'后面(该'\0'也被替换)。

注意事项:

  • target需要有足够大的空间容纳。
  • target不能是char*和const修饰的常量字符串,因为target需要被修改。
  • strcat模拟实现:

一:普通实现

代码详解: 先找到target的末尾,随后挨个拼接即可,不要为了'\0'哦。

效果图:

二:创新实现,自己拼接自己

代码详解: 利用strlen找到该字符串的末尾,随后拼接即可,注意此时字符串末尾的'\0'已被替换成字符串的第一个字符,所以,末尾的'\0'需要额外赋值。undefined

strcmp介绍

原型:int strcmp(const char str1,const char str2)

用法: 将两个字符串从前至后判断,按照ASCII值大小判断,大的被判定为大,有一个字符不同即返回;str1大则返回正数,str2大则返回负数,完全相同则返回0。

注意事项:

  • 在VS中正数返回1,负数返回-1。
  • 因编译器不同,返回值可能也不同,因此,若用strcmp的返回值判断,最好用大于号或小于号,不要直接用1或-1或0。
  • strcmp模拟实现:

代码详解: 只要str1和str2相同就一直循环,直到二者不同,判断后决定返回什么;若是循环结束,则返回0。strncpy介绍

原型:char strncpy(char target,const char * source,unsigned int n)

用法: 将source开始的n个字符拷贝到target开头的n个字符里。

注意事项:

  • 若n的数值大于source的长度,则多出来的,默认为'\0',也因此会改变target字符串的结束位置。
  • strncpy模拟实现:

代码详解: 和strcpy没什么分别,只需要注意循环n次即可。

效果图:


strncat介绍

原型:char strncat(char target,const char * source,unsigned n)

用法: 将source的n个字符,拼接到target的末尾后面。

注意事项:

  • 若n大于source的长度,则多出来的默认接入'\0',也因此会改变target的结束位置。
  • strncat模拟实现:

代码详解: 和strcat相同,只需注意循环n次即可。

效果图:


strncmp介绍

原型:int strncmp(const char str1,const char str2,unsigend n)

用法: 对str1和str2的前n个进行比较,按照ASCII值大小。较大的为判断为大;若str1大,则返回正数,若str2大,则返回负数,完全相同默认0。

注意事项:

  • VS中正数默认1,负数默认-1。
  • 不同编译器有所不同,因此不要直接用1或-1判断。
  • strncmp模拟实现:

代码详解: 和strncmp相同,只是判断前n个,随后的是否相同与此无关。

效果图:


strstr介绍

原型:char strstr(const char arr1, const char * arr2)

用法: 在arr1里面寻找第一个出现的arr2,返回第一次出现的首元素地址。

注意事项:

  • 若arr2长度大于arr1的,则返回null。
  • 若arr2长度大于arr1的,用strcmp或不做任何处理都可以。
  • 作为一个程序员,你应该避免上面两种。
  • strstr模拟实现:

代码详解: 先排除特殊情况,先从arr1遍历,找到arr2的第一个字符,然后利用遍历i,不对arr1和arr2自身进行修改,从而判断是否相等; 最需要注意的是arr1和arr2的遍历同时结束,需要额外判断。undefined

strchr介绍

原型:char strchr(const char str,char c)

用法: 找到str中第一次出现c的位置,返回地址。

  • strchr模拟实现:

代码详解: 从str遍历即可,遇到c就返回地址。undefined

strrchr介绍

原型:char strrchr(const char str,char c)

用法: 返回str中最后一次出现c的位置。

  • strrchr模拟实现:

代码详解: 哈哈,从后往前遍历即可。undefined

memcpy介绍

原型:void memcpy(void target,const void * source,unsigned n)

用法: 将source开始的n个字节,挨个,以字节为单位,拷贝到target里面。

注意事项:

  • 参数类型是void,内部会强制转换成char,因此是以字节为单位拷贝。
  • 自己拷贝自己时,可能会有字节重叠的现象,这时可以用memmove。
  • memmove在VS中是memcpy的上位替代,可以完美替换memcpy,但不同编译器有所不同。
  • memcpy模拟实现:

代码详解: 创建两个char*的指针,挨字节遍历即可。undefined

memmove介绍

原型:void memcpy(void target,const void * source,unsigned n)

用法: memcpy的升级版,可以避免自己拷贝自己时的字节重叠现象。

注意事项:

  • 在VS中memmove是memcpy的上位替代。
  • 但是在VS的标准库中,memcpy一键改的和memmove相同了。
  • 但是如果程序需要你字节重叠,还需要自己写。
  • mommove模拟实现:

代码详解: 判断了target和source谁在前,谁在后,分两种情况实现代码,避免了重叠问题。undefined

memcmp介绍

原型:int memcmp(const void data1, const void data2,unsigned n)

用法: 以字节为单位,挨个比较,data1较大则返回正数,data2较大返回负数,完全相同返回0.

  • memcmp模拟实现:

代码详解: 创建两个char*指针,挨个字节遍历,遇到不同的字节则返回。undefined

memset介绍

原型:void memset(void arr,int c,unsigned n)

用法: 将arr的前n个字节,每个字节设置成c。

  • memset模拟实现:

代码详解: 挨个遍历,赋值即可。undefined

strtok介绍

原型:char strtok(const char str1,const char * str2)

用法: 以arr2的每个字符为标识,将arr1的字符串隔开,返回隔开后的字符段首元素地址;首次调用按函数原型说明传参即可,后续调用须在第一个参数传递NULL,第n次调用返回切割后的第n个字符串首元素地址,详细请看效果图。

  • 因涉及静态区,在此不再展示代码实现。

效果图: