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

这篇具有很好参考价值的文章主要介绍了scanf函数读取数据 & 清空缓冲区。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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"); 	
    else
		printf("确认失败\n"); 	
    return 0; 
}

当我们运行程序,运行结果为
scanf函数读取数据 & 清空缓冲区,C语言,c语言,c++,算法
我们还没有输入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"); 	
    else
		printf("确认失败\n"); 	
    return 0; 
}

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

修改后的结果为:
scanf函数读取数据 & 清空缓冲区,C语言,c语言,c++,算法

练习

题目一
scanf函数读取数据 & 清空缓冲区,C语言,c语言,c++,算法
题目描述
描述
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;
} 

题目二
scanf函数读取数据 & 清空缓冲区,C语言,c语言,c++,算法
题目描述
描述
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,这样我们没有处理的回车,也不会满足其中的任何一个条件,而执行语句.
同时,也可以利用库函数:文章来源地址https://www.toymoban.com/news/detail-627592.html

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

到了这里,关于scanf函数读取数据 & 清空缓冲区的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何在 Linux 中清空缓冲区和缓存内存?

    在 Linux 系统中,缓冲区和缓存内存起着重要的作用,用于提高系统性能和优化磁盘访问。然而,有时候我们可能需要清空缓冲区和缓存内存,以释放系统资源或解决某些性能问题。本文将详细介绍如何在 Linux 中清空缓冲区和缓存内存,并提供一些实际的示例。 在深入讨论如

    2024年02月06日
    浏览(57)
  • getchar()清空缓冲区剩余的空格回车等转义字符

    多次使用scanf输入字符会出现以下错误: 分析如下: 1 、输入语句scanf(“%c,%c”,a,b)中,“%c,%c”中间有“,”,所以键盘输入时候,两个字符间应该用“,”隔开; 2、第一个scanf输入为\\\"3,h/n\\\"(scanf以回车、空格、制表符Tab结束),键入的字符中有转义字符回车n,该转义字符会存到

    2024年02月13日
    浏览(30)
  • 【学习笔记】Esp32 Arduino 串口中断函数 缓冲区修改

    最近需要用Esp32上传数据,有一块数据采集板,由串口通信,控制指令12+2字节(控制字+校验位),返回的数据量为,250、500、1000、2000字节 一开始写这个功能时用的 While 扫描串口来实现的,发现效率太低,随后开始用中断,原来并没有用过,所以参考ESP-IDF手册,单几经尝试

    2024年02月16日
    浏览(39)
  • linuxC语言缓冲区及小程序的实现

    为缓和 CPU 与 I/O 设备之间速度不匹配,文件缓冲区用以暂时存放读写期间的文件数据而在内存区预留的一定空间。使用文件缓冲区可减少读取硬盘的次数。 系统自动地在内存为程序中每一个正在使用的文件开辟一块文件缓冲区。 从内存向磁盘输出数据,先送到内存中的缓冲

    2024年02月04日
    浏览(30)
  • Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角

    Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等): Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等)_jts-core_霸道流氓气质的博客-CSDN博客 Java+GeoTools实现WKT数据根据EPSG编码进行坐标系转换: Java+GeoTools实现WKT数据根据

    2024年02月09日
    浏览(33)
  • 【Linux】语言层面缓冲区的刷新问题以及简易模拟实现

    我们接下来要谈论的是我们语言层面的缓冲区(C,C++之类的),不是我们操作系统内核里面自带的缓冲区,我们每次在打开一个文件的时候,以C语言为例子, C语言会为我们所打开的这个文件分配一块缓冲区,用来缓存我们读写的数据`,这个缓冲区会被放在我们创建的FILE的

    2024年02月05日
    浏览(39)
  • Linux缓冲区续集——手撕fopen、fwrite、fflush、fclose等C库函数

    目录 头文件: 接下来就是设计这四个函数:Mystdio.c 重点讲一讲_fflush函数的底层实现原理: 所以数据内容的经过如下: 总结:        执行——测试写好的这4个函数: 运行结果: 修改测试代码: 运行结果:        回顾上文,我讲述了关于Linux文件系统中关于缓冲区的含义

    2024年02月10日
    浏览(27)
  • (六)矢量数据的空间分析——缓冲区分析

    缓冲区是一组或一类地图要素(点、线、面)按设定的距离条件,围绕这组要素而形成具有一定范围的多边形实体,从而实现数据在二维空间扩展的信息分析方法。 从数学的角度来看,缓冲区是给定空间对象或集合后获得的他们的邻域。邻域的大小由邻域的半径或缓冲区建立

    2024年02月09日
    浏览(34)
  • 使用环形缓冲区ringbuffer实现串口数据接收

    环形缓冲区(ringbuffer),实际上就是一种队列数据结构,只不过它不是线性队列,而是环形队列。 关于环形缓冲区(ringbuffer)的详细介绍,网上一搜一大把,这里不重复介绍了,我这里直接上代码。 详细介绍可以参考下面链接里面的介绍: https://en.wikipedia.org/wiki/Circular_b

    2023年04月19日
    浏览(34)
  • 【看表情包学Linux】文件描述符 | 重定向 Redirection | dup2 函数 | 缓冲区的理解 (Cache)

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 在上一章中,我们已经把 fd 的基本原理搞清楚了。本章我们将开始探索 fd 的应用特征,探索 文件描述符的分配原则。讲解重定向,上一章是如何使用 fflush 把内容变出来的,介绍 dup2 函数,

    2023年04月25日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包