scanf函数读取数据 清空缓冲区

scanf函数读取数据&清空缓冲区

  • scanf 从输入缓冲区读取数据
    • 数据的接收
    • 数据存入缓冲区
    • scanf 中%d读取数据
    • scanf中%c读取数据
  • 清空输入缓冲区
    • 例子
    • 用getchar()吸收回车
    • 练习

scanf 从输入缓冲区读取数据

首先,要清楚的是,scanf在读取数据的时候,不是从键盘上读取,而是从输入缓冲区读取数据

数据的接收

我们从键盘上输入的全部数据,不管是数字还是字母还是空格回车Tab键等,操作系统在接收时,都是将它们当成字符来接收的。
比如,我们从键盘输入123,它表示的并不是数字123,而是字符'1'字符'2'字符'3'

数据存入缓冲区

在scanf中,从键盘中输入的一切数据,,不管是数字、字母、还是空格回车、Tab键等这些字符都会被当作数据存入缓冲区
当按下回车键时,scanf开始进入缓冲区读取数据,从前往后,依次取。

scanf 中%d读取数据

scanf中%d读取数据时,%d只识别“十进制整数”。
对于%d而言,空格、回车、Tab键都是区分数据与数据的分隔符
当scanf进入缓冲区读取数据的时候,如果%d遇到空格、回车、Tab键,那么它并不会采用,而是跳过取后面的数据,直到取到“十进制整数”为止。


%d以十进制整数形式读取整数,scanf函数依然是每次读取一个字符,而不是读取一整个数字,不会马上结束读取进行存储。
首先scanf函数从第一个输入开始检查,它会跳过所有空白字符,直到它发现一个数字或者符号(+或-),它便会保存该字符然后往下读取,如果接下来读取依然是数字,他就会不断地保存然后读取下一个字符直到遇见一个非数字字符,scanf函数认为这里是数字的结尾。
大家可以参考一个博主的这篇文章scanf函数到底怎么读取数字?
对于被跳过和取出的数据,系统会将它从缓冲区中释放掉
未被跳过或取出的数据,系统会将它一直放在缓冲区,直到下一个scanf来获取。

%d读取时中遇到字母,那么它不会跳过也不会取用,而是直接从缓冲区跳出
下面举个例子:

#include <stdio.h> 
int main() 
{ 	int a,b; 	scanf("%d", &a ); 	printf("a=%d ", a); 	scanf("%d",&b);printf("a=%d",b);return 0; 
} 

当输入1(空格)2(回车)时,输出结果为
——————————————
a=1 b=2
——————————————
当输入1(Tab)2(回车)时,输出结果为
——————————————
a=1 b=2
——————————————
当输入(空格)(空格)1(空格)2(回车)时,输出结果为
——————————————
a=1 b=2
——————————————
当输入1(回车)2(回车)时,输出结果为
——————————————
1
a=1
2
a=2
——————————————
从输出结果可以看出来,不管是多种形式123的次性全部输入完,还是一个一个输入4,输出结果都是一样的。
原因在于从键盘上输入的数据都会被依次存入缓冲区,不管是数字还是字符都会被当作数据存进去。
我们可以全部将数据全部存入缓冲区后再一个一个用scanf取出,也可以到缓冲区存入一个数据scanf读取一个数据再到缓冲区存入一个数据再用scanf读取一个数据。


%d读取时中遇到字母,那么它不会跳过也不会取用,而是直接从缓冲区跳出

#include <stdio.h> 
int main() 
{ 	int a,b; 	scanf("%d", &a ); 	printf("a=%d ", a); 	scanf("%d",&b);printf("a=%d",b);return 0; 
} 

当我们输入
a(空格)1(回车)时,输出为
——————————————
a=-858993460 b=-858993460
——————————————
为什么会是这样的结果呢?
scanf中%d从缓冲区读取数据,从前往后依次取,先读到的字符是字母a,那么它不会跳过也不会取用,而是直接从缓冲区跳出,那么变量a没有值,即未被初始化,变量b也没有值,所以输出a=-858993460 b=-858993460

scanf中%c读取数据

对于%d,在缓冲区,空格,回车,Tab键都只是分隔符,不会被scanf当成数据取用,%d遇到它们就跳过,取下一个数据.但是如果是%c,那么空格,回车,Tab键都会被当成数据输出给scanf取用.

#include <stdio.h> 
int main() 
{ 	char a,b; 	scanf("%c", &a ); 	printf("a=%c ", a); 	scanf("%c",&b);printf("a=%c",b);return 0; 
} 

当我们输入1(空格)2()回车时,输出结果为
——————————————
a=1 b=
——————————————
这是因为,当我们输入结束时,输入缓冲区的数据为1(空格)2(回车)
第一个scanf语句scanf从缓冲区读取一个字符,即字符1,将a=1 打印到屏幕上.
第二句scanf依然要从缓冲区读取数据,这时缓冲区还有数据,为(空格)2(回车),所以不需要我们再次从键盘上进行输入.scanf从缓冲区读取(空格),将此赋给变量b,b= 打印到屏幕上.

此时缓冲区剩下了2(回车).
但我们希望的是,将字符2赋值给变量b,所以我们希望将(空格)清理掉,让scanf读取字符2.

清空输入缓冲区

例子

下面,先看一个例子
我们要实现用户输入密码,输入完之后,需要用户进行确认(Y/N)

#include <stdio.h> 
int main() 
{ 	char password[20]; 	printf("请输入密码:>"); 	scanf("%s", password); 	printf("请确认(Y/N):"); 	char ch=0;scanf("%c",&ch);if (ch == 'Y') 		printf("确认成功\n"); 	elseprintf("确认失败\n"); 	return 0; 
}

当我们运行程序,运行结果为
在这里插入图片描述
我们还没有输入Y或者N,为什么会直接弹出来确认失败呢?
这是因为当我们输入密码> 123456(回车)时,scanf开始从输入缓冲区读取数据,第一个scanf语句,它只是读走了"123456",缓冲区剩下了(回车),对于第二个scanf语句,scanf依然从缓冲区读取数据,将留下缓冲区的(回车)读走.

所以我们希望我们可以清理先清理掉(回车),然后让用户自己输入Y/N.

用getchar()吸收回车

当我们要从输入流中取一个字符,但在之前使用过scanf,那么此时就必须要先用getchar()吸收回车。否则取到的将不是你想要的字符,而是scanf遗留在输入流中的回车。
我们对上面的程序进行修改:

#include <stdio.h> 
int main() 
{ 	char password[20]; 	printf("请输入密码:>"); 	scanf("%s", password); 	getchar(); //(1)printf("请确认(Y/N):"); 	char ch=getchar();  //(2)if (ch == 'Y') 		printf("确认成功\n"); 	elseprintf("确认失败\n"); 	return 0; 
}

对于语句(1),我们用getchar()吸收scanf在缓冲区留下的回车,简单,方便,都不需要将从缓冲区读到的回车赋值给一个字符变量.
对于语句(2),用getchar()缓冲区读取一个字符,将此赋值给字符变量ch.

修改后的结果为:
在这里插入图片描述

练习

题目一
在这里插入图片描述
题目描述
描述
KiKi想完成字母大小写转换,有一个字符,判断它是否为大写字母,如果是,将它转换成小写字母;反之则转换为大写字母。
输入描述:
多组输入,每一行输入一个字母。
输出描述:
针对每组输入,输出单独占一行,输出字母的对应形式。
代码实现(方法一)-----用scanf获取字符

#include <stdio.h> 
int main()  
{char ch;while(scanf("%c",&ch) != EOF){getchar();//吸收回车if (ch>='a' && ch<='z')ch=ch-32;else if(ch>='A' && ch<='Z')ch =ch+32;      printf("%c\n",ch);}return 0; }

代码实现(方法二)----用getchar()获取字符

#include <stdio.h> 
int main()  
{char ch;while((ch=getchar())!=EOF){getchar();//吸收回车if (ch>='a' && ch<='z')ch=ch-32;else if(ch>='A' && ch<='Z')ch =ch+32;      printf("%c\n",ch);}return 0; 
}

代码实现(方法三)—使用库函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<ctype.h> 
//有库函数可以判断大写字母 -isupper 
//有库函数可以判断小写字母 -islower 
//大写转小写 -tolower 
//小写转大写 -toupper 
int main() 
{ 	char ch = 0; 	while(scanf("%c", &ch) == 1) 	{ 		if (islower(ch)) 			printf("%c\n",toupper(ch)); 		else if (isupper(ch)) 			printf("%c\n", tolower(ch));} 	return 0;
} 

题目二
在这里插入图片描述
题目描述
描述
KiKi想判断输入的字符是不是字母,请帮他编程实现。
输入描述:
多组输入,每一行输入一个字符。
输出描述:
针对每组输入,输出单独占一行,判断输入字符是否为字母,输出内容详见输出样例。

#include<stdio.h> int main() 
{char a;while((a=getchar())!=EOF){getchar();//吸收回车if(('a'<=a&&a<='z')||('A'<=a&&a<='Z')){printf("%c is an alphabet.\n",a);}else{printf("%c is not an alphabet.\n",a);}} 
} 

当然这个代码也可以修改一下,不吸收回车

#include<stdio.h> int main() 
{char a;while((a=getchar())!=EOF){if(('a'<=a&&a<='z')||('A'<=a&&a<='Z')){printf("%c is an alphabet.\n",a);}else if{printf("%c is not an alphabet.\n",a);}} 
} 

用 if 和 else if,这样我们没有处理的回车,也不会满足其中的任何一个条件,而执行语句.
同时,也可以利用库函数:

#include <stdio.h>
#include <ctype.h> 
int main() 
{char a;while ((a = getchar()) != EOF){getchar();//吸收回车if (isupper(a) > 0 || islower(a) > 0){printf("%c is an alphabet.\n", a);}else{printf("%c is not an alphabet.\n", a);}}return 0; 
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/54238.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp:图片验证码检验问题处理

图形验证码功能实现 uniapp&#xff1a;解决图形验证码问题及利用arraybuffer二进制转base64格式图片&#xff08;后端传的图片数据形式&#xff1a;x00\x10JFIF\x00\x01\x02\x00…&#xff09;_❆VE❆的博客-CSDN博客 UI稿&#xff1a; 需求&#xff1a;向后端请求验证码图片&…

HttpServletRequest和HttpServletResponse的获取与使用

相关笔记&#xff1a;【JavaWeb之Servlet】 文章目录 1、Servlet复习2、HttpServletRequest的使用3、HttpServletResponse的使用4、获取HttpServletRequest和HttpServletResponse 1、Servlet复习 Servlet是JavaWeb的三大组件之一&#xff1a; ServletFilter 过滤器Listener 监…

深度学习(35)—— StarGAN(2)

深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;2&#xff09; 完整项目在这里&#xff1a;欢迎造访 文章目录 深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;2&#xff09;1. build model&#xff08;1&#xff09;generator&#xff08;2&#…

react中hooks的理解与使用

一、作用 我们知道react组件有两种写法一种是类组件&#xff0c;另一种是函数组件。而函数组件是无状态组件&#xff0c;如果我们要想改变组件中的状态就无法实现了。为此&#xff0c;在react16.8版本后官方推出hooks&#xff0c;用于函数组件更改状态。 二、常用API 1、use…

解决运行flutter doctor --android-licenses时报错

问题描述&#xff1a; 配置flutter环境时&#xff0c;会使用flutter doctor命令来检查运行flutter的相关依赖是否配好。能看到还差 Android license status unknown.未解决。 C:\Users\ipkiss.wu>flutter doctor Flutter assets will be downloaded from https://storage.…

pygame贪吃蛇游戏

pygame贪吃蛇游戏 贪吃蛇游戏通过enter键启动&#xff0c;贪吃蛇通过WSAD进行上下左右移动&#xff0c;每次在游戏区域中随机生成一个食物&#xff0c;每次吃完食物后&#xff0c;蛇变长并且获得积分&#xff1b;按空格键暂停。 贪吃蛇 import random, sys, time, pygame from …

eclipse was unable to locate its companion shared library

当转移或者Copy工程时&#xff0c; eclipse was unable to locate its companion shared library eclipse.ini 里面的路径配置错误导致 --launcher.library C:/Users/**/.p2/pool/plugins/org.eclipse.equinox. launcher.win32.win32.x86_64_1.2.700.v20221108-1024 -product …

【云原生】K8S二进制搭建三:高可用配置

目录 一、部署CoreDNS二、配置高可用三、配置负载均衡四、部署 Dashboard 一、部署CoreDNS 在所有 node 节点上操作 #上传 coredns.tar 到 /opt 目录中 cd /opt docker load -i coredns.tar在 master01 节点上操作 #上传 coredns.yaml 文件到 /opt/k8s 目录中&#xff0c;部…

孤立随机森林(Isolation Forest)(Python实现)

目录 1 简介 2 孤立随机森林算法 2.1 算法概述 2.2 原理介绍 2.3 算法步骤 3 参数讲解 4 Python代码实现 5 结果 1 简介 孤立森林&#xff08;isolation Forest&#xff09;是一种高效的异常检测算法&#xff0c;它和随机森林类似&#xff0c;但每次选择划分属性和划分…

DASCTF 2023 0X401七月暑期挑战赛 Web方向 EzFlask ez_cms MyPicDisk 详细题解wp

EzFlask 源码直接给了 CtrlU查看带缩进的源码 import uuidfrom flask import Flask, request, session # 导入黑名单列表 from secret import black_list import jsonapp Flask(__name__) # 为 Flask 应用设置一个随机的 secret_key app.secret_key str(uuid.uuid4())# 检查…

OpenAI 已为 GPT-5 申请商标,GPT-4 发布不到半年,GPT-5 就要来了吗?

据美国专利商标局&#xff08;USPTO&#xff09;信息显示&#xff0c;OpenAI已经在7月18日申请注册了“GPT-5”商标。 在这份新商标申请中&#xff0c;OpenAI将“GPT-5”描述为一种“用于使用语言模型的可下载计算机软件”。 继GPT-4发布之后&#xff0c;它预计将成为OpenAI下一…

RocketMQ生产者和消费者都开启Message Trace后,Consume Message Trace没有消费轨迹

一、依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.0.3</version> </dependency>二、场景 1、生产者和消费者所属同一个程序 2、生产者开启消…