只是一个简单的程序,取10个整数,并告诉我哪个是最大的。这是我第一次使用C语言,尽管我之前使用过Java,Python和Ruby编程。如果输入字符而不是整数,它只会进入无限循环。它将当前变量设置为-8995460(或类似的东西),然后只是无限重复该广告。我只是在某个地方犯了一个愚蠢的错误,或者这是我对C不了解的事情?
int main(void)
{
int counter = 0;
int largest = 0;
while (counter != 10)
{
int current;
printf("%s", "Enter non-negative number: ");
scanf_s("%d", ¤t);
if ((current >= 0) && (isdigit(current)))
{
if (current > largest)
{
largest = current;
}
counter++;
}
else
{
puts("Invalid number. Number must be positive. \n");
}
}
printf("%d", largest);
}
答案 0 :(得分:3)
您读取整数而不是字符。 isdigit
检查字符是否为数字。如果current
是一位数的数字,那么凭借一位数的数字肯定是一个数字"。
因此,isdigit
函数将始终返回0
(除非您输入与数字的当前字符编码值对应的十进制值),在C中等于false,所以你永远不会增加counter
。
对于您的问题,我会使用"%u"
格式来scanf
读取无符号的十进制数,并检查scanf
返回的内容以查看输入是否正确。
请注意,如果输入不正确,它将留在输入缓冲区中,以便下次调用scanf
,除非您将其删除。删除它的唯一可移植方法是逐字符号读取,直到您读取换行符。
答案 1 :(得分:1)
isdigit()用于检查字符的ASCII码是否为 0-9的数字的等效ASCII码。你应该只使用它 带有字符变量。
scanf(“%d”,& current)将始终读取整数到变量current。你不需要检查它。如果你 输入一个字符,你得到一个无限循环,因为scanf() 不能将字符存储在任何变量中,即它没有达到预期的效果。
你可以通过写作解决无限循环问题 scanf(“%s”,& str)其中str是字符数组(字符串)而不是scanf_s(“%d”,& current)。 现在你可以检查第一个字符是否是isdigit(str [0])。 如果不是,则跳过其他数字 使用atoi()函数将其转换为数字。
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#define BUF_LEN 256
int main()
{
int counter = 0;
int largest = 0;
while (counter != 10)
{
char str[BUF_LEN];
printf("%s", "Enter non-negative number: ");
scanf("%s", str);
if (isdigit(str[0]))//If first character is a digit then we asume that str contains a valid number. You should actually check it for all the characters in the string.
{
int current = atoi(str);//Convert string to integer (ASCII to Integer).
if (current > largest)
{
largest = current;
}
counter++;
}
else
{
puts("Invalid number. Number must be positive. \n");
}
}
printf("%d", largest);
}
答案 2 :(得分:0)
As @SomeProgrammerDude pointed out,isdigit
检查字符是否为数字。你传给它一个整数。它会将该整数解释为一个字符,因此它会认为10
是换行符,43
是+
。如果你给它50
它将会通过,因为它的字符是2
。
要检查scanf
是否有整数,请不要检查current
,因为如果scanf
失败,它将包含垃圾。相反,请检查scanf
的返回值,它会告诉您匹配了多少项。
int counter = 0;
int largest = 0;
// It's safer to check for X < BOUND than X != BOUND in case
// X happens to go over the BOUND.
while (counter < 10) {
int current;
printf("%s", "Enter non-negative number: ");
// What if `scanf` didn't get a number?
if( scanf("%d", ¤t) != 1 ) {
puts("That doesn't look like a number");
}
// What if it isn't positive?
else if( current < 0 ) {
puts("Invalid number. Number must be positive. \n");
}
// Now that all the error conditions have been checked...
else {
if (current > largest)
{
largest = current;
}
counter++;
}
}
printf("%d", largest);
但仍有问题。如果得到无效的数字,代码将进入无限循环。这是many, many, many problems with scanf
中的一个,特别是this one。
问题是scanf
不会读取行,它会读取尽可能多的内容。如果它读不出那么多,它就把它放在缓冲区上。如果scanf
失败,则会在stdin
上留下输入。当您再次阅读时,您将阅读相同的输入并再次失败。如果该行有任何额外输入,例如10 foo
它会读取10
,然后将foo
留在缓冲区上,以便在下一次调用scanf
时读取。 / p>
一般解决方案是逐行读取输入并解析该行。使用fgets
读取行,sscanf
扫描字符串。
int counter = 0;
int largest = 0;
char line[255];
while (counter < 10) {
int current;
printf("%s", "Enter non-negative number: ");
fgets(line, sizeof(line), stdin);
if( sscanf(line, "%d", ¤t) != 1 ) {
puts("That doesn't look like a number");
}
...and the rest is the same...
}
这可以保证你永远不会陷入无限循环。虽然如果输入大于line
,它可能需要多次遍历fgets
才能获得所有输入。