scanf_s()dosen';t返回每个输入
我写了一些C代码来读取两个数字和一个运算符:scanf_s()dosen';t返回每个输入,c,console-application,C,Console Application,我写了一些C代码来读取两个数字和一个运算符: int Numberone = 0, Numbertwo = 0; char Op; scanf_s("%d %c %d", &Numberone, &Op, &Numbertwo); 用户输入输入(5+2)后,变量具有以下值:Numberone=5、Op=+和Numbertwo=0。但这是错误的。2号应该是2号。如何改进代码?为什么我的代码错了?您使用的是scanf\u s(请注意\u s),它要求%s或%c类型的每个参数
int Numberone = 0, Numbertwo = 0;
char Op;
scanf_s("%d %c %d", &Numberone, &Op, &Numbertwo);
用户输入输入(5+2)后,变量具有以下值:Numberone=5、Op=+和Numbertwo=0。但这是错误的。2号应该是2号。如何改进代码?为什么我的代码错了?您使用的是
scanf\u s
(请注意\u s
),它要求%s
或%c
类型的每个参数都有一个最大长度参数(例如,请参阅cppreference.com):
scanf\u s
:与scanf
相同,除了%c
、%s
和%[
每个转换说明符需要两个参数(通常的指针和
rsize\t
类型的值,指示接收阵列的大小,
当用%c
读入单个字符时,可能是1
)
因此,您的%c
格式的参数太少,应该是这样的:
scanf_s("%d %c %d", &Numberone, &Op, (rsize_t) 1, &Numbertwo);
首先,您不应该使用
scanf_s()
。Microsoft的编译器告诉您使用它,但最好忽略这一点。而scanf_s()
的设计是为了“更安全”,它要求c
、s
和[
conversions,它是一个专有的Microsoft扩展,因此使用它,您将锁定到Microsoft编译器中。您的实际问题是,您在调用中没有传递缓冲区大小,scanf_s()
假定&Numbertwo
是缓冲区长度
情况甚至更糟,因为C标准还包括一个scanf_s()
。标准版本期望缓冲区大小作为元素计数作为rsize\t
给出,而Microsoft版本期望字节计数作为无符号的,因此它们之间微妙地不兼容!总之,整个函数都是不必要的,只需使用字段宽度就可以使用普通的scanf()
设置安全代码
因为scanf()
不适合从解析错误中恢复,所以您不应该直接将其用于交互式输入,而是读取整行内容并解析(例如使用sscanf()
)。您的代码可能会如下所示:
int Numberone = 0, Numbertwo = 0;
char Op;
char line[512];
if (!fgets(line, sizeof line, stdin))
{
// error reading ...
}
if (sscanf(line, "%d %c %d", &Numberone, &Op, &Numbertwo) != 3)
{
// error parsing ...
}
相应地处理错误。您的输入是什么,实际输出是什么,预期输出是什么。请回答您的问题。scanf\u s()
(微软的)要求缓冲区大小为%c
。不要使用它,使用scanf()
scanf\u(“%d%c%d”,&Numberone,&Op,&Numbertwo)
-->scanf_s(“%d%c%d”,&Numberone,&Op,1,&Numbertwo);
。顺便说一句,对于实际的用户输入,scanf()
和friends无论如何都是错误的选择(但是sscanf()
在从fgets()
获得的一行输入上就可以了)。请参阅我的部分信息。这描述了scanf_()的标准版本
当我的水晶球显示OP正在使用MS功能时…(非常相似,但不幸的是不完全相同)