1. scanf()函数
1.1 scanf基本语法
#include <stdio.h>
int scanf( const char *format, ... );
1.2 scanf原理
scanf 可以根据设置好的格式从stdin获取数据;但是我们从键盘上输入的数据并不会直接传递到scanf上,我们从键盘上输入的数据会先进入缓冲区,scanf 则会从缓冲区里面拿对应的数据
scanf 从缓冲区中只会拿取能够符合格式控制符要求的数据,如果格式不符合,则会丢弃在缓冲区
1.3 scanf的格式控制符
现在大家都知道scanf 是从缓冲区获取数据,那么scanf 获取数据的结束标识是什么么?怎么判断此次获取数据该结束了?
先来看一段代码:
char str[20] = { 0 }; int rs = scanf("%s",&str); //要求输入一个字符串 printf("str = %s\n",str); printf("scanf返回值:%d",rs);
很奇怪,代码中要求输入一个字符串,我在键盘上输入的也是一个字符串“abc defg”,为什么scanf最后获取的数据只有“abc”呢?
原因是我们在键盘上输入“abc defg”,为了将数据写入缓冲区,还敲了一个回车,此时在缓冲区内的数据是"abc defg\n"
abc defg\n /* 因为scanf读取字符串时时以空白字符(tab,空格,回车)为获取数据的结束标志,那么缓冲区内的数据分为三份: abc 空格 \n */
scanf在缓冲区中读取字符串时以空白字符(tab,空格,回车)为获取数据的结束标志,所以上面代码中scanf 获取的数据只有abc
2. getchar()函数
2.1 getchar基本语法
#include <stdio.h>
int getchar( void );
getchar()函数从stdin(标准输入)每次获取一个字符,如果到达文件尾或者获取失败则返回EOF
先看一段代码:
while (1) { int ch = getchar(); printf("ch = %c\n", ch); printf("ascll --> %d\n", ch); if (ch == EOF) { break; } }
2.1 经典案例原理解析
2.1.1 情况一分析
先上代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
printf("请输入密码:");
char pw[20] = { 0 };
scanf("%s", &pw);
printf("请确认(Y/N):");
char rs = 0;
scanf("%c", &rs);
if (rs == 'Y') {
printf("\n%s\n", "密码确认成功!");
}
else {
printf("\n%s\n", "密码确认失败!");
}
return 0;
}
1. 原理解析
分析原理:我们在键盘上输入 “abcdef”,然后为了将数据写入到缓冲区,还再敲了一下回车,那么此时缓冲区中的数据应该是 “abcdef\n”
经过上面的分析,发现没等我们从键盘上输入(Y/N)进行密码确认,rs 直接拿着获取到的 \n,进行密码确认校验了,所以直接跳出“密码确认失败”
2. 解决措施
如何解决这个问题呢?
首先是因为在密码确认环节从缓冲区中获取到了 \n 这个意外的数据导致问题出现,只要我们获取的不是 \n 而是从键盘上输入的 Y/N,问题就解决了;
所以解决方案就是在密码确认环节之前将 \n 从缓冲区中清除掉即可;
通过 getchar() 清除掉缓冲区的 \n:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
printf("请输入密码:");
char pw[20] = { 0 };
scanf("%s", &pw);
int ch = getchar(); //清空缓冲区中的 \n 字符
printf("请确认(Y/N):");
char rs = 0;
scanf("%c", &rs);
if (rs == 'Y') {
printf("\n%s\n", "密码确认成功!");
}
else {
printf("\n%s\n", "密码确认失败!");
}
return 0;
}
2.1.2 情况二分析
当我们解决了上面的问题,又发现了新的情况:当我们输入的密码带有空白字符(空格符,制表符)时,不等我们从键盘上输入(Y/N)进行密码确认,直接跳出“密码确认失败”;
1. 原理解析
经过上面的分析,发现没等我们从键盘上输入(Y/N)进行密码确认,rs 直接拿着获取到的字符 d ,进行密码确认校验了,所以直接跳出“密码确认失败”
2. 解决措施
因为在密码确认环节前缓冲区中还有其他的数据,导致问题出现
所以解决方案就是在密码确认环节之前将缓冲区中其他数据清除掉即可;
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
printf("请输入密码:");
char pw[20] = { 0 };
scanf("%s", &pw);
int ch = -1;
while (ch = getchar(), ch != '\n') { //清空缓冲区内字符
//printf("ch = %d\n", ch);
;
}
printf("请确认(Y/N):");
char rs = 0;
scanf("%c", &rs);
if (rs == 'Y') {
printf("\n%s\n", "密码确认成功!");
}
else {
printf("\n%s\n", "密码确认失败!");
}
return 0;
}