scanf()函数的原理

想象输入设备(键盘)连接着一个叫“缓冲”的东西,把缓冲认为是一个字符数组。

当你的程序执行到scanf时,会从你的缓冲区读东西,如果缓冲区是空的,就阻塞住,等待你从键盘输入。

现在假设你的缓冲区里有:abcd\n1234\n (其中\n是回车符)执行:scanf("%s",name);的时候,由于scanf是读数据直到看见空白符(空白符:指空格符、制表符、回车符)就停止的输入函数。所以执行后,把abcd存到了name中。缓冲区于是变成了 : \n1234\n

接下来的执行就有问题了,如果遇到了:scanf("%d",&number);怎么办?因为遇到了回车符,它并不是一个数字,所以scanf还有一个特性,就是忽略先导的空白符。不管是有几百个回车也好,几万个空格也罢,只要它们连续地出现在缓冲区的开头,就统统忽略他们。然后再读有意义的字符。于是1234被读入number。

回到刚刚,当缓冲区还是:\n1234\n的时候,如果遇到了:scanf("%c",&sex);应该怎么办呢?你说,那好办呀,不是说了忽略前导空白符吗?跳过回车读’1’呀!想法是好的,可这只针对你的程序这一种情况。如果我编写的程序就是统计用户输入了多少个回车呢?所以对scanf来讲跳过前导空白符有个例外,当参数是%c的时候,就把缓冲区的第一个字符返回回去,不管是什么。

这样的设计就有个问题,scanf对不同的参数表现出来的特性不一样。得承认,这是个缺陷,但不是说这样不好。

这样的设计至少把发现所有字符的机会交给了用户,设计者这样想:如果程序员使用了scanf("%c",…),那他就有必要知道这函数能把回车符读出来,至于程序员对回车符感不感兴趣,那就看他了,不感兴趣的话,程序员也一定知道该怎么处理。回到你的程序里。

当执行scanf("%s",name)的时候,要求你从键盘输入,于是你输入了"abc",然后“回车”。缓冲区里自然而然地是:abc\nscanf把abc拿走了,留下了\n,缓冲区里现在就剩下\n于是,下一个scanf ("%c",&sex); 想当然地读取了\n

  • 关于scanf忽略前导空白符这一点,可以这样验证:

    写个程序,用scanf()读数据,只要不是%c就行。然后输入的时候,随便输入回车、空格、制表符,然后“回车”确认。会发现程序依然提示等待你输入。就是因为它忽略掉所有前导空白符之后发现缓冲区是空的!于是乖乖地阻塞住,等待你输入。
  • 关于scanf是直到看见空白符结束读取这一点,如果你是初学C的话,那么很快你就会遇到另一个函数,叫gets()。

    程序里如果我们想一次读入一个英文句子:I am a student.如果你用scanf读的话,只能读出"I",想读出后面的东西要不断调scanf。此时需要用gets,这个函数不管是什么一律读进来,直到遇到回车符才停下。总之,各有各的用途,全都熟悉之后,才能在恰当的时候恰当地使用。

    以上转自:http://blog.pfan.cn/katwood/53198.html

    scanf中\n问题----------------------------------------------------------------------------------

    scanf("%d\n",&num);

    scanf函数的第一个参数指定了后面变量读取的格式,这样写的话会按照 :

    数字 回车

    的格式读取,读到回车之后会继续读下一行,如果缓冲区没有东西scanf就会阻塞在那里,直到用户有输入

    以至于有时候会遇到再输入一行才能有返回的情况

scanf用法及scanf中有\n的问题的更多相关文章

  1. scanf 用法及陷阱(转)

    函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设备( ...

  2. c语言:scanf(" %c",&bla); scanf("%c",&bla); 语句差别

    %前有空格,%没有空格 scanf("%c",&c) 与 scanf(" %c",&c),后者只是在%前多了个空格,似乎没有什么区别,但使用起来 ...

  3. scanf/sscanf %[]格式控制串的用法(转)

    scanf/sscanf %[]格式控制串的用法 scanf中一种很少见但很有用的转换字符:[...]和[ ^...]. #include<stdio.h> int main() { ch ...

  4. 羽夏闲谈—— C 的 scanf 的高级用法

    前言   今天看到博友发了个有关scanf的使用的注意事项,就是讨论缓冲区残存数据的问题,用简单的代码示例复述一下: #define _CRT_SECURE_NO_WARNINGS #include ...

  5. 数据类型、常量、变量、printf、scanf和运算符

    数据类型 常量 变量 printf函数介绍 scanf函数介绍 运算符 数据类型 数据类型是指数据在内存中存储的方式. C语言中有5大数据类型:基本类型.构造类型.指针类型.空类型.定义类型. C语言 ...

  6. 字符串处理scanf("%d%*c",&n);

    "*"表示该输入项读入后不赋予任何变量,即跳过该输入值.这在减小内存开支上面还是有一点用处的,不需要的字符直接跳过,免得申请没用的变量空间 你的例子中的%*c的作用是读入'\n', ...

  7. 关于cin,getchar(),scanf()的注意事项(转)

      问题描述一:(分析scanf()和getchar()读取字符) scanf(), getchar()等都是标准输入函数,一般人都会觉得这几个函数非常简单,没什么特殊的.但是有时候却就是因为使用这些 ...

  8. scanf()/getchar()和gets()深入分析

    C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数 ---------------------------------------------------- | ...

  9. 【学习笔记】【C语言】scanf函数

    1. 简介 这也是在stdio.h中声明的一个函数,因此使用前必须加入#include <stdio.h>.调用scanf函数时,需要传入变量的地址作为参数,scanf函数会等待标准输入设 ...

随机推荐

  1. [炼丹术]UNet图像分割模型相关总结

    UNet图像分割模型相关总结 1.制作图像分割数据集 1.1使用labelme进行标注 (注:labelme与labelImg类似,都属于对图像数据集进行标注的软件.但不同的是,labelme更关心对 ...

  2. [Git]解决Permission denied, please try again问题

    在gitlab上传项目的时候出现Permission denied, please try again问题, 网上有很多解释,但是都没能解决我的问题,后来经过自己尝试成功了,这里把经验分享给大家. 在 ...

  3. Android studio 报错 Unable to resolve dependency for ‘:app@releaseUnitTest/compileClasspath‘:

    出现报错: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not find any ...

  4. ActiveMQ基础教程(二):安装与配置(单机与集群)

    因为本文会用到集群介绍,因此准备了三台虚拟机(当然读者也可以使用一个虚拟机,然后使用不同的端口来模拟实现伪集群): 192.168.209.133 test1 192.168.209.134 test ...

  5. Zookeeper基础教程(一):认识Zookeeper

    引用百度百科的话 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服 ...

  6. Sentry 企业级数据安全解决方案 - Relay 运行模式

    内容整理自官方开发文档 Relay 可以在几种主要模式之一下运行,如果您正在配置 Relay server 而不是使用默认设置,那么事先了解这些模式至关重要. 模式存储在配置文件中,该文件包含 rel ...

  7. OpenIddict 登录及详细流程解析

    GitHub上实例都是集成了Identity来实现,我这里去掉了相关东西,实现自定义的登录满足自己的结构要求 服务端配置添加数据库服务以及定时任务服务 builder.Services.AddDbCo ...

  8. spring boot热部署 -- 实现 后端java热更新 -- 详细操作 【idea 的 JRebel破解】

    1.前言 上一随笔写了如何使得spring boot热更新前端 ,但后端java部分无法热更新. 对于Java热更新,以前常使用  springloaded  ,但是缺点 和bug很多 无法实现真正意 ...

  9. Word2010邮件合并制作成绩单

    原文链接: https://www.toutiao.com/i6488941003494392333/ 准备数据源: 选择"邮件"选项卡,"开始邮件合并"功能组 ...

  10. 【漏洞复现】CVE-2022–21661 WordPress核心框架WP_Query SQL注入漏洞原理分析与复现

    影响版本 wordpress < 5.8.3 分析 参考:https://blog.csdn.net/qq_46717339/article/details/122431779 在 5.8.3 ...