上一期,我讲解了关于字符串函数中,受限制的字符串函数,有想了解的小伙伴们可以点此链接去看看:C语言字符串函数(2)受限制的字符串函数
那么今天,我来讲一讲标题中这两个函数的作用和使用方法。
目录
一.strstr函数
注:Find a substring.意为:在字符串中寻找子字符串
1.函数基本原理:
strstr函数 用于判断字符串strCharSet是否是string的子串。如果是,则该函数返回strCharSet在string中首次出现的地址;否则,返回NULL。
const char* string:被查找目标字符串
const char* strCharSet:要查找的对象字符串
2.接下来,我来展示函数在代码中的使用方法:
int main() {
char a1[] = "www.httpschinasystem.com";
char a2[] = "china";
char* tmp=strstr(a1, a2);
if (tmp == NULL) {
printf("此字符串不存在,未能查找成功!\n");
}
else {
printf("%s\n", tmp);
}
return 0;
}
通过创建两个字符串,a1为被查找的字符串,a2为要进行查找的字符串,使用strstr函数,将数据传给指针进行打印。
注:只要子串存在,函数不仅打印出子串a2的内容,还会打印出子串a2在a1所处位置往后的所有字符 。
以上代码呈现的是函数一次就能在a1中找到a2的情况,属于简单情况;
接下来,我会为大家展现函数需要多次才能在a1中找到a2的复杂情况:
char a3[] = "abbbcdef";
char a4[] = "bbc";
char* ret = strstr(a3, a4);
if (ret == NULL) {
printf("此字符串不存在,未能查找成功!\n");
}
else {
printf("%s\n", ret);//bbcdef
}
strstr函数对于复杂情况处理过程:
通过代码可知,a4的字符串为:"bbc",a3的字符串为:"abbbcdef",当函数首先利用指针string指向a3的首字符时,发现字符a不等于strCharSet指针指向a4字符串的字符b,string会指向下一个字符进行寻找,string指向了字符b,发现与strCharSet指向的吻合,然后两个指针同时进行对比,对比成功继续向后对比,在string和strCharSet第三次进行对比时,发现不相等,寻找失败。
strCharSet指针重新指向a4的首地址,等待string再一次与它指向字符相等;而string会指向刚才字符b的下一个字符,重新开始寻找配对字符,发现配对成功,string与strCharSet再一次开始对比,经过三次的对比都成功,查找成功,查找成功的理由就是strCharSet指针顺利指向'\0'字符,系统会把该子串a4在a3的首位置及以后的所有字符作为返回值传给ret,结束函数执行操作。
以下为查找失败代码:
char a5[] = "abbbcdef";
char a6[] = "bbd";
char* ecp = strstr(a5, a6);//NULL
if (ecp == NULL) {
printf("此字符串不存在,未能查找成功!\n");
}
else {
printf("%s\n", ecp);
}
表明指向字符串的两指针从始至终都没有真正完整的配对成功过,直到指针string遍历完a5数组中的字符串,然后指向’\0'结束查找,以失败告终。 函数的返回值置为NULL!
3.模拟实现strstr函数
char* my_Strstr(const char* str1, const char* str2) {
assert(str1 && str2);
const char* s1 = str1;
const char* s2 = str2;
char* p = str1;
while (*p != '\0') {
s1 = p;
s2 = str2;
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) {
s1++;
s2++;
}
if (*s2 == '\0')
return p;
p++;
}
return NULL;
}
模拟实现的原理与我刚在讲解多次寻找情况中所说的一样,需要考虑三种情况:
当两指针开始只要有任何一方,或者双方都指向'\0'(NULL)空字符时,直接会停止寻找,查找失败,返回NULL。
第二种是被查找的字符串中,string遍历完所有字符都没能找到与之相等的子字符串,则查找失败,返回NULL.
最后一种:直到strCharSet指针顺利指向子字符串的'\0'位置,才会被判断为查找成功,该函数返回strCharSet在string中首次出现的地址。
二.strtok字符串切割函数
Find the next token in a string.: 在字符串中查找下一个标记。
1.定义:
函数是将字符串strToken通过分割符分解为多组组字符串。
char*strToken:是一长串字符串
char* strDelimit:字符串中的分隔符,字符分割符能够自己设定,可以是任何符号、记号,也可以是字符 。
2.函数标准规定:
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容,并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。!!!
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
3.函数代码使用
int main() {
char arr[] = "www.http://zhangsan@chnk.com";//字符串
char arr2[] = { ". : // @" };//分隔符数组
char* ret=strtok(arr, arr2);
printf("%s\n", ret);
ret = strtok(NULL, arr2);
printf("%s\n", ret);
ret = strtok(NULL, arr2);
printf("%s\n", ret);
ret = strtok(NULL, arr2);
printf("%s\n", ret);
ret = strtok(NULL, arr2);
printf("%s\n", ret);
如上图:arr是要被分割的字符串数组,arr2是分割符数组,函数会通过分隔符的位置将字符串切割成多个字符串。每次切割时遇到分割符就结束切割,每一次切割完等到下一次切割开始都会在上一个保存的位置开始向后操作,直到最后指针遇到;'\0'字符完成切割操作。
我将该函数调用5次后才将切割后的所有字符串 全部打印出来,除了第一次调用函数是将arr1放进去,剩下的四次都是放入NULL,原因就是下面规定所要求:
问题1:大家可能会问若是多打印了一次或者多次,会发生什么?结果如下:
多打印后的结果也是输出两次null空字符串,并不会对程序造成越界访问,报错。
问题2:若是字符串有很长很长很长,到底要打印几遍?造成代码冗余怎么办?
这是关键所在,程序员在设计的时候已经想到了这种情况,针对此,需要我们使用for循环遍历:
nt main() {
char arr[] = "www.http://zhangsanli@bite.com//efhba.cabjke:sqf@1578621";//字符串
char arr2[] = { ". : // @" };//分隔符数组
//若字符串数组是很长的话,无法算出到底应该输出几次才能输完,所以要用到for循环
char* ret = NULL;
for (ret = strtok(arr, arr2); ret != NULL; ret = strtok(NULL, arr2)) {
printf("%s\n", ret);
}
return 0;
}
在循环中,ret!=NULL是限制条件,若是下一次拷贝到的是空字符串,就表明字符串已经到了最后了,停止循环。
初始条件就是第一次得到strtok的返回字符串,每次循环完之后,便会执行下一次的strtok。
好了,对于strstr字符串查找子串函数、strtok字符串切割函数的讲解就到这里,大家觉得有用的话,记得点个一键三连!