给助教班里小朋友看的字符串

给小朋友看的字符串

现在假设你是我助教班上的小朋友,预设你知道最基本的字符串相关知识,在这里强调一些非常重要的字符串相关知识,并试图简单引入一下指针,让你明白strstr应该怎么用。

两种输入方式

char a[10];
gets(a);
scanf("%s",a);

gets:

读一整行,不可能读一行的一半,把行末回车从缓冲区里取出,变成\0放到最后。
输入一行(既然都说输入了,行末肯定有回车)

hey you!

缓冲区里进来了九个字符:

`h` `e` `y` `空格` `y` `o` `u` `!` `\n`

a这个字符串变成了:

{`h`,`e`,`y`,`空格`,`y`,`o`,`u`,`!`,`\0`}

然后缓冲区里什么也没有了。

scanf:

不一定读一整行,遇到空白符(如空格)就停了。
输入一行(既然都说输入了,行末肯定有回车)

hey you!

缓冲区里进来了九个字符:

`h` `e` `y` `空格` `y` `o` `u` `!` `\n`

a这个字符串变成了:

{`h`,`e`,`y`,'\0'}

然后缓冲区里剩:

`空格` `y` `o` `u` `!` `\n`

这时候如果后面还有scanf("%s",b);或者gets(b)等试图读一个字符串的语句,便不会等用户输入,直接从缓冲区里剩的字符里拿。

scanf %s会忽略前导空白符,遇到空白符就停

但gets不会,有啥要啥,一整行除了回车全是它的

在这里插入图片描述
在这里插入图片描述

应用

在这里插入图片描述
为什么hint让我们用gets(a)读入?
因为如果用scanf("%s",a)的话,long long只能读进去long
剩下的空格long回车还留在缓冲区里,干扰下一次输入。

顺带一提,输入2和5以后要怎么来着?
是不是要getchar?
如果不getchar,gets(a)就把缓冲区里的回车吃掉了。

多组输入

如果用scanf

while(scanf("%s",a)!=EOF)
{
	//balabala
}

如果用gets

while(gets(a)!=NULL)
{
	//balabala
}

重大误区

char a[20];
a="hello";

错!

char a[20];
char b[10]="hhh";
a=b;

错!
字符串不可以直接赋值哦。

char a[20]="hello";
if(a=="hello")
{
	puts("ok");
}

错!字符串不可以用== > <来比较。

那怎么办

引入string库

#include<string.h>

用里面的库函数。

下面放一些不需要懂指针也可以明白的函数!
strlen
strcpy
strcmp
strcat
memset

#include<stdio.h>
#include<string.h>
/*-----------搞懂string.h-------------*/
int main()
{
	/*---strlen是字符串的长度---*/ 
	char a[100]="hhh";
	int c=strlen(a);
	printf("%d\n",c);//输出3 
	
	
	/*---strcpy(a,b)是把b的值给了a---*/ 
	strcpy(a,"hello");
	puts(a);//输出hello 
	char b[100]="world";
	strcpy(a,b);
	puts(a);//输出world 
	
	
	
	/*---strcmp(a,b)是比较字符串---*/ 
	/*---strcmp(a,b)<0  字典里a在b前面---*/ 
	/*---strcmp(a,b)>0  字典里a在b后面---*/ 
	/*---strcmp(a,b)==0  a和b一模一样---*/ 
	if(strcmp("hello","world")<0)
		puts("ok");
	if(strcmp(b,"world")==0) 
		puts("ok");
	if(strcmp("car ","car")>0)
		puts("ok");
	//输出了三个ok 
		
		
		
	/*---strcat(a,b)是把b的值接到了a后面---*/ 
	strcpy(a,"toyama") ;
	strcpy(b,"kasumi");
	strcat(a,"_");//a是"toyama_" 
	strcat(a,b);
	puts(a);//输出toyama_kasumi 
	
	
	
	/*---memset(a,0,sizeof(a))是把数组元素很快地都设成0---*/ 
	/*---memset(a,-1,sizeof(a))是把数组元素很快地都设成-1---*/  
	int d[3]={1,2,3};
	memset(d,0,sizeof(d));
	for(int i=0;i<3;i++)
		printf("%d ",d[i]);//输出0 0 0 
	putchar('\n'); 
	
 } 

虽然strstr函数需要懂指针才能彻底了解,不过它有点好用,所以我粗略介绍一下,听不懂就不要听了!快乐备考最重要。

还记得函数那一节讲的返回值吗?

int max(int a,int b)
{
	if(a>b) return a;
	return b;
}

int max里面的int,就代表着这个函数return的是一个int类型的变量。

double ave(int sum,int n)
{
	return 1.0*sum/n;
}

double ave里面的double,就代表着这个函数return的是一个double类型的变量。

如果我们在网上查一下strstr函数的原型,网上会这么告诉我们:

	char* strstr(const char* haystack, const char* needle)
	{
	//balabala
	}

char *虽然很像char,但是char *char是两种数据类型,char *是指向一个char类型数据的指针类型变量。正如int *是指向一个int类型数据的指针类型变量。double *是指向一个double类型数据的指针类型变量。

如果我们用了一句

char a[10]="toyama";
strstr(a,"yam");

这一句strstr的值现在是个指针,char*类型,指向“yam”在"toyama"中第一次出现的位置,也就是这儿。

在这里插入图片描述
对,没错,指针就是个箭头,指向某个数据,在这里就是指向我们的a[2]。

顺带一提,我们定义数组的时候,数组名可以看做指向第一个字符的指针。当我们char a[10];的时候,a的类型,可以说是char [10],也可以说是char *。如果把a当成指针的话,它指向哪儿呢?指向它的头头,也就是a[0]。

在这里插入图片描述
你可能会问,指针有什么用,我不会输入指针,也不会输出指针,也没有题让我求指针。
但是指针的差有用啊,能解决大问题。
一个字符串中,两个指针(箭头)的距离是几,两个指针(箭头)的差就是几->一个常数。

那么来看题,C6的字符串匹配。
请添加图片描述
这题可以这么做。

#include<stdio.h>
#include<string.h>
int main() {
	char a[120],b[120];
	gets(a);
	gets(b);
	if(strstr(a,b)!=NULL) {//如果strstr找不到就返回NULL,跟EOF差不多
		printf("YES %d",strstr(a,b)-a);
	}
	else printf("NO");
	return 0;
	
}

如果我们输入akizukiizu,那么strstr(a,b)a两个指针分别指向这里:
请添加图片描述
这两个指针中间差2(指针a往右挪两位,就到指针strstr(a,b)那里了)。
也就是“izu”在“akizuki”中最早出现的位置是第二位。(从第零位开始算)

再开拓思维一下,如果题目让你输出字符串A里,字符串B第一次出现及以后的所有字符,也就是让我们输出“izuki”的话,怎么办呢。
直接

printf("%s",strstr(a,b));

就行。
还记得上面说的吗,数组本质就是指针,这句话只是在输出一个字符串罢了。
就跟下面的这句话原理一样。

printf("%s",a);

a是一个从a[0]开始到a[6]结束的数组,那strstr(a,b)也是一个从a[2]开始到a[6]结束的,长度为5的数组呀,他们都是指针,指向哪儿,就从哪儿开始,到’\0’结束。

再开拓思维一下,如果题目让你输出字符串A里,字符串B第一次出现以后的所有字符,不包括字符串B,也就是让我们输出“ki”的话,怎么办呢。
直接

printf("%s",strstr(a,b)+strlen(b));

就行。
还记得上面说的吗,指针上面可以加减常数,相当于把指针向右(左)挪动几位。

再开拓思维一下,如果题目让你输出字符串A里,字符串B第一次出现及以前的所有字符,也就是让我们输出“akizu”的话,怎么办呢。
直接

a[strstr(a,b)-a+strlen(b)]='\0';
printf("%s",a);

看起来有点复杂,不过只是把a[5]从’k’变成了‘\0’哦,因为字符串输出到\0为止,也是刚刚说过的问题。

请添加图片描述
这是包学姐和贠学长当年E6的题。
你当然可以用暴力法,一位一位对着来解决这道问题,你也可以用strstr的各种妙用,更方便并且不容易出错。
这是strstr法的标程。

#include <stdio.h>
int main()
{
 char a[20],b[20];
 char *p;
 int len;
 gets(a);
 gets(b);
 len = strlen(b);
 p = a;//让指针p和指针a一开始指的一样
 while((p = strstr(p, b))!=NULL){//如果还能找到子串
 printf("%d-%d\n",p-a, p-a+len-1);
 p += len;//指针p往右挪子串那么长
 }
 return 0; 
}

PS.这些开拓思维如果觉得听起来比较困难就不要管了!暴力循环永远滴神!

PPS.你说指针是箭头吧,那肯定不准确,这么说只是为了让小朋友在期中考试之前速成理解strstr怎么用罢了,等真正学指针了,别信我说的话。

PPPS.字符串很重要,跟排序和查找一样。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值