C无限循环

时间:2016-01-15 21:36:17

标签: c loops scanf do-while infinite

这是一个简单的程序,用于在几分钟内提示用户他或她的淋浴时间长度(作为正整数,根据需要重新提示),然后打印相同数量的水瓶(作为整数)。

假设淋浴每分钟使用1.5加仑水(192盎司),塑料瓶尺寸为16盎司

我的do-while循环成功拒绝负数和0,但是,如果我输入文本,例如" foo"当在几分钟内提示淋浴的长度时,程序会进入无限循环,永远运行循环并打印"您的淋浴时间(以分钟为单位)?:"

如何改进while条件以避免这种情况?

#include <stdio.h>

int min_to_bottles(int *n);

int main(void)
{
    int minutes;
    int bottles;
    do
    {
        printf("How long is your shower(in minutes)?:");
        scanf("%i", &minutes);
    }
    while (minutes < 1);

    bottles = min_to_bottles(&minutes);

    printf("Equivalent of bottles used per shower is: %i\n", bottles);

}

int min_to_bottles(int *n)
{
    int bottles;
    int oz = 192 * *n;
    bottles = oz/16;
    return bottles;
}

3 个答案:

答案 0 :(得分:4)

始终检查scanf()的返回值:

int result;
do {
    printf("How long is your shower(in minutes)?:");
    result = scanf("%d", &minutes);
    if(result != 1) 
        break;
} while (minutes < 1);

较短的版本(如果只需要一次扫描):

printf("How long is your shower(in minutes)?:");

while ((scanf("%d", &minutes) == 1) && (minutes < 1))
    ;

无需在int min_to_bottles(int *n);中使用指针作为参数:

#include <stdio.h>

int min_to_bottles(int n)
{
    return (192 * n) / 16;
}

int main(void)
{
    int minutes = 0;
    int bottles = 0;

    printf("How long is your shower(in minutes)?: ");

    while ((scanf("%d", &minutes) == 1) && (minutes < 1 || minutes > 100))
        printf("Enter a number between 1 and 100 : ");

    // if(minutes == 0) here means invalid data was entered.
    //    so a check could be done before continuing.

    bottles = min_to_bottles(minutes);

    printf("Equivalent of bottles used per shower is: %d\n", bottles);

    return 0;
}

minutes初始化为0将避免在bottles失败的情况下(例如输入文字)计算带有未定义值的scanf()

答案 1 :(得分:1)

当您输入文本时,它与%i格式说明符不匹配,因此文本卡在输入缓冲区中并且它一直尝试读取相同的内容。

如果你没有得到一个好的匹配,你需要刷新缓冲区。您通过检查scanf的返回值来了解是否是这种情况,这会返回成功匹配的图案数量。

int minutes = 0;
while (minutes < 1)
{
    printf("How long is your shower(in minutes)?:");
    int count = scanf("%i", &minutes);
    if (count < 1) {
        scanf("%*s");   // The * tells scanf to read the input but not assign it to anything
    }
}

答案 2 :(得分:0)

请勿使用scanf("%i",...)

主要问题是,在stdin中,未转换为数字的错误输入仍然是,直到另一个函数读取它为止。由于代码未检查scanf()的返回值,因此minutes的值不明,do ... while (minutes < 1);可以轻松重复循环。

解决方案:读取一行输入,转换为数字,有效数字:

通过阅读输入行

来处理意外的用户输入
char buf[80];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOF();

然后解析缓冲区中的数字。

errno = 0;
char *endptr;
long num == strtol(buf, &endptr, 0);

// detect overflow and no conversiosn
if (errno || buf == endptr) Handle_BadInput();

// Ignore trailing white-space
while (isspace((unsigned char) *endptr) endptr++;

if (*endptr) Handle_BadInput();

验证号码。

#define SHOWER_TIME_MIN (1 /* minute */)
#define SHOWER_TIME_MAX (60 /* minute */)
if (num < SHOWER_TIME_MIN || num > SHOWER_TIME_MAX) Handle_BadInput();

将这一切都放在辅助函数中

示例How to test input is sane