2021 6-6
- strstr 在一个字符串中找另一个字符串
- strtok 切割字符串函数(kmp算法也可以实现)
- strerror 返回错误码转换为所对应的错误信息,需写printf来打印
- perror 打印错误信息(包含自定义信息),自身可以打印,不需要printf
strstr- -在一个字符串中找另一个字符串
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bbc";
char* ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("没找到\n");
}
else
{
printf("找到了:%s\n", ret);
}
return 0;
}
- 在arr1中查找是否包含arr2数组
- 输出找到了 且输出bbcdef,从找到以后的那个字符开始往后输出
模拟实现这个函数
- 输出找到了bbcdef
- char* my_strstr(const char* str1, const char* str2)
传的是字符串的首地址,所以参数用char * ;不会改变字符串,只是查找一下在不在用const较安全;要么返回空指针要么返回地址,所以返回类型就是char *
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* s1 = NIULL;
const char* s2 = NULL;
const char* cp = str1;
if (*str2 == '\0')//找的是空指针的时候
{
return (char*)str1;//因为str1是const修饰但是返回的是char *,所以要强制转换为char *
}
while (*cp)//当cp没有指向0的时候
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && (*s1 == *s2))//*s1 和*s2都不为\0且两个相等
{
s1++;
s2++;
}
//假设为字符串abcdef和字符串cde
//当发现两个字符串不相等(在这里是d和\0不相等)且发现第二个字符串是\0说明找到了
if (*s2 == '\0')
{
return (char*)cp;//因为str1是const修饰但是返回的是char *,所以要强制转换为char *
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bbc";
在arr1中查找是否包含arr2数组
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("没找到\n");
}
else
{
printf("找到了:%s\n", ret);
}
return 0;
}
cp++意义
- 当在s1没有找到和s2第一个字符相同的时候,就cp++即s1++指向下一个字符,直到找到
- 当在s1没有找到和s2第一个字符相同情况下,再返回去的时候找到了,此前记录的cp就是一开始匹配成功的字符,当匹配到部分不成功,,s1需要重新指向一开始成功匹配的字符的下一个字符(cp++实现),而cp会指向s1
找字符会出现的两种情况
- 找到第一个字符相同,后面会连续出现相同的字符的情况
- 当s1中没有找到和s2第一个字符匹配的字符的时候,s1++
- 找到相同的时候就s1++和s2++,然后在比较下一个字符
- 找到一部分相同的字符以后,后面出现了不同的字符
- s2的前两个字符本来和s1的bb两个字符是匹配·的,但是第三个字符开始c就和b不匹配了,当字符开始匹配不成功,s1需要重新指向一开始成功匹配(第一个b)的下一个字符(第二个b)开始(用cp来实现),s2需要重新指向到字符串的首地址
- cp指向成功匹配的初始字符,s2因为直接返回字符串的的首地址,所以不需要cp来帮助
上述算法也可以用KMP - 字符串查找算法实现- -更好- -后续更新
strtok- -切割字符串函数
-
zpw@bitedu.tech
zpw
bitedu
tech -
192.168.3.122
192
168
3
122
第一个参数指向整个想要分割的字符串(zpw@bitedu.tech)
第二个参数是分隔符集合
(@ .)
int main()
{
char arr[] = "zpw@bitedu.tech hehe";
char* p = "@ . ";
//把字符串保存到tmp中切割
char tmp[30] = { 0 };
strcpy(tmp, arr);
char* ret = NULL;
for (ret = strtok(tmp, p); ret != NULL; ret=strtok(NULL, p))
{
printf("%s\n", ret);
}
// ret = strtok(tmp, p);
// printf("%s\n", ret);
// ret = strtok(NULL, p);
// printf("%s\n", ret);
// ret = strtok(NULL, p);
// printf("%s\n", ret);
return 0;
}
- strtok有记忆下一次切割的位置的功能
strerror- -把错误码转换为错误信息- -需printf来打印
int errno;//5调用库函数失败的是,都会设置错误码,全局的错误码
#include <errno.h>
int main()
{
// printf("%s\n", strerror(0));
// printf("%s\n", strerror(1));
// printf("%s\n", strerror(2));
// printf("%s\n", strerror(3));
// printf("%s\n", strerror(4));
// printf("%s\n", strerror(5));
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
perror- -直接打印错误信息- -不需printf
比streeror更简单,不需要printf来打印,自己就可以打印
int main()
{
//打开文件失败的时候,会返回NULL
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
}