通过消除C中if
语句中的重复条件,是否有更好的方式编写以下代码?
while (n < 0) {
printf("Enter a positive integer: ");
scanf("%d", &n);
if (n < 0) {
printf("Error: please enter a positive integer\n");
}
}
谢谢。
答案 0 :(得分:5)
在给出正确输入后,只需重新处理循环中断。这样,检查仅执行一次:
while (1)
{
printf("Enter a positive integer: ");
scanf("%d", &n);
if (n >= 0)
break;
printf("Error: please enter a positive integer\n");
}
而且,正如注释中所指定的那样,优化的编译器应该能够自行反转循环。
答案 1 :(得分:1)
以下示例是本着人们应该了解该语言可用内容的精神提出的。 1 Frankie_C’s answer中显示了我通常编写代码的方式。正如某些人指出的那样,优化通常会使这种简单的情况不值得担心,但是问题不仅仅限于像n < 0
这样的简单评估;而是该测试可能是对较复杂的条件进行一些昂贵评估的函数调用。
人们不会喜欢这样,但是:
goto middle;
do
{
printf("Error, please enter a positive integer\n");
middle:
printf("Enter a positive integer: ");
scanf("%d", &n);
} while (n < 0);
如果您强烈反对goto
,则可以使用简化版本的Duff’s device:
switch (0)
do
{
printf("Error, please enter a positive integer\n");
case 0:
printf("Enter a positive integer: ");
scanf("%d", &n);
} while (n < 0);
但是你不应该。
1 通常,软件工程师将不得不使用其他人编写的代码,因此他们必须准备好识别和理解该语言中可表达的任何内容,即使这仅仅是改写的第一步。将其转换为更好的代码。偶尔会出现出于商业或其他实际原因而需要“丑陋”代码的情况。
答案 2 :(得分:1)
这是通过一些重构才能最好地实现IMO的功能:
#include <stdio.h>
#include <stdbool.h>
static bool get_postive_integer(int *pOut) {
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
if(n < 0)
return false;
*pOut = n;
return true;
}
int main(void)
{
int n;
while (!get_postive_integer(&n)) {
printf("Error: please enter a positive integer\n");
}
}
为操作指定一个 name ,检查其是否失败,然后仅相应地打印一条消息。在指定的操作中,成功或失败条件仅在此处编码一次。
答案 3 :(得分:1)
您可以使用:
while (printf("Enter a positive integer: ") > 0 &&
scanf("%d", &n) == 1 &&
n < 0)
{
printf("Error: please enter a positive integer\n");
}
如果printf()
失败,scanf()
失败或n
中的值是非负值,则此操作停止。始终检查scanf()
是否成功是个好主意。 printf()
返回它写入的字符数(或失败时返回负数)只是方便的,因此也可以在某种情况下使用它。您也可以将fflush(stdout) == 0 &&
添加到操作堆栈中。
或者您可以确定条件中的代码应该在函数中:
static int read_positive_integer(void)
{
int value;
if (printf("Enter a positive integer: ") > 0 &&
fflush(stdout) == 0 &&
scanf("%d", &value) == 1 &&
value >= 0)
return value;
return -1;
}
,然后调用代码为:
while ((n = read_positive_integer()) < 0)
printf("Error: please enter a positive integer\n");
主题有很多变化;您可以将while
循环包装到一个函数中;您可以将提示变成函数的参数。您可能决定更谨慎地报告问题所在(如果printf()
失败,则采取不同的操作;如果发生错误,则scanf()
返回0(输入中的非数字数据)或EOF(没有更多数据)输入)。
答案 4 :(得分:1)
另一种替代方法是拆分为一个函数:
int func(){
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
return scanf("%d", &n) == 1 ? n : -1;
}
,循环变为
while ((n = func()) < 0){
printf("Error: please enter a positive integer\n");
}
尽管条件检查中的分配并不符合每个人的口味。请注意,如果scanf
的返回值不为1,我将返回-1,您应始终检查该值。
在这种情况下,我要做的事情(请参阅Eric的答案)
switch (0) do {
printf("Error, please enter a positive integer\n");
case 0:
printf("Enter a positive integer: ");
scanf("%d", &n);
} while (n/*ToDo - make sure n is initialised if scanf fails*/ < 0);