如果条件相同的while循环中的if语句

时间:2018-10-31 11:31:55

标签: c if-statement while-loop conditional-statements

通过消除C中if语句中的重复条件,是否有更好的方式编写以下代码?

while (n < 0) {
   printf("Enter a positive integer: ");
   scanf("%d", &n);

   if (n < 0) {
      printf("Error: please enter a positive integer\n");
   }
}

谢谢。

5 个答案:

答案 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);