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. Objective-c---分类 、 扩展 、 ARC

    1 分类练习 1.1 问题 分类是Objective-C提供的一种类的补充和扩展方法,补充和扩展的每个部分被称为分类,分类本质上是类的一部分.提出分类概念的作用有两个:一是分解大的代码,提高程序可读性 ...

  2. ImportError: No module named 'commands'

    /*********************************************************************** * ImportError: No module na ...

  3. 【ajax】FormData

  4. 【题解】【位操作】【Leetcode】Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  5. js 实现复制到剪切板 复制按钮兼容各大浏览器

    zeroclipboard官网:https://github.com/zeroclipboard/ZeroClipboard 下载压缩包,得到两个“ZeroClipboard.js”和“ZeroCli ...

  6. iOS学习笔记---c语言学习第七天

      结构体 结构体是一种自定义的数据类型 struct 结构体名 { 类型说明符  成员名: … 类型说明符  成员名: }: #import <Foundation/Foundation.h& ...

  7. HOG特征提取分析(转)

    背景引言 方向梯度直方图(Histogram of Oriented Gradient,HOG)是用于在计算机视觉和图像处理领域,目标检测的特征描述子.该项技术是用来计算图像局部出现的方向梯度次数或信 ...

  8. 12. Integer to Roman

    Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...

  9. 2015GitWebRTC编译实录9

    2015.07.20 neteq 编译通过注意不要引用tools目录里的内容 [1347/1600 ] CXX obj /webrtc/modules/audio_coding/neteq/neteq ...

  10. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...