目录

一、可以用三种方式解决子串问题:函数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函数的详细定义可以参看https://www.runoob.com/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循环的详细用法可参看http://c.biancheng.net/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指向数据,详细了解指针可参看https://www.cnblogs.com/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()的具体用法可参见https://www.runoob.com/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;}}}}

文中三种思路来源于文章https://blog.csdn.net/fakine/article/details/7517417/

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

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

  1. 写一函数,实现删除字符串str1中含有的字符串str2.

    删除str2在str1中第一次出现的部分 #include <stdio.h> #include <stdlib.h> #include <string.h> ch ...

  2. python判断列表中含有_Python:判断列表中含有字符串且组成新的列表打印输出-Dotest董浩...

    ''' 题一:判断列表中含有字符串且组成新的列表打印输出 知识点:列表.列表的增删改查.for循环.if判断 ''' #@Author:Dotest软件测试 #@QQ:1274057839 names ...

  3. R语言str_flatten函数通过自定义字符连接(concatenate)字符串向量中的字符串

    R语言str_flatten函数通过自定义字符连接(concatenate)字符串向量中的字符串 目录 R语言st

  4. java返回字符数组_JAVA语言实现随机返回字符串数组中的字符串

    本文主要向大家介绍了JAVA语言实现随机返回字符串数组中的字符串,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. //随机返回字符串数组中的字符串 public static Stri ...

  5. C语言:从键盘中输入字符串,追加填写到指定文件中

    /*从键盘中输入字符串,追加填写到指定文件中*/ #include <stdio.h> #include <string.h> #include <ctype.h> ...

  6. python中定义字符串_python中的字符串

    python中的字符串一旦定义,则不可以修改 python中的原始字符串 即 在字符串前面加小写字母r 比如:打印输出C:\Program Files\Microsoft Games python中的 ...

  7. python中格式化字符串_Python中所有字符串格式化的指南

    python中格式化字符串 Strings are one of the most essential and used datatypes in programming. It allows the ...

  8. python中定义字符串_Python中的字符串String

    Python中除了数字(Numbers)(int,float,complex)之外,另外一种重要的类型就是字符串. 字符串是字符序列,可以由任何字符构成. 在Python语言中,字符串可以放在单引号( ...

  9. java中截取部分字符串_JAVA中截取字符串substring用法详解

    substring public String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串.该子字符串始于指定索引处的字符,一直到此字符串末尾. ...

  10. java list 对象 json字符串_Java中Json字符串直接转换为对象的方法(包括多层List集合)...

    使用到的类:net.sf.json.JSONObject 使用JSON时,除了要导入JSON网站上面下载的json-lib-2.2-jdk15.jar包之外,还必须有其它几个依赖包:commons-b ...

最新文章

  1. 数据结构与算法:15 树
  2. python赋值语句格式_Python中变量和变量赋值的几种形式
  3. Python实现跨文件全局变量的方法
  4. 数组元素倒置-Java
  5. 《移动App测试的22条军规》—App测试综合案例分析23.4节测试微信App的手势操作...
  6. mysql 代码结构_MySQL代码执行结构
  7. 转载自(梦想天空)【必备】史上最全的浏览器 CSS JS Hack 手册
  8. IplImage中的widthStep大小计算及原理
  9. JAVA课程设计——拼图小游戏
  10. Oracle数据库以及客户端下载资源
  11. centos 7 使用certbot解决域名证书续签最佳实践
  12. 你认为,做期货是基本面更有效还是技术面更有效?
  13. 什么是手机证书和签名干什么用的
  14. 树莓派3B--HC-05蓝牙无线模块设置
  15. 腾讯区块链2022秋招面试题(一面)
  16. Fastboot的使用简单教程
  17. 自动驾驶层次测试体系(单元测试/集成测试/SIL/HIL/VIL/RIL/LABCAR/实车等)
  18. 公链分析报告(6)--Zcash
  19. RAM在单片机里究竟有什么用?
  20. 【就业必备知识】大学毕业如何处理档案和户口,小心变成死档和黑户

热门文章

  1. 如何用WPS表格生成拟合曲线
  2. 802.11 与wifi
  3. java 参考期刊文章_计算机论文java参考文献_期刊[J]_学位论文[D]_专著[M]_(30)
  4. 20春季 7-2 The Judger (25 分)
  5. centos桌面系统怎么退回终端系统_CentOS下命令行和桌面模式的切换方法
  6. 个人陈述 计算机专业,研究生个人陈述范例,计算机专业
  7. 基于主从博弈的智能小区代理商定价策略及电动汽车充电管理
  8. linux查看ip命令
  9. 北美票房:《触不可及》惊喜夺冠
  10. [转]经济学金融学书籍推荐