在下面的代码中输入' a'价值为3.4(即浮动)它给我回答垃圾价值,甚至不允许我进入' b'价值,当我给出' a'价值为3和' b'价值为2.3(即浮动)它被接受并给我答案5而不是垃圾。
我的问题是为什么第二个参数没有进行类型检查;为什么只有第一个参数?
如果我给3,3.5代码工作更清楚但是为什么我不能输入3.5,3?
int sum(int k,int l)
{
int s= k+l;
return s;
}
void main()
{
int a,b,k;
printf("enter the numbers");
scanf("%d",&a);
scanf("%d",&b);
k= sum(a,b);
printf("the value of sum is %d", k);
}
PS:我在quora上看到了这个问题。我对那里提供的答案不满意。我认为这是提出这个问题的最好地方。
答案 0 :(得分:2)
类型检查不是程序中的问题。类型检查在编译时发生;您看到的行为发生在运行时。 printf
,scanf
和类似函数的编译时类型检查存在问题,我将在下面讨论,但这不适用于您的程序,它会传递正确类型的参数同时scanf
和printf
。不过,我将在下面讨论这个问题(因为我在仔细阅读你的问题之前写过这个问题)。
您拨打scanf
两次以(尝试)读取两个int
值。输入为3.4
,这是float
或double
的有效输入。那么scanf
对此做了什么?
scanf
格式的 "%d"
读取的输入格式类似于可选的有符号整数文字,当它看到任何与该格式不匹配的内容时停止。因此,第一个scanf
只读取3
并停在.
。它不认为.
可能是小数点,因为您没有要求它读取浮点值。 .
不是错误,只是scanf("%d", ...)
正在寻找的输入的结尾。
第二个scanf
尝试读取另一个int
值,但现在输入流中的第一个字符是.
,它不能是有效整数字的一部分,所以它失败。 (检查scanf
的返回值会告诉您;它会返回成功扫描的项目数。)
你应该总是检查输入函数返回的结果并编写代码来处理失败(即使只是通过用错误消息中止程序来处理它)。
更安全的读取数字输入的方法是使用fgets()
一次读取整行,然后使用sscanf
解析内存中的行。这也可能有问题,但它不会让以后的调用等待读取无效的输入字符(除非你有一个很长的输入行)。阅读fgets
和sscanf
的文档以获取更多信息 - 再次,请务必检查它们返回的结果,以便检测输入错误。
printf
和scanf
都是可变参数函数,这意味着它们可以接受可变数量和类型的参数。
例如,printf
的声明是:
int printf(const char *format, ...);
这意味着对printf
的调用中的第一个参数将根据参数类型进行检查,但在编译时不会检查零个或多个后续参数。这为您提供了极大的灵活性,但代价是编译=时间检查。几乎完全取决于您确保所有以下参数都是格式字符串指定的类型。如果传递错误类型的参数(例如printf("%d\n", 1.5)
),则不一定会收到错误消息;相反,行为是未定义的。
scanf
类似,但格式字符串的语义不同(大多数参数是指针而不是要打印的值)。
如果格式字符串是字符串文字,某些编译器(特别是gcc)将为您做额外的检查,但这不是必需的,其他编译器可能不会这样做。
顺便提一下,您发布的代码缺少必需的
#include <stdio.h>
和void main()
应为int main(void)
。如果您正在使用建议使用void main()
的书籍或教程,则可能是由不熟悉C语言的人编写的。找一个更好的。
答案 1 :(得分:1)
当scanf遇到变量&#39; a&#39;正如你所说的3.4。它以整数形式读取3并以小数形式停止。然后,.4将在下一次调用时读作双精度数。它在第二个输入是浮点数时有效,因为它会丢弃小数并且不会再次调用,因此会忽略其余的小数。 如评论中所述,请阅读有关scanf的内容并对代码进行一些更改。
答案 2 :(得分:-2)
我认为你应该添加&#34; getchar()&#34;在scanf方法之后,按Enter键时,&#39; / n&#39;会给 下一个参数。 这只是我的观点。
void main()
{
int a,b,k;
printf("enter the numbers");
scanf("%d",&a);
getchar();/* the /n is last in stdin*/
scanf("%d",&b);
k= sum(a,b);
printf("the value of sum is %d", k);
}