我正在编写一个C程序,它从键盘读取未定义的整数。无限。该程序有一个循环,用scanf读取整数,并存储要显示的最低和最高值。如果用户输入负数或非整数,则循环结束并显示信息(最低和最高值)。
注意:我不想在“ISDIGIT”或“FGET”等功能中使用内置功能。不知道它们是什么,我不想“欺骗”。
我发现我的EOF值是-1。我尝试在我的循环中放入“while(scanf(”%d“,& num)> -1)”。如果你输入一个char(继续阅读并且永远不会结束循环),这就什么都不做。如果你输入一个双重负数如“ - 2”,它有时会打破循环。无论如何它都不起作用。
我的问题是我的程序会将行为与当前代码混淆。有时它不会保持或读零。有时它只存储并显示第二个最高值。在输入字符或符号以触发循环结束后,有时它会显示第二个到最高或最低值。其他时候它工作得很好。我尝试了一些更符合逻辑的语句,如果它不等于1且小于1,则强制min为零,但这也不起作用。
奇怪行为的一个例子......
输入一些整数值,EOF退出...
0
1
2
3
4
ë
不是int
最小值为0
,最大值为3
任何人都可以解释为什么会发生这种情况并提供解决方案和/或提示吗?我一直在搜索和谷歌搜索几个小时。
谢谢!
这是我的代码......
int min;
int max;
int num;
printf(" Enter some integer values, EOF to quit...\n");
scanf("%d\n", &num);
min = max = num;
while(scanf("%d", &num) == 1)
{
if(num > max)
{
max = num;
}
else if(num < min)
{
min = num;
}
scanf("%d\n", &num);
}//while(scanf("%d", &num) == 1);
printf(" not an int \n");
printf(" The minimum value is %d\n", min);
printf(" and the maximum value is %d\n", max);
答案 0 :(得分:1)
您可以使用scanf
使其“正常”,但它不会真正起作用。 scanf
is ill advised for a large number of reasons
例如,假设我们这样做了:
printf("Enter some integers, or ctrl-D to quit.\n");
while(scanf("%d", &input) != EOF) {
if(input > max) {
max = input;
}
else if(input < min) {
min = input;
}
}
似乎合理,scanf
如果没有任何输入则返回EOF
。它似乎有效。
$ ./test
Enter some integers, or ctrl-D to quit.
230
-238
5
max: 230, min: -238
但是,如果我们给它一些不是数字的东西呢?
$ ./test
Enter some integers, or ctrl-D to quit.
230
-238
5
ldsfkj
^D
^D
^D
^C
为什么不停止?如果它无法读取所需内容, 将其保留在stdin缓冲区 。它尝试读取ldsfkj
,失败因为它不是整数,返回0(不是EOF)因为它与任何东西都不匹配。但是ldsfkj
仍然在缓冲区中,所以当它再次循环时它再次读取它并再次失败。这是scanf
中的一个重大缺陷。
好的,如果我们检查它扫描了什么怎么办?
while(scanf("%d", &input) == 1) {
...
}
再次,似乎工作得很好......直到我们输入不是整数的东西。然后它就会停止,因为scanf
失败了。这不是我们想要的行为。
$ ./test
Enter some integers, or ctrl-D to quit.
2039
-203
23.4
max: 2039, min: -203
安全的做法是逐行读取输入并使用sscanf
处理它。这将读取线与解析线分开。我们不必担心卡在缓冲区中的问题,我们可以通过解析做更多的事情,比如给用户一个错误信息。
printf("Enter some integers, or ctrl-D to quit.\n");
char line[256];
while(fgets(line, 256, stdin) != NULL) {
if( sscanf(line, "%d", &input) != 1 ) {
puts("Sorry, I don't understand that");
continue;
}
if(input > max) {
max = input;
}
if(input < min) {
min = input;
}
}
请注意,我们始终同时检查min
和max
,因为input
现在可以同时使用。{/ p>
请注意,我们使用的是fgets
而不是gets
,因为gets
不会将其输入限制为字符串的大小,因此很容易溢出其缓冲区。
第二部分是使min / max代码更简单。不是将第一个数字作为min和max的特殊情况,而是将最大可能的整数分配给min
,将最小的整数分配给max
。然后第一个输入保证为最小值和最大值。这些限制可以在limits.h中找到。
这就是一起。
#include <stdio.h>
#include <limits.h>
int main() {
int min = INT_MAX;
int max = INT_MIN;
int input;
printf("Enter some integers, or ctrl-D to quit.\n");
char line[256];
while(fgets(line, 256, stdin) != NULL) {
if( sscanf(line, "%d", &input) != 1 ) {
puts("Sorry, I don't understand that");
continue;
}
if(input > max) {
max = input;
}
if(input < min) {
min = input;
}
}
printf("max: %d, min: %d\n", max, min);
}
该计划有一个小故障。我把它作为练习让你找到并修复它。