C语言的输入输出函数

scanf函数

scanf函数,与printf函数一样,都被定义在stdio.h里,因此在使用scanf函数时要加上#include。它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中,其关键字最末一个字母f即为“格式”(format)之意。

1.函数原型:

int scanf( const char *format, ... );
scanf()函数是格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。
其调用格式为: scanf("<格式化字符串>",<地址表>);
函数 scanf() 是从 标准输入流 stdio 中读内容的通用 子程序,可以读入全部固有类型的数据并自动转换成机内形式。

2.返回值

scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。
如:
scanf("%d,%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
且返回值为int型.
例:使用scanf函数输入数据。
#include<stdio.h>
int main()
{
int a,b,c;
printf("输入 a, b, c\n");
scanf("%d,%d,%d", &a, &b, &c);
printf("a = %d b = %d c = %d\n", a, b, c);
return 0;
}
注意上面的scanf("%d,%d,%d",&a,&b,&c);中%d,%d,%d之间有逗号,在输入数据时也要加逗号,如果去掉逗号,输入时就不用逗号,而用空格,tab键或回车键将各个数据隔开

3.字符说明

scanf函数中的format字符串参数中可能包含下列内容:
    1.空白字符--它们与输入中的零个或者多个空白字符匹配(空格属于空白字符,此外还有像制表符等也属于空白字符),在处理过程中被忽略掉。
    2.格式代码--它们指定函数如何解释接下来的字符
    3.其他字符--当任何其他字符出现载格式字符串中的,下一个字符必须于与它相匹配。包括空格、制表符和新行符,都用于从输入流中匹配并放弃字符,被匹配的字符都放弃。如果不匹配,函数不再读取直接返回。
4.注意问题
 1.在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,TAB或回车作间隔。
 2.在输入字符数据(%c)时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。 
3.scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
  ① 遇空格、“回车”、“跳格”键。
  ② 遇宽度结束。
  ③ 遇非法输入。


先看测试案例:

#include <stdio.h>
#include <stdlib.h>
#define  N 100
int main()
{
    while(1)
    {

        int i,j,k;
        printf("Input i,j,k:\n");
        scanf("%d",&i);
        scanf("%d %d",&j,&k);
        printf("i=%d,j=%d,k=%d",i,j,k);
        printf("\n");

    }
    return 0;
}
测试结果:


由测试案例可以看出 3个整形值,输入的时候 无论有多少个空格或者回车键都不影响i,j,k三个值的输入。都会自动过滤掉空格或者回车键。

然后我们测试下 char  类型的:

测试案例:

#include <stdio.h>
#include <stdlib.h>
#define  N 100
int main()
{
   // while(1)
   // {

        int i;
        char j,k,c,d;
        printf("Input i,j,k:\n");
        scanf("%d",&i);
        scanf("%c %c",&j,&k);
        printf("i=%d,j=%c,k=%c",i,j,k);
        printf("\n");
        scanf("%c",&c);
        printf("c=%c",c);
        scanf("%c",&d);
        printf("d=%c",d);

  //  }
    return 0;
}
来看一下测试结果:

#代表空格 ,*代表回车

从上面的这张测试图我们可以看出:显然没有达到我们预期的效果,我们在输入了1*a#b* (我们的本意是1赋值给i,a 和b 分别赋值给j,k )但是 不等我们输入c和d的值,它就全部打印出来了。

原因如下:j,k,c,d 都是字符型的值,它可以接收 回车 空格和Tab键,当scanf函数以%c格式接收单个字符时,空格、回车、Tab键将不再作为分隔符,它们以ASCII码形式存储到对应参数地址所在内存空间。

看一下内存缓冲区的概念:

         缓冲区是为了提高存储器访问效率的存在。绝大多数输入输出流是完全缓冲的,数据流先进入内存缓冲区,当它写满时才会刷新(flush)到设备或文件中。“读取”和“写入”操作实际是从缓冲区(buffer)来回复制数据。但使用标准输入或输出时,并不一定会等到缓冲区满才执行刷新操作,缓冲状态由编译器决定。

         scanf函数从标准输入流(stdin)读取数据,按照格式说明参数,将数据写入参数地址所在空间。标准输入流默认的是键盘的输入流。但由于操作系统的缓冲区管理机制,从键盘上输入的数据并不是立刻被scanf函数读取,而是暂存于内存缓冲区,只有敲回车键的时候scanf函数才开始工作(尤其要注意,最后敲的回车键('/n')也会送入缓冲区)。也就是说,scanf函数取读的数据是缓冲区里的数据,只有当缓冲区为空的时候程序才会暂停下来,等待用户输入;反之,缓冲区不为空时它就不需要等待用户输入了,转而执行下一句程序指令!

对于我们的测试程序而言,我们在输入了1*a#b*之后,scanf开始工作 开始按照格式参数说明来匹配字符,首先找到1匹配给i,然后回车键* 批给给j a匹配给k,这时候我们的本意是等待c和d的输入,但是此时缓冲区中还存在#b*这3个字符,所以系统便没有等待这两个字符的输入,直接匹配。空格匹配给c,b匹配个d。


最后一个测试函数:

#include <stdio.h>
int main()
{
    int a;
    char c;
    do
    {
        scanf("%d", &a);
        scanf("%c", &c);
        printf("a = %d c = %c\n", a, c);

    } while(c != 'N');
    return 0;
}
执行结果如下:


从上图我们看出:首先输入a+回车。这个时候a获得1  c获得回车,然后我们继续输入一个a和回车,此时也直接打印恶劣a和c的值。a=1,c=a。

对于这里我是这么理解的。首先我们输入a和回车的时候 。缓冲区里面有a和回车。

第一个scanf开始找整形d的值,找遍缓冲区。没找到。退出该scanf函数,

然后第二个scanf开始找字符型c的值,找到a输出a,而a是在dowhile外面定义的。根据上一步的1.打印出1.

如果这样理解有错误,请高手指出!~


使用scanf函数进行输入,必须指定输入的数据的类型和格式,不仅繁琐复杂,而且很容易出错.C++保留scanf只是为了和C兼容,以便过去用C语言写的程序可以在C++的环境下运行。C++的编程人员都愿意使用cin进行输入,很少使用scanf。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值