在刷题过程中 经常会见到一些操作字符串的函数
当我们掌握使用这些函数并且了解这些函数的实现原理 做起题来就可以得心应手啦
strlen函数每读取一个字符串 就会计数+1 读取到'\0'就会停止 并且'\0'不会计入 |
字符串函数的头文件 都是 string.h 后面就不在说啦
如果我们想要求某一个字符串函数的使用 那么strlen很容易就可以帮我们实现
模拟实现strlen函数 有三种方法 |
既然不能创建临时变量 那么我们想到利用递归的思想 把大事化小 |
那么具体怎么实现呢?
首先进入函数 如果str(也就是第一个元素不为\0) 那么就返回1+my_strlen1(str+1) 也就是把str+1作为参数 进行递归 只要不遇到\0 就会一直递归下去
所以限制条件就是 如果str==’\0’ (这里的str就是每一次传进入的参数) 说明走到了字符串的尽头 这时候返回0就可以了 因为\0不进入字符串长度
(上一篇指针初阶已经介绍了指针-指针)忘了可以去看看~
戳这里
我们知道 指针-指针得到这两个指针之间的元素个数(不是字节个数)所以我们只需要两个指针就可以计算出字符串的长度 |
在函数内部创建一个字符指针 ps 利用while循环使ps指向最后一个元素,最后返回ps-str就可以了
char* strcpy(char * destination, const char * source ); 的作用 是把字符串src拷贝到字符串dest里面 |
不过需要注意的是:
1.需要有程序员检查 目的地字符串必须足够大 确保可以存放源字符串
2.源字符串需要以’\0’结束 否则会造成越界访问导致程序崩溃----因为无\0 就会一直向后找 ,直到找到\0 ,这一过程已经造成了非法访问
3.目标字符串必须可变 否则无法进行修改
4.拷贝过程 实际上会把\0拷贝到目的字符串中
#include
#include
#include
int main()
{
char str1[20] = "abcde";
char str2 = "hello_world";
strcpy(str1, str2);//直接调用函数进行 拷贝
printf("%s\n", str1);
return 0;
}
如图分析
每一次把src源字符串中的对应元素放到目标字符串dest里面
并且每一次赋值之后 src和dest这两个地址都++
这里可以利用后置++ 简化代码 具体看下面代码
注意 由于每一次dest这个地址都在改变 所以开始应该先把目标字符串的地址先拷贝一份
最后返回目标字符串的地址 用于打印
这段代码运行起会直接崩溃,因为char* str1=“quertiop”-----这是一个常量字符串,存储在常量区而不是内存的栈区,是不可以被修改的!!!
而char str1[20]="quertiop"是在栈区开辟了一个数组 里面存放了quertiop这个字符串
这两者的本质是不同滴!
strcmp比较的不是字符串的长度,而是比较字符串对应位置上字符的大小,实际上比较的是字符的ASCII码值。 如果相应位置的字符相同,那么就会比较下一对,直到遇到不同的字符 或者都遇到'\0' |
标准规定:
第一个字符串大于第二个字符串:返回>0的数
第一个字符串等于第二个字符串:返回=0的数
第一个字符串等于第二个字符串:返回<0的数
可以看到 两个字符串中前三个字符都相同 但是第四个字符串 str1中字符小于str2中
所以返回小于0的数
注意:在VS编译器下 默认返回的>0的数是1,<0的数是-1
但是这不意味着在所有的编译器下都是这个值 不同编译器不一样
思路:利用两个指针 分别一一比较对应位置字符大小
如图分析:
对于字符串str1 str2 strcat函数可以把两个字符串拼接起来 对于strcat(str1,str2),实际上是把str2完美无瑕的接到str1的后面 |
首先一个指针找到 str1中的 ‘\0 ‘的位置 然后从str2中的第一个字符开始 依次替换掉包括str1中’\0’ 并从’\0’开始向后的每一个字符 直到str2也到达’\0’才会结束
需要注意的是:
1.源字符串str2必须以’\0’结尾
2.目标空间足够大,能够容纳源字符串的内容
3.目标空间必须可更改
思路:
1.找到目标字符串str1中的’\0’
2.把源字符串str2中的内容拷贝到str1中
(即 相比于strcpy只是多了一个找到’\0’)
如图分析:
注意:要把dest先拷贝一份 用于返回打印字符串
以上只是进行了不同字符串的追截 但是如果是字符串自己给自己追加呢?
我们 模拟实现的strcat对于自己给自己追加 不好实现
这里实现的模拟实现并不能给自己追加 因为源字符串和目标字符串相同 目标字符串中的\0被替换掉了 源字符串中的\0也就没了 所以没有了\0 无法停下来 造成死循环程序崩溃!
如图所示:
strstr(str1,str2)的作用是从str1中查找有没有包含str2的子集
如果有 返回的是第一次出现该子集的时候的地址
如果没有返回空(NULL)
strstr有两个参数 一个是目标字符串str1 一个是待查找的字符串str2
思路是:
1.首先创建两个字符指针s1,s2作为str1和str2的拷贝 --(这是因为 在之后的查找过程中 str1和str2会发生改变)
2.s1指向str1中的第一个字符 s2指向str2中的第二个字符
3.如果*s1==*s2 那么说明此时两个字符串中的第一个字符是相同的,有可能可以找到子集 那么需要对比两个字符串的下一个字符,这时候s1和s2都需要+1来比较下一个字符,(不过如果没找到s1是应该返回 从第一次相同的字符的下一个位置来继续查找,所以需要有一个指针来保存从哪里开始查找的位置)
所以还需要一个指针cur ,当这一次进入比较并没有找到完全相同的字串 那么s1返回到cur
4.如果找到了,那么这时候str2(待查找的子串)应该已经走到了’\0’
返回此时cur(也就是第一次出现字串的首地址)
如图分析:
第一次查找到相同字符的时候 :
第二次查找我就不演示啦,上面的str2中最后一个元素是 ‘\0’ (我没有打上)
第二次是可以找到的 由于s2直接找到 \0 所以直接寻找完毕 返回!
好了 相信你们看明白了
上代码:
// 找到就会返回 第一次出现字串时 首字符地址
// 如果找不到返回NULL
#include
#include
char* my_strstr(const char*str1,const char* str2)
{
assert(str1 && str2);
char* s1 = str1;
char* s2 = str2;
char* cur = s1;
//外层循环 利用cur 检查str1中有无字串
while (*cur)
{
s1 = cur;
s2 = str2;
//内层循环判断 两个位置是否相等
// 判断条件必须还要满足 *s1 和 *s2不为0
// *s1=\0 说明已经找完了 还没找到字串
// *s2=\0 说明 s2可以遍历完 即可以找到字串
while ((*s1 == *s2) && *s1 && *s2)
{
s1++;
s2++;
}
//说明找到了
if (*s2 == '\0')
{
return cur;//返回第一次出现字串的首地址
}
//如果找到 说
//如果跳出循环 说明元素不相等
// 表明此时cur的位置不可找到可以匹配的字串 cur需要++
// 同时s1需要重新回到cur 在上面实现
// s2也需要回到起始位置str2
cur++;
}
// 找不到
if (*cur == '\0')
{
return NULL;
}
}
int main()
{
char str1[] = "abcdqabcdefddd";
char str2[] = "cdef";
printf("%s\n",my_strstr(str1,str2));
return 0;
}
这几个字符串函数就介绍到这,后面还会更新其他字符串函数奥!
❤️❤️❤️