你的程序也会莫名结束吗(scanf和getchar的正确打开方式)

在混着用scanf输入数据用getchar读取字符的时候,各种空白(空格、制表符、换行符)常常困扰我们。到底这个空白会不会被scanf接收呢?这是一个好问题。我来谈一点我浅薄的认识。

目录

缓冲输入:

scanf和getchar的‘接收’:

程序演示:

解决方案:


缓冲输入:

不知道你有没有注意,我们在把输入发送给程序前可以编辑输入,这是缓冲输入。

先来了解一下缓冲输入吧,与之相对的无缓冲(直接)输入,也就是程序可以立即使用输入;而缓冲输入是把我们输入的字符先存在一个叫做缓冲区的地方,等我们按下Enter后,程序才可以使用。

这一点很好,便于用户修改输入的字符,但是发送时按下的“Enter”可能会带来麻烦。

接下来看看scanf和getchar会接收什么数据叭~


scanf和getchar的‘接收’:

  1. getchar()读取每一个字符,包括空白(空格、制表符、换行符);这也是我以前懵懂无知,发现程序突然结束时,在scanf后面,不知道为什么的,加一个getchar回收Enter的原因。
  2. scanf在读取数字时会跳过空白,这点很重要。既然我标出了“在读取数字时”,你是否想到读取字符、字符串呢?
  3. scanf在读取字符串时也很乖,输入项之前的空白她都不理会,直到输入字符串;但是她也是铁面无私的包青天空白也是她的分隔符(也就是她从第一个不是空白的字符开始读一串字符直到遇到空白则停止);所以我们都知道用scanf读取的字符串中是没有空格的;
  4. scanf在读取字符时,既不会忽略之前的空白也没有任何分隔字符。所有的字符(包括空白)都会被当成输入字符。

程序演示:

关于以上所讲,我们写一个程序感受一下scanf和getchar的厉害:

程序内容主要是获取一个数组然后输出菜单并且获取用户选则,我们在第一个被调函数里用scanf读取字符,第二个用getchar读取字符,第三个用scanf读取数字。

#include<stdio.h>
#define N 100
char MenuAndChoice();//第一次先使用这个函数
char AMenuAndChoice();//第二次在main里改名字用这个函数
int BMenuAndChoice();//第三次在main里改名字用这个函数
int main()
{
	int anum,num[N];
	scanf("%d",&anum); //输入几个数据 
	for(int i=0;i<anum;i++)
	{
		scanf("%d",&num[i]);
	} 
	char choice=MenuAndChoice();
	printf("%c",choice); 
}

char MenuAndChoice()
 {
 	
 	printf("Choose from: A.B.C.D.\n");
 	char cc;
	 scanf("%c",&cc);
 	return cc;
 }
 
char AMenuAndChoice()
 {
 	
 	printf("Choose from: A.B.C.D.\n");
 	char cc;
	cc=getchar();
 	return cc;
 }

int BMenuAndChoice()
 {
 	printf("Choose from: 1 2 3 4 \n");
 	int cc;
	scanf("%d",&cc);
 	return cc;
 }

你是否发现调用前两个函数时程序没有等你输入选项就莫名其妙结束,这就是Enter在作祟

 //可恶可恶(〃>目<)

试试在调用前两个函数之前用getchar回收一下空白,有没有改变呢?

解决方案:

跳过一轮输入结束和下一轮输入开始之间的换行符和空格。

1.简单一点的老方法:用getchar回收

但是如果淘气可爱的用户偏偏要输入很多无用的空白,这个时候,我们就可以用如下代码:

while(getchar()!='\n')

        continue;

放到scanf后面可以丢弃上一轮输入后的所有字符(包括换行符),就可以为下一轮输入做准备啦~

2.scanf()中使用’\n’,就是scanf自己吃掉自己的回车,听起来还不错有没有,可是我觉得也挺麻烦。

scanf("%d\n",&n);

3.清空输入流缓冲区的函数:fflush(stdin);

在#include <stdlib.h>头文件中;


希望这篇小文章可以解决你的烦恼~~ 一起加油吧~~

2021.11.25

SThree楠钰子.

上一篇:读入优化


下一篇:CSP-S 前的比赛记录