C++ scanf_s()函数的用法以及注意事项
前身——scanf()
有的教材里用的scanf(),其实在目前Visual Studio版本中已经弃用了,用scanf_s()函数代替了。
为什么现在要用scanf_s()
scanf_s()函数是Microsoft公司VS开发工具提供的一个功能相同的安全标准输入函数,从vc++2005开始,VS系统提供了scanf_s()。在调用该函数时,必须提供一个数字以表明最多读取多少位字符。另外,很多带“_s”后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元素,防止hacker利用原版的不安全性(漏洞)黑掉系统。简单的理解,就是scanf_s会比scanf更安全,那么为了安全也需要编程者多传一些参数,这些参数就是变量的长度(占用的字节数)。
很多带“_s”后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元素,有时黑客可以利用原版的不安全性黑掉系统。比如:char d[20];写成scanf_s("%s",d,20);才是正确的,有这个参数20使准确性提高。
注意事项
下列代码
double a,b,c;
scanf_s("%f%f%f",&a,&b,&c);
printf("%f%f%f",a,b,c);
打印结果:
512181,17989019,86000000
可以看到为3个随机数
为啥会这样呢?
scanf_s读%f时,系统会按照4字节长度来读,读完要放到一个4字节的空间位置,也就是一个float所在的位置。那么double有8字节空间,比4字节还大,能不能来放?答案是不能。因为float和double的关系不像int和long的关系那样,简单的在后面增加4字节的位置。float和double有自己专门的数据排列格式,如下:如果读的时候明明是按照float的格式来读,但是却存在double的空间内,并且之后一直按double来操作,那么里面数据的符号位、阶码、尾数就全错位了。除非你在用的时候把每个double强制转换成float来用,但是何必多次一举?同理,如果读用%lf来读,却存在float中,不仅格式错位,而且存储空间也不够,会有数据丢失。所以用scanf_s读的时候,读%f就规规矩矩的放进float中来存,读%lf就放进double中,这样在使用的时候里面的数据才不会错位。在printf的时候,首先C++里面的float其实在使用过程中都是被隐式转换成了double来用。所以你在printf时用float还是double其实是一样的。用%f和%lf都可以。
所以正确的写法是
double a,b,c;
scanf_s("%lf%lf%lf",&a,&b,&c);
总结
(1)printf的%f说明符既可以输出float型又可以输出double型。
根据“默认参数提升”规则(在printf这样的函数的可变参数列表中,不论作用域内有没有原型,都适用这一规则)float型会被提升为double型。因此printf()只会看到双精度数。
(2)scanf对于float类型必须用%f,double必须用%lf
对于scanf,情况就完全不同了,它接受指针,这里没有类似的类型提升。(通过指针)向float存储和向double存储大不一样,因此,scanf区别%f和%lf。
(3)事实上,printf中没有定义%lf,但是很多系统可能会接受它。要确保可移植性,就要坚持使用%f。
要想保留小数位数,请使用(比如保留8位小数):
printf("%.8f",a);
C++ scanf_s()函数的用法以及注意事项的更多相关文章
- Oracle的trim( )、ltrim( )、rtrim( )三个函数的用法及注意事项
学习一下用法整理trim().ltrim().rtrim()的用法 trim().ltrim().rtrim()三个函数有两个作用,分别是: 一.去除字符串前后空格(基本用法) trim(string ...
- memset函数用法及注意事项
头文件 #include<cstring>// or #include<memory.h> ------------------------------------------ ...
- PHP中header函数的用法及其注意重点是什么呢
1.使用header函数进行跳转页面: header('Location:'.$url); 其中$url就是将要跳转的url了. 这种用法的注意事项有以下几点: •Location和":&q ...
- C语言中关于scanf函数的用法
scanf()函数的控制串 函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化 ...
- MYSQL中str_to_date函数的用法
str_to_date(str,format) 函数的用法 str_to_date函数将str转化为日期型的数据,format表示转化后的格式. format参数格式: 常用: %Y 年 %m 月 ...
- Python内置函数reversed()用法分析
Python内置函数reversed()用法分析 这篇文章主要介绍了Python内置函数reversed()用法,结合实例形式分析了reversed()函数的功能及针对序列元素相关操作技巧与使用注意事 ...
- 有关日期的函数操作用法总结,to_date(),trunc(),add_months();
相关知识链接: Oracle trunc()函数的用法 oracle add_months函数 Oracle日期格式转换,tochar(),todate() №2:取得当前日期是一个星期中的第几天,注 ...
- Oracle to_date()函数的用法
Oracle to_date()函数的用法 to_date()是Oracle数据库函数的代表函数之一,下文对Oracle to_date()函数的几种用法作了详细的介绍说明,供您参考学习. 在Orac ...
- js中bind、call、apply函数的用法
最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但 ...
随机推荐
- 以Aliyun体验机为例,从零搭建LNMPR环境(上)
使用云服务器搭建 Web 运行环境,尤其是搭建常见的 LNMPR(Linux+Nginx+MySQL+PHP+Redis) 环境,对于开发人员是必备的职场基本技能之一.在这里,借着搭建我的" ...
- Python脚本打包成exe执行文件
需求 一个教辅目录结构检查工具,目录结构是[书籍]-[章节]-[题目|答案]-[*.jpg],后台有个异步处理的服务,需要强依赖这个目录结构. 书籍解析是单独的pipeline,日志对用户不可见,这里 ...
- 日志文件删除shell脚本
大日志文件切割shell脚本 #!/bin/bash # --------------------------------------------------------------------- # ...
- 用python连接数据库模拟用户登录
使用pycharm下载pymysql库,在终端输入命令: pip install mysql 使用pycharm写登入操作前需要在数据库内添加一些数据,比如用户名和密码 create database ...
- Jenkins教程:使用Jenkins进行持续集成
[注]本文译自: https://www.edureka.co/blog/jenkins-tutorial/ 本文将重点介绍 Jenkins 架构和 Jenkins 构建管道,并向您展示如何在 J ...
- Spring Cloud Alibaba(2)---Nacos概述
Spring Cloud Alibaba(2)---nacos概述 上一篇博客讲了有关 SpringCloudAlibaba的概述,这篇开始讲SpringCloudAlibaba组件之一---Naco ...
- jQuery入门看这一篇就够了
一.选择器 1.基本 名称 用法 描述 #id $("#myDiv"); 根据给定的ID匹配一个元素 element $("div"); 根据给定的元素标签名匹 ...
- Fiddler 菜单功能 Host配置 请求伪造 接口调试
菜单功能: Fiddler工具栏上每个按钮的功能只要鼠标停留在按钮上面就会出现英文描述的功能. 小气泡:增加备注,点击气泡即可对下面捕捉到的会话增加备注(很少使用) Replay回放按钮:较常用,捕捉 ...
- day15.继承
1.什么是继承 继承是一种新建子类的方式,新建的类称之为子类/派生类,被继承的称之为父类/基类 子类会遗传父类的属性 2.为何要用继承 类是解决对象之间冗余问题的 ...
- Day14_79_IO+Properties联合应用
IO+Properties联合应用 - dbinfo文件中可以存放<key=value> - 像dbinfo这样的文件我们叫做配置文件,配置文件的作用是使程序更加灵活 - 一般在程序中可变 ...