详解函数 scanf()、getchar()函数

文章详细介绍了scanf函数的工作原理,包括它如何从缓冲区读取数据,以及其以空白字符作为结束标志的特点。在示例中,解释了为何scanf在读取字符串时只获取到abc的原因。同时,讨论了getchar函数用于清除缓冲区的用途,特别是在密码确认场景下的应用,如何通过getchar解决未预期的换行符和空白字符问题。
摘要由CSDN通过智能技术生成

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;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值