scanf的使用

  使用scanf需要记住下面两条简单规则:

  •   如果使用scanf来读取某种基本变量类型(%d,%c,%f,%lf)的值,请在变量名之前加上一个&
  •   如果使用scanf把一个字符串(%s)读进一个字符数组中,应不要使用&

  scanf与空白字符(空格、换行符和制表符)

  scanf函数使用空白字符(空格、换行符和制表符)来决定怎样把输入分成几个字段。唯一的例外就是%c,即使下一个字符是空白字符,它也会读取那个字符(即读取字符不忽略空白字符)。

  

  实际上,scanf不是C最常用的输入函数,但是他的用途很多。而getchar和gets(gets(s)没有指明读取的最大字符数,存在缓冲区溢出漏洞,不推荐使用。现多使用fgets(s,MAXN,stdin)代替),它们更适用于读取一个字符和读取包含空格的字符串。

  scanf的返回值

  scanf 函数是有返回值的,它的返回值可以分成三种情况
    1) 正整数,表示成功读入项目的个数。例如执行 scanf("%d%d", &a, &b);  
      如果用户输入"3 4",可以正确输入,返回2(正确输入了两个变量);
      如果用户输入"3,4",可以正确输入a,无法输入b,返回1(正确输入了一个变量)。
    2) ,表示没有读取任何项目,例如当它期望一个数字而我们却键入了一个非数字字符串时就会发生这种情况。如上例,用户如果输入",3 4",则返回0。
    3) EOF,这是在stdio.h里面定义的特殊值(一般#define指令把EOF的值定义为-1),表示输入流已经结束。在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复2次),就表示输入结束;Linux/Unix下使用CTRL+D表示输入结束。

  所以可以使用下面的代码来处理输入:

while (scanf("%s %c %c", str, &oldchar, &newchar) == ) /* 或!= EOF , 但前者更好 */
{
; //处理
}

  为什么前面 scanf 的格式串里面,%s和%c中间需要空格呢?
    那是因为如果没空格的话。。。oldchar输入的就是空格了= =.

  顺便说一下,printf的返回值是输出的字符数,例如,printf("1234")的返回值是4,而printf("1234\n")的返回值是5。

  scanf 和 scanf_s

  • scanf()函数是标准C中提供的标准输入函数,用以用户输入数据
  • scanf_s()函数是Microsoft公司Visual Studio开发工具提供的一个与scanf()功能相同的安全标准输入函数

  从vc++2005开始,VS系统提供了scanf_s()。在调用该函数时,必须提供一个数字以表明最多读取多少位字符。

  原因和区别

  scanf()在读取数据时不检查边界,所以可能会造成内存访问越界:
  例如:分配了5字节的空间但是用户输入了10字节,就会导致scanf()读到10个字节

    char buf[]={'\0'};
scanf("%s", buf);

  如果输入1234567890,则5以后的部分会被写到别的变量所在的空间上去,从而可能会导致程序运行异常。

  以上代码如果用scanf_s()则可避免此问题:

    char buf[]={'\0'};
scanf_s("%s",buf,); //最多读取4个字符,因为buf[4]要放'\0'

  如果输入1234567890,则buf只会接受前4个字符

  注: scanf_s最后一个参数n是接收缓冲区的大小(即buf的容量),表示最多读取n-1个字符.

  PS: 很多带“_s”后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元素,防止hacker利用原版的不安全性(漏洞)黑掉系统。

scanf与scanf_s的更多相关文章

  1. C语言杂谈(一)scanf()、scanf_s()与错误 C4996

    错误 C4996 初学C语言时,第一个接触到的I/O函数便是scanf()了.但在高版本的 Visual Studio (包括但不限于2015.2013.2012)编译代码时,却会出现意想不到的错误. ...

  2. scanf与scanf_s的区别

    scanf()函数是标准C中提供的标准输入函数,用以用户输入数据 scanf_s()函数是Microsoft公司VS开发工具提供的一个功能相同的安全标准输入函数,从vc++2005开始,VS系统提供了 ...

  3. scanf和scanf_s在VS2013中的使用

    转载:https://www.cnblogs.com/liuchaojiayou/p/4418215.html 在VS2013中,每次使用scanf都会报错:This function or vari ...

  4. scanf()和scanf_s()

    在最初的C语言中,原版的输入就是scanf("<格式化字符串>",<地址表>) ANSI C中没有scanf_s(),只有scanf(),scanf()在读 ...

  5. C语言中的scanf与scanf_s 以及循环输入的问题解决

    Scanf 在标准C中,scanf提供了键盘输入功能. scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中.与printf函数相同,C语言也允许在使用scanf函数之前不必包含s ...

  6. 在C语言中使用scanf语句时遇到的问题总结

    在使用visual studio2013编写c语言代码时,遇到了这样的几个小问题,进行如下的总结. 1, 关于使用scanf语句报错的解决方案1 #include <stdio.h> in ...

  7. printf和scanf整理(后续填补)

    scanf和printf头文件:<stdio.h> 1.%d.%3d.%03d.%-3d区分 %d:以十进制形式输出整数(int) %3d:指定宽度为3,不足的左边补空格 %03d:一种左 ...

  8. vs2017中的scanf_s

    在visual studio 2017中格式化输入函数不同于其他c/c++编译器使用scanf,而是使用scanf_s. scanf_s相比较于scanf来说更安全,因为使用scanf_s函数需要有一 ...

  9. 【九度OJ】题目1096-二分查找

    题目1069:查找学生信息 这篇文章中提到的问题主要是由于调试平台Visual Studio和测试平台Online Judge的一些小差异,造成在Visual Studio中调试通过的代码,在输入OJ ...

随机推荐

  1. css制作三角形

    #triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid tr ...

  2. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

  3. 在Entity Framework中使用事务

    继续为想使用Entity Framework的朋友在前面探路,分享的东西虽然技术含量不高,但都是经过实践检验的. 在Entity Framework中使用事务很简单,将操作放在TransactionS ...

  4. 解决CSS小于12px的文字在谷歌浏览器显示问题

    做前端设计的人经常要接触CSS方面的问题,估计有不少人会遇到Chrome谷歌浏览器中CSS设置字体小于12px显示不正常,强创网络在做magento模板过程中就遇到了,起初以为是自己写的CSS的问题, ...

  5. mysql [ERROR] Can't create IP socket: Permission denied

    /*************************************************************************** * mysql [ERROR] Can't c ...

  6. 用vs2008打开vs2012项目

    1 使用记事本打开*.sln解决方案文件,将Visual Studio 2012改为Visual Studio 2008 将版本号改为9.00 2 打开扩展名为*.csproj的项目文件,修改为 To ...

  7. [转载] C++ typedef 用法详解

    typedef的语法描述 在现实生活中,信息的概念可能是长度,数量和面积等.在C语言中,信息被抽象为int.float和 double等基本数据类型.从基本数据类型名称上,不能够看出其所代表的物理属性 ...

  8. springmvc学习笔记---idea创建springmvc项目

    前言: 真的是很久没搞java的web服务开发了, 最近一次搞还是读研的时候, 想来感慨万千. 英雄没落, Eclipse的盟主地位隐隐然有被IntelliJ IDEA超越的趋势. Spring从2. ...

  9. HDU 4311 前缀和

    Description It has been ten years since TJU-ACM established. And in this year all the retired TJU-AC ...

  10. JavaWeb学习记录(十三)——商城购物之添加订单的数据库级联操作

    一.方法实现 private JdbcTemplate jdbcTemplate = new JdbcTemplate(DBConn.getDataSource()); @SuppressWarnin ...