从小甲鱼C++例程弄清 scanf 和 getchar 函数

例程及功能描述

根据实例程序,快捷高效弄清楚scanf 和 getchar 的实现过程,有利于更好的使用scanf 和 getchar。

例程:

#include<iostream>
using namespace std; 

int main(void)
{
	int i;
	int sum = 0;
	char ch;

	printf("请输入一串整数和任意数目的空格:");

	while (scanf("%d", &i) == 1)
	{
		sum += i;
		while ((ch = getchar()) == ' ') ;//屏蔽空格
		
		if (ch == '\n')
		{
			break;
		}
		ungetc(ch, stdin);
	}

	printf("结果是:%d", sum);
	printf("\n");
	system("pause");

	return 0;
}

功能能描述:

用户输入一串数字和任意数目的空格,程序自动屏蔽数字中的空格并计算由空格隔开的数字之和。

遇到的问题

1.如果没有ungetc(ch, stdin)程序输出的计算结果不正确。

2.为什么程序是输入一串整数和空格的一串数据后回车,程序才执行while (scanf("%d", &i) == 1)的循环体。

3.为什么输入一串数据后程序的循环体会一直执行,不应该是执行一次后重新输入一串数据再执行循环体吗?

4.程序中的scanf和getchar起什么作用?执行流程是什么样的?

5.ungetc返回输入流是什么意思?

6.屏蔽空格是怎么实现的?

问题解决

scanf函数的输入和执行过程

scanf 函数在执行时需要用户进行输入,用户通过键盘输入的是一串数据,而不是一个数据;

在 scanf 中,从键盘输入的一切数据,不管是数字、字母,还是空格、回车、Tab 等字符,都会被当作数据存入缓冲区。(例:输入的是123本质上是输入的三个字符’1’,‘2’,‘3’)
存储的顺序是先输入的排前面,后输入的依次往后排;

由于我们需要的是整形数据,因此需要用%d控制符来将输入的字符型数据转换为整形数据;

按回车键的时候 scanf 开始进入缓冲区从前往后依次一位一位地读取数据,例如:输入123 45,scanf 读取’1’,在读取’2’,再读取’3’,再读取空格。由于使用的是%d控制符获取的字符’1’,‘2’,'3’将转化为数字1,2,3,同时scanf 遇到空格,Tab,enter键时会将之当做分隔符,也就是遇到空格时scanf 就会跳过不读取空格,且退出此次对数据缓冲区的访问。scanf 获取的参数是数字123;

scanf访问了数据缓冲区后,被scanf读取的数据将从数据缓冲区清空释放。例如:数据缓冲区剩下 ’ ',‘4’,'5’三个字符。若将控制字符换成%c那么scanf 此次访问数据缓冲区读取的数据是字符123 45,缓冲区全部清空。

getchar函数的输入和执行过程

getchar函数的输入类似scanf函数,也是执行时访问输入数据缓冲区,但是getchar只会依次读取一个字符,并将字符从输入数据缓冲区取出,直接返回得到的字符型数据。此时数据缓冲区的值也会清空被读取的数据位。

有了对scanf 和 getchar 函数的了解,我们带入程序加以理解,解决前面的问题。

程序执行逻辑回顾

1. 程序进入主函数之后进行变量定义,然后打印输入提示

2. 程序执行到while (scanf …)(讨论条件为真):

第一次while(scanf…)循环
第1步 执行scanf("%d", &i);
1.用户输入数据’1’,’ ‘,‘2’,‘3’,’ ‘,‘4’,‘5’,‘6’,’\n’。
此时输入数据缓冲区为:
在这里插入图片描述

2.输入‘\n’后,scanf 访问数据缓冲区,读取到‘1’,继续读取到空格,退出,并将数字1赋予变量 i 。scanf 函数返回1。此时数据缓冲区为:
在这里插入图片描述

第2步 执行while的条件判断,scanf返回值为1( i 是否接收到值1),执行while(scanf("%d",&i) == 1)的循环体。

3.程序执行到sum,sum的值为1

4.程序执行到while(getchar…)

第1步 getchar 访问数据缓冲区,获得空格字符,并返回空格字符。
第2步 while 条件判断为真,执行循环体,但是没有语句就是空操作。此时数据缓冲区为:
在这里插入图片描述第3步 跳转到while(getchar…),getchar 继续访问数据缓冲区,得到字符‘2’,并返回字符‘2’。ch = ‘2’。此时数据缓冲区为:
在这里插入图片描述可以看到虽然while的循环体为空语句,但是经过getchar操作后,空格字符从数据缓冲区清空,起到了屏蔽空格的作用。下一次检测时得到新字符‘2’,但同时数据缓冲区的字符‘2’同样被清空。

第4步 while 条件判断为假,不执行循环体。执行 if(…)

5.if 条件为假,执行ungetc(ch, stdin);

对于函数 ungetc 的作用是将ch的值返回输入流也就是将字符‘2’返回输入缓冲区。此时的输入缓冲区为:
在这里插入图片描述若没有执行ungetc,输入缓冲区为:
在这里插入图片描述
这样一个while(scanf…)就执行一次。

6.程序跳转到while(scanf…)

scanf 第二次访问数据缓冲区。

  1. 此时若没有执行ungetc,scanf 获得的第一个字符是‘3’,之后遇到空格字符,跳出此次访问。获得数字3。sum的值为1 + 3 = 4。得到错误的结果。
  2. 但是若执行了ungetc,scanf获得的第一个字符是‘2’,然后获得字符‘3’,再遇到空格,跳出此次访问,获得数字23。sum的值为1 + 23 = 32。得到正确的结果。

这就解释了为什么需要ungetc函数。同时屏蔽了空格。实现函数功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值