前言:
语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。
字符串常量 适用于那些对它不做修改的字符串函数.
(一)strlen函数
这是我们对strlen的基本认识
1.字符串是以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
2.参数指向的字符串必须要以 '\0' 结束
计算值是15(随机值),因为数组里面没有\0,直到找到\0才会停止。
3.注意函数的返回值为size_t,是无符号的(重点!)
通过上图计算等于3-6=-3,应该输出<=对吧?实则不然!
因为strlen函数的返回值是无符号类型 size_t 就是无符号整形数据。
4.strlen的模拟实现
有三种模拟实现方式:1.计数器 2.递归实现 3.指针-指针
计数器模拟实现strlen函数
递归模拟实现strlen函数
递归的不同处是:不用创建临时变量统计字符串长度。
如果*str不等于空指针,就返回1+字符串下一个字符(str+1);如果等于'\0'就返回0。
指针-指针模拟实现strlen函数
(二)strcpy函数
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
strcpy模拟实现函数
也能直接这样打印。
(三)strcat函数
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
通过调试我们可以清晰看见,在追加arr1字符串数组的时候,是从\0处开始追加的。
那我们怎么知道arr2字符串数组后面的\0有没有拷贝过来呢?
通过调试我们发现,arr2字符串数组在追加的时候把自己的\0也拷贝了过来。
所以我们发现了如果要把一个字符串数组追加到另一个字符串数组,两个字符串数组后面都得以\0结束。
strcat模拟实现函数
那么字符串自己给自己追加,会如何呢?
当给自己追加的时候,自己给自己追加的时候 \0被覆盖 源头也没\0 相当于字符数组 找到\0才停止 所以会乱码 相当于随机值。
(四)strcmp函数
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
strcmp模拟实现函数
if return 1 or else return -1是否有点啰嗦了?我们可以这样修改
那么我们可不可以这样写?
不可以!因为只有在VS编译器才会返回1或者-1,换个编译器结果就会不同!
VS编译器比较聪明,会提示我们arr2数组内容存放不下,但如果不提示,是不是就是个坑?而且有时候就算程序崩溃也会给你非法完成任务拷贝过去。
所以C语言引入了长度受限制的字符串函数
(五)strncpy函数
与strcpy的不同之处就是有了一个size_t num。相当于拷贝个数。
我们可以调试看一下,拷贝的到底是不是3个?
果然这个函数很听话,说拷贝几个就拷贝几个,是个君子!
那么如果拷贝的个数大于源头的数据会怎么样呢?
我们也可以调试观察一下
当拷贝个数大于源头个数,\0会充当备胎一直填满目的地的字符串内容。
(六)strncat函数
这个追加的是 它是追加完自动补充\0还是原有的\0,但我们不清楚,所以我们可以测试一下。
当追加完我们给予的追加个数,它会自动在后面填充\0。
如果追加的个数大于追加数组的个数呢?
通过调试我们可以发现,它不会动第八个字符的内容,还是一样会用\0自动填充。
(七)strncmp函数
因为d比\0的ASCII码值大,所以返回1。
b比qASCII码值小,所以返回-1。
(八)strstr函数
如果arr2在arr1中多次出现,那么返回第一次出现的位置
strstr模拟实现函数
我们用画图解析一下。
当我们用*cp记录两个字符串数组开始相等的起始位置,为了保证cp不变改变,用s1=cp,如果s1==s2 那么就s1++,s2++。当s2等于\0时就返回cp就即可,这样又记录了相等的起始位置cp,又没有改变cp的位置,又遍历了s1和s2字符串数组,如果找不到就返回空指针NULL。*s1&&*s2是为了判断两个字符串数组是不是\0,如果有一方为\0就为假 不执行直接返回空指针NULL或者返回cp。