失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > c语言判断字符串str1中含有字符串str2(是否为子串问题)

c语言判断字符串str1中含有字符串str2(是否为子串问题)

时间:2023-05-13 00:45:00

相关推荐

c语言判断字符串str1中含有字符串str2(是否为子串问题)

目录

一、可以用三种方式解决子串问题:函数strstr、指针、子串出现的首个位置。

二、使用函数strstr判断str1中是否包含str2

三、利用指针来判断是否为子串

四、不用函数和指针,返回子串在母串中出现的首位置

一、可以用三种方式解决子串问题:函数strstr、指针、子串出现的首个位置。

先举几个例子来说明一下什么样的字符串可以称作子串(区分大小写,假设字符串数组长度为20):

令str1[20]="dou LUO da lu";

1.str2[20]="da l";是子串;

2.str2[20]="dal";不是子串;

3.str2[20]="LUO";是子串;

4.str2[20]="Luo";不是子串;

5.str2[20]="dou da";不是子串。

二、使用函数strstr判断str1中是否包含str2

1.strstr函数在库函数"string.h"中,它的使用方法是strstr(str1,str2),函数得到的是地址,并不是数据内容,所以要用指针变量来接收;

2.如果判断str2是子串,就会返回str1中首次出现str2加上其后的内容,否则返回null;

举个例子:str1[20]="dou LUO da lu"; str2[20]="da l";那么strstr(str1,str2)返回的内容是"da lu";

3.运行代码和结果(codeblocks和手机程序C Compiler可运行)

#include<stdio.h>#include<string.h>void main(){char str1[20],str2[20];char *str;//设置指针变量来存储子串在母串中的地址printf("请输入被查找字符串str1:");scanf("%s",str1);printf("要查找的字符串str2:");scanf("%s",str2);str=strstr(str1,str2);if(str)//判断str是否为空,不能写成str!=null{printf("str2是子串:%s\n",str);}else{printf("str2不是子串:%s\n",str);}}

注意代码中进行比较的两个字符串是运行程序后手动输入的,用的scanf函数获取,所以字符串得是连续的,若有空格则会自动将前两个字符串分别赋值给str1和str2,至于第二个空格及以后有多少内容都不管,看结果就知道了:

所以可以把原代码中的scanf函数改成:

printf("请分别输入字符串str1和str2,用空格隔开:");scanf("%s%s",str1,str2);

运行结果:

4.如果不用输入的方式,直接在程序中给定两个字符串的话,可以有多个空格,代码如下:

#include<stdio.h>#include<string.h>int main(){char str1[20]="dou LUO da lu";char str2[20]=" LUO d";//注意必须写成数组型,一定要带下标[N]!!char *str;str=strstr(str1,str2);printf("根据结果自行判断:%s\n",str);}

关于strstr函数的详细定义可以参看/cprogramming/c-function-strstr.html

三、利用指针来判断是否为子串

1.基本思路:利用指针p依次遍历str1,每遍历一位字符便将之与str2的首地址值*q进行比较,如果相同则两个指针同时自增,然后依次向后比较,若不同则指针p往下移动一位,再与str2的首地址值*q进行比较,循环往复,直到str2遍历完(即确定str2为子串),或者str1遍历完。

①外层循环:for(p=str1;*p;p++)意思是从首地址开始,只要*p不等于'0',则执行内嵌语句块,然后自增;

②内层循环:for(q=str2;*p==*q&&*q;p++,q++); 意思是从首地址开始,判断两个字符串的值是否相等且str2是否遍历完,因为for语句后面有分号,表示它没有内嵌语句,所以若判断为真则执行第三表达式,判断为假则退出内层循环,执行外循中内嵌的其他语句,然后再执行外层循环,接着再从头开始执行内层循环。

关于for循环的详细用法可参看/cpp/html/45.html

2.指针初始化与赋值需要注意,在c语言里没有总体处理一个字符串的机制。例如:

①char *p="asdfgh"; 初始化,指针p指向字符串首地址

②char *p; p="asdfgh"; 赋值,指针p指向字符串首地址

③char a[10],*p; p=a; 赋值,数组的变量名a表示该数组的首地址

④int a=1; int b[10]; int *p=&a; int *q=b; int *w=&b[0];这些指针初始化都是正确的

总的来说,指针p指向地址,而*p指向数据,详细了解指针可参看/mfrbuaa/p/3756342.html

3.代码及运行情况:

#include<stdio.h>int main(){char str1[20]="sadadadf";char str2[20]="adf";char *p=str1,*q=str2;//指针初始化,赋以首地址int flag=0;//设置一个变量来判断是否为子串for(p=str1;*p;p++)//将str1的首地址赋给p;第二个表达式判断字符是否为‘0’;{for(q=str2;*p==*q&&*q;p++,q++);//注意这里有分号!!这个for语句没有内嵌代码if(!*q)//如果str2遍历完,此时*q的值一定是默认值‘0’,那么!*q为真{flag=1;break;//得到想要的答案之后就跳出循环}}if(flag==1) printf("是");else puts("否");//判断后执行紧邻第一句,可以不加大括号{},puts()和printf()都可以输出}

啰嗦几句:最开始用while语句写的代码,发现运行结果不对,调试之后还是for循环好用点,但这个程序还是有个小问题,如果str1="sadadf"; str2="adf"; 运行结果显示“否”,不正确,若str2="df",运行结果为“是”,是对的,那是因为内层循环比较到str1[3]和str2[2]时,前者是‘a’,后者是‘f’,这时候内存循环结束,外层循环执行第三表达式p++,这时候*p='d',再执行内层循环也得不到想要的结果了,我就想着是不是可以再增加一个内层循环,可是呢,对于现在这两个字符串来说,结果是对了,可是如果str1="sadadadf";结果又会出错,还是跟之前一样的问题,嗯~一般情况下还是好使的,不过下面这种不用函数和指针的方法更好,没有这些问题!

四、不用函数和指针,返回子串在母串中出现的首位置

1.用getchar()来获取一个个字符,依次存入数组当中;

getchar()的具体用法可参见/cprogramming/c-function-getchar.html

2.用while循环将获得的字符依次存入数组中:while((c=getchar())!='\n') a[num++]=c;

①如果获得的字符不是回车符,就存入数组a中,包括空格。注意while循环后没有大括号{}或分号;时,则紧邻的第一句为其循环体;

②num=0;则(num++)=0,num=1,所以是从a[0]开始存,存到最后一个字符a[num-1],循环结束。

3.进行判断,如果是子串,返回并输出子串在母串中出现的首位置,否则什么都不返回。(同while一样,若for和if后面没有分号和大括号,则紧跟的第一句为其循环体)

首先,外层循环先依次判断母串元素a[i]与要查找串的首位值b[0]是否相等,如果相等则进行下一步循环与比较,内循表达式如下:

if(a[i]==b[0]){for(j=1;j<lb;j++)if(a[i+j]!=b[j])break;if(j==lb){printf("%d\n",i+1);}}

因为前面已经判断了a[i]与b[0]相等,所以将数组下标分别下移一位,再比较,每比较一次就判断是否相等,如果相等,下标下移并比较;如果不相等则退出内层循环,判断j与lb是否相等(此时肯定不相等的,只是遵从顺序执行规则,要判断一次),再回到if(a[i]==b[0])语句,此时a的下标已经变成了i+j,即i=i+j,将这一位与b的首位再比较,若相等则循环比较,若不相等则退回到外层循环。

如果比较之后确定为子串,那么子串一定遍历完,此时jj与lb一定相等。

4.代码及运行情况:

#include<stdio.h>#include<string.h>int main(){int i,j,la,lb,num=0;char c,a[120],b[100];printf("请输入母串:");while((c=getchar())!='\n')//while循环后没有大括号{}或分号;时,则紧邻的第一句为其循环体a[num++]=c;//用数组a存储被查找字符串num=0;//num一定要重新赋值为0,否则数组b的值就不是从首地址开始printf("输入要查找的字符串:");while((c=getchar())!='\n')b[num++]=c;//用数组b存储要查找的字符串la=strlen(a);lb=strlen(b);for(i=0;(la-i)>=lb;i++)//如果遍历到i还没行,将剩下的串长与要查找的串长相比,若还大,接着循环,若小,就不用再比较了{if(a[i]==b[0]){for(j=1;j<lb;j++)if(a[i+j]!=b[j])//for后面没有分号和大括号,所以紧跟的第一句为其循环体break;//if后面没有分号和大括号,所以紧跟的第一句为其循环体if(j==lb){printf("子串出现的首位置是母串第%d位\n",i+1);break;}}}}

文中三种思路来源于文章/fakine/article/details/7517417/

写在最后:每次代码看懂了,复制能够运行,然后自己码一遍,结果运行没问题,但就是结果出了问题,前前后后仔细对比,就是不知道哪里错了,感觉都是对的啊,每次到最后找到问题所在时,基本上都是咪咪小问题被忽略了,就造成了大问题,比如多个或少个分号啊空格,或者数据类型搞的不对、少个简单但很关键的语句等,好的习惯需要更多训练。

如果觉得《c语言判断字符串str1中含有字符串str2(是否为子串问题)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。