必威体育Betway必威体育官网
当前位置:首页 > IT技术

C语言scanf函数以及缓存详解

时间:2019-10-08 15:42:19来源:IT技术作者:seo实验室小编阅读:67次「手机版」
 

c语言scanf

前言

  1. 以下代码都是在VC6.0环境下完成的;
  2. 对于缓冲这个知识,我觉得还有一些疏漏或错误,但是我又没找到很详尽的资料,有知道的朋友欢迎留言讨论;

需要清楚的几个知识点(以笔记本电脑为例)

  1. 人们一个传统的思维就是,笔记本是一个整体,键盘鼠标硬盘显示器,话筒,摄像头,喇叭等都是一个整体;这些组合起来确实是一个笔记本,但是对于cpu来说,这些设备都是外部输入输出设备(I/O),输出的是什么,输入的是什么?是数据
  2. 什么是输入设备,什么是输出设备?

    输入设备:首先这是一个设备,设备的功能是用来输入信息;比如键盘,鼠标,咱们很容易理解键盘,当我在这儿敲打键盘写博客的时候,屏幕上会显示字,所以这是一个键盘向电脑输入信息的设备;这里注意:对于键盘来说,数据是在输入(到电脑),但对于CPU来说,数据是在读取

    输出设备:同理就是用来输出信息的设备,比如你眼前的这个笔记本电脑屏幕;屏幕可以显示动画,文字,图片和视频;同理还有打印机,咱们经常打印一个word文件,很显然,CPU讲这个word输出到打印机;此时,对于打印机和屏幕来说,数据是在读取,对于CPU来说,数据是在写入(到输出设备)

  3. C语言中scanf()函数分隔符:空格(space),回车(enter),指标符(table);

scanf() :标准输入函数

定义:scanf()函数在stdio.h头文件中可以找到声明;如下图;

这里写图片描述

返回值:从上图中可以看出函数返回值类型是 int ,所以函数结束是有返回类型的;一般返回值为:EOF,0,1,2,3…其对应的意义是:

比如:scanf(“%d%d”,&x,&y);

返回值 意义
EOF 程序遇到错误或遇到end of file
0 x和y都没有被成功读入
1 只有x被成功读入
2 x和y都被成功读入

处理机制

scanf()以删除的方式从缓冲区读取数据(输入设备的数据存储缓冲区,比如键盘);也就是说,scanf从缓冲区读入一个数据项,该数据项在缓冲区中就被清除掉了。而如果scanf需要读取一个数据项,返现缓冲区当前是空的,那么程序就会在scanf代码处阻塞,等待用户输入,scanf函数接收到相应的数据项之后,在缓冲区中将这一数据项清除,scanf函数返回,程序继续执行。

我们以一个简单程序流程说明处理机制:

1.编写代码:

#include <stdio.h>

void main()
{
    int a;
    printf("请输入一个整数:");
    scanf("%d",&a);
    printf("a=%d\n",a);

}
  1. 输出结果

    这里写图片描述

  2. 处理机制 (这里只针对%d)

    这里写图片描述

    当程序执行到“scanf(“%d”,&a);”时,程序向CPU发出指令,要求其先检测输入缓冲内有没有数据,本程序内输入缓冲内没有数据,CPU开始等待输入设备(键盘)向输入缓冲内输入数据,这里咱们输入一个“2”,输入后按enter(回车),此时2和换行符一并被输入设备写入输入缓冲,输入缓冲检测到有回车进来了,CPU开始执行读取指令,将2读取后将其从输入缓冲清除,从输入缓冲将数据“2”赋值给a,由于a是一个具体的地址空间变量,所以赋值结束后,CPU将a的值写入输入缓冲,对于笔记本电脑而言,a的保存输出设备就是电脑硬盘,所以电脑硬盘就是输出设备;这样就完成了几个操作;(以上并不是详细的讲解,比如将2从输入设备删除后,还剩一个换行符没处理,下面说缓冲的时候再详细说)

  3. scanf对不同类型输入的处理方式

    4.1 整数%d

    对于整型数据的输入,也就是说”%d”类型的输入,scanf默认的分割符是所有的空白字符(空格,回车和指标符都行)。也就是说如果一个scanf函数中出现scanf(“%d%d”,&a,&b),那么用任何一个空白字符来分隔两个整数a,b的值,变量a,b都可以接收到正确的输入。另外,要注意的是,scanf对于数字输入,会忽略输入数据项前面的空白字符

    下面举个例子:

#include <stdio.h>

void main()
{
    int a,b;
    printf("请输入a和b的值:");
    scanf("%d%d",&a,&b);   //分隔符用空格
    printf("a=%d\nb=%d\n",a,b);
    printf("----------------\n");

    int c,d;
    printf("请输入c和d的值:");
    scanf("%d%d",&c,&d);    //分隔符用Tab
    printf("c=%d\nd=%d\n",c,d);
    printf("----------------\n");   
}

运行:

这里写图片描述

4.2字符串%s

scanf对于字符串输入的处理和对整数类似,会忽略前导的空白字符,而且默认的分隔符是所有的空白字符。但是,要注意的是,由于C语言中,没有string类型,都是用char型数组来表示。因此,scanf会为每一个输入的字符串最后加一个‘\0’ (NULL)。下面是一个例子,可以看出scanf这货的边界控制还是要

#include <stdio.h>
void main()
{
    char a[5],b[5];  
    int i;  
    printf("请输入a和b的值:");  
    scanf("%s%s",a,b);     
    printf("a=%s,b=%s\n",a,b);  
    for(i=0;i<5;i++)  
        printf("%d:(%c) ",a[i],a[i]);  
    printf("\n");  
    for(i=0;i<5;i++)  
        printf("%d:(%c) ",b[i],b[i]);  
    printf("\n");   

    printf("请再次输入a和b的值:");  
    scanf("%s%s",a,b);  
    printf("a=%s,b=%s\n",a,b);  
    for(i=0;i<5;i++)  
        printf("%d:(%c) ",a[i],a[i]);  
    printf("\n");  
    for(i=0;i<5;i++)  
        printf("%d:(%c) ",b[i],b[i]);  
    printf("\n");  
}

运行:

这里写图片描述

4.3 字符%c (注意

scanf在处理对字符数据的输入时,既不会忽略前导空白字符,默认也没有任何分隔字符。所有的字符,包括空白字符都会被当成输入字符。举个例子:

 #include <stdio.h>
 void main()
 {
    char a ,b ;  
    printf("请输入a和b的值:");  
    scanf("%c%c",&a,&b);
    printf("a=%c,b=%c\n",a,b);  
    printf("请输入a和b的值:");  
    scanf("%c%c",&a,&b);
    printf("a=%c,b=%c\n",a,b);  
}

运行结果:

这里写图片描述

C语言中的缓冲区

对程序4.3进行分析能够帮我们更好的理解scanf()函数的分隔符;

分析:

1~5:行程序正常执行;

6:程序走到这里,scanf检测到输入缓冲区没有字符,开始等待输入;我们输入了两个字符AB,这是我们一共在按键上依次按下”A”,”B”,“enter”,于是缓冲区现在有这三个字符;AB被分别分给了字符变量a,b;并且被清除了;于是缓冲区内就剩下了“enter”;

7:程序正常输出a,b值;

8:正常执行程序;

9:程序走到这里,scanf检测缓冲区内有字符,但是只有一个字符“enter”,不够再次分配两个变量的,所以程序让再输入一个字符;可是我们输入了两个字符,AB;程序结束后,a被赋值“enter”,b被赋值A,这时缓冲区不仅将会剩下一个B字符,还会剩下一个“enter”;这个缓冲区的内容会随着程序的结束而被消除,由于不操作了,所以我们感觉不到他俩的存在;

10:a,b再次被输出,a被输出了回车,所以换行了,a被输出了A;

程序结束;

缓冲区的三种类型

1. 全缓冲

在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2. 行缓冲 (scanf()函数的缓冲类型就是这个)

在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

3. 不带缓冲

也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

缓冲区的刷新

下面几种情况将引起缓冲区刷新,也就是清空所有数据:

1) 缓冲区被写满;

2) 执行flush语句;

3) 执行endl语句;

4) 关闭文件;

fflush(stdin)函数清楚缓冲区

举例:

 #include <stdio.h>
 void main()
 {
    char a ,b ;      printf("请输入a和b的值:");  
    scanf("%c%c",&a,&b);
    fflush(stdin);      //清楚输入缓冲区;
    printf("a=%c,b=%c\n",a,b);  
    printf("请输入a和b的值:");  
    scanf("%c%c",&a,&b);
    printf("a=%c,b=%c\n",a,b);  
}

运行:

这里写图片描述

fflush(stdin)函数用来清除缓冲区内所有的数据;从而等下一个输入函数来到的时候发现输入缓冲去没有字符,就直接要求从新输入;从而达到解决问题的目的;

本博客参考了下面两位前辈的博客比较多:

1. https://blog.csdn.net/junbopengpeng/article/details/16809475

2. https://blog.csdn.net/qq_36532097/article/details/70197061

相关阅读

便利蜂数学考卷曝光:没有三角函数、空间向量

A5创业网(公众号:iadmin5)1月31日消息,近日有消息称便利蜂正在裁员并且出了新招,要求员工参加数学考试,考试不及格的都开除。对此,便利

string的contain()函数用法

String.contain()函数主要用于匹配字符串,例如:String x=(1+(8*(9-6/2)/4)*2);if(x.contains("(")){System.out.println("匹配成功"

StretchBlt函数和BitBlt函数的用法

StretchBlt和BitBlt都用在双缓冲视图中,用来显示一幅图像一、StretchBlt函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设

MATLAB三维基本绘图-plot3()函数

clear all; theta=0:0.01*pi:pi*2; x=sin(theta); y=cos(theta); z=cos(4*theta); figure; plot3(x,y,z,'rs','LineWidth',2,'Mar

Oracle to_date()函数的用法

在Oracle数据库中,Oracle to_date()函数是我们经常使用的函数,下面就为您详细介绍Oracle to_date()函数的用法 to_date()与24小时制

分享到:

栏目导航

推荐阅读

热门阅读