一、数组方式来实现
// 手写一个自己的Mystrstr:很有价值。
#include<stdio.h>
char* mystrstr(char* dest, char* src)
{
char* p = NULL; // 使用了可能未初始化的本地指针变量p
int i = 0;
int j = 0;
while (dest[i] != '\0')
{
while (dest[i] == src[j])
{
i++;
j++; // j从0开始,当++后,刚好为strlen值。终止条件。
if (strlen(src) == j)
{
p = &dest[i - strlen(src)];
return p;
}
}
// 如果三位,有两位相同,找第三位,则需将前面所有推翻。
i = i - j;
j = 0;
i++;
}
return p;
}
// 每个循环都需要回到当前字符,内循环会把字符往后放很多,需要在外循环回归。
int main06()
{
//char* p = strstr("all hello world, bllo allo a", "llo");
//printf("%s\n", p);
//char* p1 = mystrstr(" hello world , llo allo", "llo");
char* p1 = mystrstr(" hell,", "llo");
//char* p1 = mystrstr("all ol hello world, bllo allo a", "llo");
//char* p1 = mystrstr(" all ol hellllo world, bllo allo a ", "llo");
printf("%s\n", p1);
system("pause");
return 0;
}
二、采用指针的方式实现
# include<stdio.h>
char* mystrstr01(char* dest, char* src)
{
// 不用计数器了,简单明了。
char* p = NULL;
char* tmp = src;
while (*dest) // 或者while(*dest != '\0')
{
p = dest; // 因为返回的是dest中满足条件的起始位置,所以,先把p放在dest上。
while (*dest == *tmp) // 解引用,内容相同。
{
//printf("*tmp = %c, *dest = %c\n", *tmp, *dest);
tmp++;
if (!*tmp) // 或者if(*tmp == '\0')
{
return p; // 此时的p在内循环起始位置。如果满足条件,返回的刚好为起始位置。
}
dest++;
}
// 没有这步,则不对。因为从循环中出来,会直接跳到下一个字符。
// 需要从上次不符合的下一个字符开始。
dest = p; // dest重新回到外循环的起始位置,等待下一步递增。
tmp = src; // 指向src的重新回到起点。// 回拨到起点。
//printf("dest = %c\n", *dest);
printf("%s\n", src); // src没有变化。用tmp变量保护了。
dest++; // dest重新加一,继续比对。
}
return NULL;
}
// 每个循环都需要回到当前字符,内循环会把字符往后放很多,需要在外循环回归。
int main07()
{
char* p = strstr("all hello world, bllo allo a", "llo");
//printf("%s\n", p);
//char* p1 = mystrstr01(" hello world , llo allo", "llo");
//char* p1 = mystrstr01(" hell,", "llo");
//char* p1 = mystrstr01("all ol hello world, bllo allo a", "llo");
char* p1 = mystrstr01(" all ol hellllo world, bllo allo a ", "llo");
printf("%s\n", p1);
system("pause");
return 0;
}
理清思路很重要。
从结构上看其实就是两层循环:内循环和外循环。
- 外循环就是从dest每个char开始,依次建立子string,
- 然后内循环中与src比对。
- 如果满足进内循环,并且输出这个char的位置。
- 不满足移动到下一个char。
因此,每次内外的切换都需要有两次回拨至起点的操作。
- 内循环如果不满足,需要重新回到dest的起始位置,然后加1。开启下一波循环。
- 此时遍历src,也需要回到src的起始位置,等待下一波循环。
输入的src和dest就是起点。
输出为dest中子字符串的起点,因此可以将输出p直接置于dest上。
p = dest;
此时的p既可以直接作为输出,又可以记录每次外循环开始时的位置。
所以在回拨dest时,可以反过来,让dest = p.
dest = p;
在指针中:temp相当于记录src的起始位置,每次外循环temp都要回到src的起点位置。
所以每次内循环temp = src