C无限做while循环
C infinite do while loop
这是一个简单的 class 程序,它提示用户以分钟为单位的淋浴时长(作为正整数,根据需要重新提示),然后打印等量的淋浴时间瓶装水(整数)。
假设淋浴器每分钟使用 1.5 加仑水(192 盎司),塑料瓶大小为 16 盎司
我的 do-while 循环成功地拒绝了负数和 0,但是,如果我在提示输入淋浴时长(以分钟为单位)时输入诸如 "foo" 之类的文本,程序将永远进入无限循环运行 循环和打印 "How long is your shower(in minutes)?:"
有什么想法可以改进 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;
}
始终检查 scanf()
的 return 值:
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
将避免在 scanf()
失败的情况下使用未定义的值计算 bottles
(例如通过输入文本)。
当您输入文本时,它与 %i
格式说明符不匹配,因此文本会卡在输入缓冲区中,并且会一直尝试读取相同的内容。
如果你没有得到一个好的匹配,你需要刷新缓冲区。您可以通过检查 scanf
的 return 值来判断是否是这种情况,return 表示成功匹配的模式数。
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
}
}
不要使用scanf("%i",...)
。
主要问题是未转换为数字 的错误输入会保留在 stdin
中 直到另一个函数读取它。由于代码没有检查 scanf()
的 return 值,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
这是一个简单的 class 程序,它提示用户以分钟为单位的淋浴时长(作为正整数,根据需要重新提示),然后打印等量的淋浴时间瓶装水(整数)。
假设淋浴器每分钟使用 1.5 加仑水(192 盎司),塑料瓶大小为 16 盎司
我的 do-while 循环成功地拒绝了负数和 0,但是,如果我在提示输入淋浴时长(以分钟为单位)时输入诸如 "foo" 之类的文本,程序将永远进入无限循环运行 循环和打印 "How long is your shower(in minutes)?:"
有什么想法可以改进 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;
}
始终检查 scanf()
的 return 值:
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
将避免在 scanf()
失败的情况下使用未定义的值计算 bottles
(例如通过输入文本)。
当您输入文本时,它与 %i
格式说明符不匹配,因此文本会卡在输入缓冲区中,并且会一直尝试读取相同的内容。
如果你没有得到一个好的匹配,你需要刷新缓冲区。您可以通过检查 scanf
的 return 值来判断是否是这种情况,return 表示成功匹配的模式数。
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
}
}
不要使用scanf("%i",...)
。
主要问题是未转换为数字 的错误输入会保留在 stdin
中 直到另一个函数读取它。由于代码没有检查 scanf()
的 return 值,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