您的位置:首页 > 其它

关于vs中scanf函数的一点说明

2015-12-13 12:08 316 查看
众所周知,由于安全原因,vs2012版本及其以上会出现scanf函数报错的情形,编译时便会提示如下错误:

error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

错误解释:

微软该种类型报错主要因为那些C库的函数,很多函数内部是不进行参数检测的(包括越界类的),微软担心使用这些会造成内存异常,所以就改写了同样功能的函数,改写了的函数进行了参数的检测,使用这些新的函数会更安全和便捷。关于这些改写的函数你不用专门去记忆,因为编译器对于每个函数在给出警告时,都会告诉你相应的安全函数,查看警告信息就可以获知,在使用时也再查看一下MSDN详细了解。

一般来说,直接解决该问题方法有三种:

方法一:将原来的旧函数替换成新的 Security CRT functions,即替换成为新的函数scanf_s,但是scanf_s函数比scanf函数多了一个参数,即读取个数参数。例如scanf从输入流中读取一个字符类型字节,scanf("%c",&ch),则若使用scanf_s需改为scanf_s("%c",&ch,1);

方法二:以下方法的原理为屏蔽这个错误:

1. 在预编译头文件stdafx.h里(注意:一定要在没有include任何头文件之前)定义下面的宏:

#define _CRT_SECURE_NO_DEPRECATE

2. 或声明 #param warning(disable:4996)

3. 更改预处理定义:

项目->属性->配置属性->C/C++ -> 预处理器 -> 预处理器定义,增加:

_CRT_SECURE_NO_DEPRECATE

第三种注意更改预处理定义时若在最后面加上该句话,需在这句话前面即未加之前最后面加上一个分号(在英文输入法模式下哦~)。

方法三:方法二没有使用更加安全的 CRT 函数,显然不是一个值得推荐的好方法,但我们又不想一个一个地改函数名,这里还有一个更简便的方法:

在预编译头文件 stdafx.h 里(同样要在没有include任何头文件之前)定义下面的宏:

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

在链接的时候便会自动将旧函数替换成 Security CRT functions 。

注意:这个方法虽然使用了新的函数,但是不能消除警告(原因见红字),你还得同时使用方法二(-_-)。即实际应在预编译头文件 stdafx.h 里加入下面两句:

#define _CRT_SECURE_NO_DEPRECATE

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

虽然解决了该报错问题,但是很多童鞋会发现运行时,scanf函数虽然并未报错,即该程序正确执行,但是在输入时,会发现scanf函数跳过输入字符的原因,即你没有办法输入的问题,这是为什么呢?

因为scanf只是读入一个字符,而你在输入时实际上输入的是:字符+回车(Enter),Enter产生的"\n"也在输入缓冲区中,下次调用 scanf时就会直接读到 它而不是等待你再次输入!所以我们不提倡使用 scanf("%c", ...),特别是不提倡把它用在循环中。这也是微软改写该类函数的原因,那么如何解决呢?

一把来说,主要方法有四种:

方法一:只要再加一句scanf就行了。

方法二:使用函数fflush,清除流,就是在每个接收字符的scanf语句前面,加上fflush(stdin);

方法三:将 scanf("%c", &ch); 修改为: scanf(" %c", &ch); /*在%前加上一个空格*/

方法四:将 scanf("%c", &ch); 修改为: scanf("%c%*c", &ch); %*c是跳过一个输入字符的意思.这个是scanf的一个语法.就是在%和格式字符之间加一个*号就可以跳过这个输入数字.比如当执行语句:scanf("%c,%*c,%c",&a,&b);时,我输入m,n,p三个字母后,a的值为m,b值为p,n被跳过了。

个人认为第三种方法最为简便而且有效哦!O(∩_∩)O
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: