c语言scanf中的分隔符的作用,C语言中scanf与分隔符(空格回车Tab)-程序员宅基地

技术标签: c语言scanf中的分隔符的作用  

众所周知,C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值,并存储到参数列表中指针所指向的内存单元。下面从几个方面说一下一些稍微细节的东西。下面的实验都在vc6.0中通过。

1、scanf的返回值

scanf通常返回的是成功赋值(从标准输入设备赋值到参数列表所指定的内存区域)的数据项数,如果出错或是遇到end of file(注意,如果想从键盘输入EOF,在windows的DOS窗口用Ctrl+Z 或F6;在UNIX系统上,用CTRL+D。),则返回EOF,比如:

scanf("%d%d", &x, &y);

如果x和y都被成功读入,那么scanf的返回值就是2;

如果只有x被成功读入,返回值为1;

如果x和y都未被成功读入,返回值为0;

如果遇到错误或遇到end of file,返回值为EOF。

2、scanf的处理机制

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

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

首先,要清除一个概念:空白字符(white space)。一般,程序中所指的空白字符是指空格(space),回车(enter)和指标符(table)。

3.1 整数%d

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

Code:

#include

intmain()

{

inta,b;

printf("Input the value of a and b:");

while(scanf("%d%d",&a,&b)!=EOF)

{

printf("a=%d,b=%d\n",a,b);

printf("Input the value of a and b:");

}

return0;

}

Output:

Input the value of a and b:123 456

a=123,b=456

Input the value of a and b:123  456

a=123,b=456

Input the value of a and b:123

456

a=123,b=456

Input the value of a and b:

123 456

a=123,b=456

Input the value of a and b:     123 456

a=123,b=456

Input the value of a and b: 123 456

a=123,b=456

Input the value of a and b:^Z

Press any key to continue

3.2 字符串%s

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

#include

intmain()

{

chara[5],b[5];

inti;

printf("Input the value of a and b:");

while(scanf("%s%s",a,b)!=EOF)

{

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("Input the value of a and b:");

}

return0;

}

运行结果:

0818b9ca8b590ca3270a3433284dd417.png

3.3 字符%c

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

#include

intmain()

{

chara ,b ;

printf("Input the value of a and b:");

while(scanf("%c%c",&a,&b)!=EOF)

{

printf("a=%c,b=%c\n",a,b);

printf("Input the value of a and b:");

}

return0;

}

运行结果:

0818b9ca8b590ca3270a3433284dd417.png

可以看出,在对字符数据输入的时候,由于缓冲区中有回车空格等数据,会导致输入数据比较诡异,为了解决这个问题,有以下方法:

(1) 清空缓冲区

在微软系统中,有一个名为fflush(stdin)的函数,可以用来清空缓冲区,如下例4。

#include

intmain()

{

chara ,b ;

printf("Input the value of a and b:");

while(scanf("%c%c",&a,&b)!=EOF)

{

printf("a=%c,b=%c\n",a,b);

fflush(stdin);

printf("Input the value of a and b:");

}

return0;

}

运行结果:

0818b9ca8b590ca3270a3433284dd417.png

(2)将缓冲区的数据读出来

有的编译系统并没有定义stdin的fflush操作,这个时候,可以把缓冲区中的数据读出来,有如下几种可行的方法:

1) getchar()

将例4中的fflush(stdin);语句换成

char c;

while((c=getchar())!='\n'&&c!=EOF);

运行效果和上面的相同。

2)gets()

char* gets(char* buffer)从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。

要注意的是gets函数可以无限读取,不会判断上限,所以应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。

将例4中的fflush(stdin);语句换成

char c[10];

gets(c);

运行效果也和上面的相同。

#include

#include

#include

char*method1(void)

{

staticchara[4];

scanf ("%s\n", a);

returna;

}

intmain(void)

{

char*h = method1();

printf ("%s\n", h);

return0;

}

运行结果:

ab

cd

ab

Press any key to continue

可以发现,输如两次之后才会输出。这个现象比较诡异,原因如下:

White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input.  Everything else matches only itself. Thus with scanf ("%s\n", a) it will scan for a string followed by optional white space. Since after the first newline more whitespace may follow, scanf is not done after the first newline and looks what's next. You will notice that you can enter any number of newlines (or tabs or spaces) and scanf will still wait for more. However, when you enter the second string, the sequence of whitespace is delimited and scanning stops.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39920629/article/details/116988025

智能推荐

Leetcode 栈刷题心得单调栈用法-程序员宅基地

文章浏览阅读134次。leetcode刷题过程中取得了部分心得:在栈的专题下,主要的考察点是栈先进后出的特性,当遍历一个字符串或者一个列表的时候,可能会出现类似于字符串解码,或者是接雨水之类的问题,这时就需要从后往前出栈,只有栈才能满足这样的特性。因此当出现从后往前输出已经遍历的过的值的时候,就应该考虑使用栈这种数据结构。首先我们最应该掌握的栈的一种用法就是单调栈leetcode中的每日温度接雨水等都是典型的单调栈解题、以接雨水题为例class Solution { public int t_栈刷题

国标流媒体-H265摄像头如何实现网页直播_网页播放h265的流媒体-程序员宅基地

文章浏览阅读2.9w次。介绍目前安防监控行业,基本所有的摄像头都支持H264编码,但是已经有部分摄像头开始支持H265,并且支持H265的摄像机已经越来越多。H265相比H264有着很多优势,是压缩更高,网络传输消耗的带宽更小,相同码率下H265视频更清晰。H264目前已经可以在各种web浏览器、客户端等进行解码播放,但是H265目前还没用得到大部分浏览器的支持,没法直接在web端播放。达到目的为了最终能再各种终端..._网页播放h265的流媒体

CentOS下yum安装FFmpeg_yum偷懒-程序员宅基地

文章浏览阅读606次。一、yum安装FFmpeg1. 最偷懒的方式就是yum安装了,自动解决依赖。不过CentOS系统默认无FFmpeg源,企业版 Linux 附加软件包EPEL源也不包含,需要手动添加yum源配置/etc/yum.repos.d/dag.repo: [dag]name=Dag RPM Repository for Red Hat Enter_yum偷懒

Linux命令之"ping"_如何ping64字节数据的-|是什么-程序员宅基地

文章浏览阅读1.4k次。Linux系统的ping命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”、不能打开网页时会说“你先ping网关地址192.168.1.1试试”。它通过发送ICMP ECHO_REQUEST数据包到网络主机(send ICMP ECHO_REQUEST to network hosts),并显示响应情况,这样我们就可以根据它输出的信息来确定目标_如何ping64字节数据的-|是什么

windows API:ShowWindow_windows api showwindow-程序员宅基地

文章浏览阅读745次。ShowWindow(hwnd,SW_SHOWNORMAL);//显示窗口UpdateWindow(hwnd);//刷新窗口 该句可有可无BOOL ShowWindow( HWND hWnd, //handle to window int nCmdShow //show state);SW_HIDE 、 WS_MAXMIZE_windows api showwindow

ROS2编译运行节点代码_ros2 node 编译和启动-程序员宅基地

文章浏览阅读877次,点赞17次,收藏14次。自用自用。_ros2 node 编译和启动

随便推点

OpenStack-Ocata版+CentOS7.6 云平台环境搭建 — 4.镜像服务(glance)-程序员宅基地

文章浏览阅读223次。节点配置信息说明:控制节点:controller:IP:192.168.164.128hostname&hosts:likeadmin计算加点:Nova:IP:192.168.164.129hostname&hosts:likenode块存储节点:cinder:IP:192.168.164.136hostname&hosts:likebloc..._"option \"verbose\" from group \"default\" is deprecated for removal."

android-调用手机程序打开本地html文件(7.0以上、7.0以下区别)_intent.action_view 打开本地html-程序员宅基地

文章浏览阅读4k次。1、方法,7.0以下直接运行,不用管2、3步 public static void openFile_html(String string) { File file = new File(string); if (!file.exists()) { Log.e(cn.uiautomator.Constants.TAG, "文件不存在:" + string); return; } Int_intent.action_view 打开本地html

Cadence每日一学_08 | OrCAD绘制原理图 - 元器件封装FootPrint信息处理及显示_cadence怎么查看原理图的封装-程序员宅基地

文章浏览阅读6.5k次,点赞7次,收藏63次。在绘制原理图的时候,元器件只显示标号和值,一般不显示封装信息,如图,这篇文章讲述如何处理元器件的封装信息并显示出来。在原理图中元器件的封装信息绘制有三种方法:单个元器件编辑并显示;整个原理图工程批量设置显示元器件的封装(不能设置显示);创建元器件的原理图库时直接设置封装并显示;1.单个元器件编辑并显示填写该元器件封装:设置封装显示出来:2.整个原理图工程批量设置..._cadence怎么查看原理图的封装

51单片机的存储结构_51单片机哈佛结构-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏11次。51单片机的存储结构为哈佛结构,即程序存储器(ROM)与数据存储器(ROM)空间是各种独立的。_51单片机哈佛结构

2021年NOC大赛编程马拉松赛道图形化小低组模拟卷,包含答案_2021年noc编程马拉松 真题-程序员宅基地

文章浏览阅读922次。2020-2021 NOC核桃编程马拉松图形化小低组模拟卷。_2021年noc编程马拉松 真题

云原生|kubernetes|centos7下离线化部署kubesphere-3.3.2---基于kubernetes-1.22.16(从网络插件开始记录)_离线部署kubesphere-程序员宅基地

文章浏览阅读1.7k次。kubesphere的离线化部署指的是通过自己搭建的harbor私有仓库拉取镜像,完全不依赖于外部网络的方式部署。我的kubernetes集群是一个单master节点,双工作节点,总计三个节点的版本为1.22.16的集群。该集群只是初始化完成了,网络插件什么的都还没有安装,本文计划做一个整合,将metricserver,网络插件,storageclass nfs存储插件的部署整合到这一个文章中来,在将kubesphere这些部署依赖安装完毕后,在将镜像推送到我自己搭建的一个带有证书的harbor_离线部署kubesphere