1.一个例子
我们首先来看一个简单的程序:
例题:确认你输入的密码
//确认你输入的密码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char password[20] = { 0 }; //密码
printf("请输入你的密码:\n");
scanf("%s", password); //输入密码
printf("确认你的密码: (Y/N)\n");
int ch = getchar(); //获取一个字符(Y/N)
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
这个按正常的程序来走的话,我们输入密码之后紧接着就会继续确认密码,但是运行起来并不是如此:
继续按下回车键以后:
我们可以发现,程序直接结束了,那么为什么会发生这个错误呢?这时候我们就不得不了解一下---缓冲区这一个概念了.
2.什么叫缓冲区
首先来一段比较专业的描述:
ANSIC标准是采用缓冲文件系统处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块文件缓冲区。从内存向硬盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到硬盘上。如果从硬盘向计算机读入数据,则从硬盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。 通俗一点来讲,系统的内存空间中预留了一定的存储空间,当你输入数据时就会被系统存储在这些空间中,这些空间用来缓冲输入或输出的数据,因此这部分预留的空间就叫做缓冲区。打个比方,如果当一个老师准备上课时,有很多学生陆陆续续的提问题,不断打断老师讲课,那么课堂效率就会明显下降;若老师说,当一个人攒够10个问题以后才能提问,那么一方面会一定程度上限制同学提问的次数,另一方面也会提高课堂的效率,缓冲区也是这个道理。
3.对一个实例代码进行分析
实例代码--大写字母转为小写字母
//注:此代码此时是作为一个错误案例
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
printf("%c", ch + 32);
}
return 0;
}
当getchar输入函数读取内容的时候,在我们的键盘输入和它之间有一个输入缓冲区,它其实是在输入缓冲区里面读取数据的,比如当我们开始输入数据之前,屏幕上就会什么都没有(因为缓冲区里面没有东西),
当我们放入一个数据,比如说我们在屏幕上输入一个字符A,
这时缓冲区里面也是没有任何数据的,但是当我们按下回车(Enter)键以后,字符A和\n(回车)这两个数据才会被放到缓冲区中去,
输出结果:
此时getchar()就会拿走缓冲区里的第一个字符,也就是'a',将它放到ch中去,所以大写字母A就会被转换为小写字母a被打印出来,但是这个*号是哪儿来的呢?因为当输入缓冲区中的字符A被拿走后,此时缓冲区里面就会只剩下一个\n,
而当我们再次进入循环,getchar此时就会发现缓冲区中有一个剩余的数据(\n)没被拿走,因此就会直接把这个\n拿到ch里面去,此时ch的ASCLL值就是'\n'的ASCLL值(10),印出来的字符就是'*'(*的ASCLL值为42),因此我们发现,这些输入函数使用的顺序大概就是
但是遇到这种情况我们该怎么办呢?所以我们要想个办法将这个'\n'或者缓冲区剩余的数据拿走,很简单,再使用一次getchar函数,此时缓冲区剩余的'\n'就会被这个getchar函数拿走,这个操作也被称为清理缓冲区。
修改后代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
printf("%c", ch + 32);
getchar();//清理缓冲区
}
return 0;
}
输入字符'A',输出字符'a':
当我们了解输入函数的使用过程之后,我们就可以对开头的例子进行分析并修改了。
4.分析开头的例子
原代码:
//确认你输入的密码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char password[20] = { 0 }; //密码
printf("请输入你的密码:\n");
scanf("%s", password); //输入密码
printf("确认你的密码: (Y/N)\n");
int ch = getchar(); //获取一个字符(Y/N)
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
当我们在屏幕中输入密码时,再按下回车(Enter)键,输入的密码和'\n'(换行符)就会被存储到缓冲区当中,假设我们输入的密码为123456789,因此此时缓冲区当中的情况就是:
此时scanf就会将我们输入的密码从缓冲区拿出来,并将密码存放到password当中,则缓冲区中就只剩下一个'\n',
但是当使用getchar时,getchar就会将缓冲区中剩余的'\n'拿走,因此此时ch=='\n',所以最后会直接输出"放弃确认"。
要将代码改正确也很简单,直接在scanf后面再放一个getchar()就行,这样getchar()可以起到一个吸收缓冲区中剩余的'\n'的作用。
修改后的代码如下:
//确认你输入的密码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char password[20] = { 0 }; //密码
printf("请输入你的密码:\n");
scanf("%s", password); //输入密码
getchar();
//清理缓冲区
printf("确认你的密码: (Y/N)\n");
int ch = getchar(); //获取一个字符(Y/N)
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
输入密码:
确认密码:
输出结果:
本篇博客的内容就到此结束了,如果你觉得对你多少有点帮助的话,可以点赞或者收藏支持一波哦,欢迎大佬在评论区批评指正,我们下次再见!!!