VisualStudio中scanf函数报错的解决方法:scanf与scanf_s

目录

一、前言

二、解决方案

三、scanf_s

1.简要介绍

2.scanf函数为何不安全

3.scanf_s函数的使用方法


一、前言

俗话说:“工欲善其事,必先利其器。”对于想要学习C语言的人来说,选择一个合适的编译器是首要任务。在众多编译器中,Visual Studio(简称VS)应用广泛且知名度高。然而,尽管VS功能强大,但在一些方面对新手不太友好。例如在处理函数时,出于安全性考虑,VS并不提倡使用某些C语言标准中的函数,像scanf函数就属于这一类 ,这无疑给初涉C语言学习的新手设置了一定的障碍。今天,我们就来解决在VS中使用scanf会报错这一问题。

二、解决方案

首先,我们先尝试在VS中使用scanf函数,代码如下:

#include <stdio.h>
int main()
{
	int n;
	printf("请输入n的值:");
	scanf("%d",&n);
	return 0;
}

运行该代码,会得到如下报错信息:   

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.   

我们可以翻译一下这句话,它的中文含义是:

“scanf”:此函数或变量可能不安全。建议使用 scanf_s 函数替代它。若要取消此弃用提示,请使用 _CRT_SECURE_NO_WARNINGS 宏。有关详细信息,请查看联机帮助。

从报错信息中我们就可以知道,用两种解决方案,一是使用VS特有的scanf_s函数,这时VS提供的scanf函数的安全版,详细内容等到第三部分再行介绍,现在,我们先来看看第二种解决方案,使用宏定义,就是对报错信息 _CRT_SECURE_NO_WARNINGS进行宏定义,修改后的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n;
	printf("请输入n的值:");
	scanf("%d",&n);
    printf("n的值为:%d", n);
	return 0;
}

此代码可以正常运行。 

三、scanf_s

1.简要介绍

scanf_s 是 scanf 的一种安全版本,主要用于防止缓冲区溢出等安全问题。它是 Microsoft 提供的扩展函数,符合 C11 标准。与 scanf 相比,scanf_s 需要额外的参数来指定输入缓冲区的大小。

2.scanf函数为何不安全

(1)缓冲区溢出风险:在使用scanf读取字符串时,如果没有对输入字符串的长度进行有效控制,就极易引发缓冲区溢出问题。例如

#include <stdio.h>
int main() {
    char str[10];
    // 若输入超过9个字符(不包含字符串结束符'\0'),就会发生缓冲区溢出
    scanf("%s", str); 
    printf("你输入的内容是:%s\n", str);
    return 0;
}

当用户输入的字符数超出str数组的容量时,多余的字符会覆盖相邻内存空间的数据,这可能导致程序崩溃、产生不可预测的结果,甚至引发安全漏洞,使恶意攻击者能够执行任意代码。

(2)输入类型不匹配:scanf函数根据格式控制字符串来解析输入,如果输入的数据类型与格式控制字符串中指定的类型不匹配,scanf可能无法正确读取输入,还会导致未定义行为。例如:

#include <stdio.h>
int main() {
    int num;
    // 若输入的不是整数,如输入字符'a',就会导致输入类型不匹配
    scanf("%d", &num); 
    printf("你输入的整数是:%d\n", num);
    return 0;
}

当输入非整数时,scanf会将其转换为int类型,但这不仅会使num的值不正确,还可能影响后续scanf函数的执行以及程序的稳定性。(如果输入是浮点数会自动取整舍去小数部分,如果输入是字符类型的话,会打印出一个很奇怪的数字)

3.scanf_s函数的使用方法

在输入整型以及浮点型数据时,scanf与scanf_s使用上并没有区别,代码如下

#include <stdio.h>
int main()
{
	int n;
	printf("请输入n的值:");
	scanf_s("%d",&n);
    printf("n的值为:%d", n);
	return 0;
}

在读取字符串或字符数组时,scanf_s要求明确指定接收缓冲区的大小。这有助于防止输入的长度超出缓冲区大小,提高程序的安全性。使用方法是在变量后面加上其大小,代码如下

#include <stdio.h>
#include <stdlib.h>
int main() {
    char str1[5];
    scanf_s("%s", str1, (unsigned)_countof(str1)); 
	// 注意这里的_countof(str)是一个宏,它的值是sizeof(str),包含在stdlib.h中
    printf("%s\n", str1); 
	char str2[5];
    scanf_s("%s", str2, 5);
	// 数组最后一位需要用来存储字符串结束符\0,所以实际上只能输入4个字符
    printf("%s\n", str2);
    return 0;
}

如果同时输入多个数组,可采用以下写法

#include <stdio.h>
int main() {
    char str1[5]; 
    char str2[5];
    scanf_s("%s %s", str1, 5, str2, 5);
    printf("%s\t%s\t", str2);
    return 0;
}

请勿写成

scanf_s("%s %s", str1, str2, 5, 5);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破阵子44328

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值