对多组输入while((scanf(“%c“,&ch)!=EOF)的整理和总结

目录

一、引例 - 牛客网OJ题

二、代码

 while((scanf("%c",&ch))!=EOF)

 while(~(scanf("%c",&ch))) 

利用getchar( )去除换行符   

缓冲区

工作原理

scanf("%c\n",&ch)同样可以去除换行符

三、练手-字符逆序

scanf( )正则表达的多组输入

使用gets( )的多组输入 

gets( )函数

四、小结 

常规多组输入:

除去换行符:

读取空格的多组输入:


一、引例 - 牛客网OJ题

为了更好地说明这个问题,我们以一道牛客网的题目作引例。题目链接贴在这里

判断是元音还是辅音_牛客题霸_牛客网KiKi开始学习英文字母,BoBo老师告诉他,有五个字母A(a), E(e), I(i),。题目来自【牛客题霸】icon-default.png?t=N7T8https://www.nowcoder.com/practice/7eb4df4d52c44d309081509cf52ecbc4?tpId=290&tqId=307549&ru=%2Fpractice%2F9cc35bd0754f4feca18e10e57c672467&qru=%2Fta%2Fbeginner-programmers%2Fquestion-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E8%25AF%25AD%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D290

题干如下:

基本思路:

这道题的基本思路很明确,将所有的元音字母作为元素定义一个字符数组arr[5],这时有人会说,不对呀,这不严谨,算上大小写应该是十个呀,为什么是arr[5]。是的,言之有理,不过这个的解决可以在if 语句上做文章,不妨设获取的变量为ch,if ( ch==arr[i] || ch==arr[i]-32),因为在ASCII码中,大小写字母在数值上相差32,这样我们就不必创建另外五个的空间,也会减少循环的长度,既减少时间复杂,又减少空间复杂,何乐而不为呢?

明确此,然后再利用循环,将数组中所有的元素与输入的字符进行比对,如果符合if 语句的条件,打印Vowel,表明该个字母是元音字母,然后break 跳出循环,同时这时,我们要明确i 的值肯定是小于5的。但如果历遍数组没有符合的元素,打印Consonant,表明这个字母是辅音字母。不过,值得注意的是,在打印之前我们需要判断i 的值是否等于5,以避免元音字母跳出循环之后仍然会再次打印。

二、代码

#include<stdio.h>
int main()
{
	int i=0;
	char arr[5]={'a','o','e','i','u'};
	char ch;
	for (i = 0; i < 5; i++) {
		if (ch == arr[i] || ch == arr[i] - 32)
		{
			printf("Vowel\n");
			break;
		}
	}
	if (i==5)
		printf("Consonant\n");
	return 0;
}

可是真的是这样吗,让我们看一看这个运行的结果。 

为什么会这样呢?好像和我们预想的不太一样。从结果上看,我们好像完成了对一个字母的判断,那么我们该如何多组输入呢?这里就会用到while((scanf("%c",&ch))!=EOF)来完成多组输入。

接下来让我详细了解认识一下即将在题目里大展身手这位“大家伙”,同诸位观一观他的庐山真面目。

 while((scanf("%c",&ch))!=EOF)

首先我们来认识一下scanf( )的返回值。要scanf的返回值等于成功输入的个数。

如果成功,该函数返回成功匹配和赋值的个数。

如果达到文件末尾或发生读取错误,则返回EOF

那么EOF又是何方神圣呢?

其实答案很简单,EOF是 End Of File的缩写,即表示文件的结束,他的宏定义值为-1

在文本中,数据通常以ASCII码值的形式存放,但ASCII码值的范围为0-127,不可能出现-1,因此可以用EOF作为文件的结束标志

那么,有没有其他的方法呢,其实基于此,我们仍然可以做一些小小的变动,让他变得更加简洁些,该怎么做呢?当然我们你还要回到数据在计算机的储存方式——二进制。

 while(~(scanf("%c",&ch))) 

当读取失败时,scanf( )返回-1,经过取反会变成 0,跳出循环,完成 while((scanf("%c",&ch))!=EOF)一样的效果。

知道了如何多组输入,我们再回到题目,我们根据以上做一个小变动再试一次把!

#include <stdio.h>
int main() {
	int i = 0;
	int arr[5] = {'a', 'e', 'i', 'o', 'u'};
	char ch;
	while ((scanf("%c", &ch))!=EOF ) {
		for (i = 0; i < 5; i++) {
			if (ch == arr[i] || ch == arr[i] - 32)
			{
				printf("Vowel\n");
				break;
			}
		}
		if (i==5)
			printf("Consonant\n");
	}
	return 0;
}

哎?!怎么还是不对?问题究竟在哪里?

我们只输入了两个字符为什么会出现三个打印结果呢?要理解为什么,我们要对scanf( )的理解要更加深刻一些。不妨,让我们了解一下,输入函数是如何工作的。

当我们从控制台输入字符时,scanf( )并没有全部接收    ,而是将他们存放在寄存器中按照输入的顺序一个一个读取,同时要知道,在输入时的 “回车”,也属于字符,最终会被scanf( )读取。因此我们需要把“回车”去除干净。

利用getchar( )去除换行符   

getchar( )和scanf( )都属于输入函数,不妨,让我们了解一下,输入函数读取字符的原理。接下来,让我们认识一下,缓冲区。

缓冲区

缓冲区是内存空间的一部分,也就是说在内存空间中预留了一定大小的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

工作原理

当调用输入函数scanf( )时,输入函数会将我们输入的数字,输入到输入缓冲区,而当我们的“输入缓冲区”有内容时,再次输入将不会被执行,而是直接跳过执行,将输入缓冲区的内容赋给变量。也就是说,在读取了前一个字符以后,换行符留在了缓存区,使得后面的字符无法赋值, 

这时getchar( )的使用,将换行符提前读取。这样,scanf( )就可以顺利读取后面的内容,最终完成任务。

#include <stdio.h>
int main() {
	int i = 0;
	int arr[5] = {'a',for (i = 0; i < 5; i++) {
	char ch;
	while ((scanf("%c", &ch))!=EOF ) {
		getchar();
		for (i = 0; i < 5; i++) {
			if (ch == arr[i] || ch == arr[i] - 32)
			{
				printf("Vowel\n");
				break;
			}
		}
		if (i==5)
			printf("Consonant\n");
	}
	return 0;
}

那么可不可以不使用getchar( )呢?不使用的话,最好让scanf( )自己读取字符的时候同时把换行符一并读取了,这样的方法能行吗?其实,答案不容置喙,是肯定的。

scanf("%c\n",&ch)同样可以去除换行符

三、练手-字符逆序

好了,了解到上面的知识,相信我们对使用 while 语句的多组输入,有了更深的认识。不妨,我们再做一道题练练手。

我们以一道牛客网的题目作练手。题目链接贴在这里

字符逆序__牛客网字符逆序icon-default.png?t=N7T8https://www.nowcoder.com/questionTerminal/cc57022cb4194697ac30bcb566aeb47b

题干如下 

//错误答案模板
#include <stdio.h>
#include<string.h>
int main() {
    char str[10001];
    while((scanf("%s",str))!=EOF)
    {
         int len=strlen(str);
         int left=0;
         int right=len-1;
         while(left<right)
         {
            char tmp=str[left];
            str[left]=str[right];
            str[right]=tmp;
            left++;
            right--;
         }
         puts(str);
    }
    return 0;
}

基本思路 

这道题的基本思路还不简单,利用多组输入,将所有字符全部存放在数组,接着用双下标法完成数组逆置,然后用puts( )函数将数组元素输出。哎呀,简单简单,下一个。可是答案真的仅仅如此吗?当我们信誓旦旦的点击“保存并提交”时,结果会发现,事实上远没有我们想的那么简单。

 

究竟是为什么呢? 当我们看到实际输出的时候可能会非常诧异。怎么会实际输出是两行呢?这主要是scanf( )的原因,scanf( )当遇到空格会读取结束。由于这样的特性,实际输出一分为二分别输出。那么这个问题该怎么解决呢?于是我么想到了scanf( )的正则表达。

scanf( )正则表达的多组输入

while((scanf("%[^\n]",arr))!=0)

那么问题来了,为什么scanf( )正则之后,停止条件变成了scanf("%[^\n]",arr))!=0呢?其实答案很简单,当使用正则之后,scanf( )的返回值变成了成功读取字符串的个数,不再读取则返回0作为返回值。

那么除了正则表达,还可以使用什么进行代替呢?于是,我们想到了——gets( )函数。 

使用gets( )的多组输入 

不妨,我们先了解一下gets( )函数。

gets( )函数

gets( )函数的原型:

char * gets(char *string)

gets函数作用: 

从标准输入中读取字符,遇到换行符'\n'(newline)

gets函数返回: 

读取成功时返回一个指针,指向的是存放读取数据的地址值;
读取失败(遇到EOF或者其他错误)时,返回NULL;

当gets( )函数读取失败返回时,返回NULL。由此,我们可以知道gets函数的多组输入,是while(gets(arr)!=NULL) 

四、小结 

常规多组输入:

while((scanf("%c",&ch))!=EOF)

while(~(scanf("%c",&ch))) 

除去换行符:

利用getchar( )

scanf("%c\n",&ch)

读取空格的多组输入:

while((scanf("%[^\n]",arr))!=0)

while((gets(arr))!=NULL)

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值