简体   繁体   English

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

[英]If statement inside while loop with the same condition

Is there a better way to write the following code by eliminating the repeated condition in the if statement in C? 通过消除C中if语句中的重复条件,是否有更好的方式编写以下代码?

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

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

Thank you. 谢谢。

Simply rework your loop breaking when correct input is given. 只要给出正确的输入,只需对回路中断进行重新处理。 This way the check is done only one time: 这样,检查仅执行一次:

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

   if (n >= 0)
       break;

   printf("Error: please enter a positive integer\n");
}

And, as specified in comments, an optimized compiler should be able to reverse the loop by itself. 并且,如注释中所述,优化的编译器应该能够自行反转循环。

The following examples are presented in the spirit that people should know what is available in the language. 提出以下示例是出于人们应该了解该语言可用内容的精神。 1 The way I would usually write the code is shown in Frankie_C's answer . 1 Frankie_C的答案显示了我通常编写代码的方式 As some have noted, optimization usually makes this simple case not worth worrying about, but the question is not limited to a simple evaluation like n < 0 ; 正如某些人指出的那样,优化通常会使这种简单情况不值得担心,但问题并不局限于简单的评估,如n < 0 ; the test might be a function call to some expensive evaluation of more complicated criteria. 该测试可能是对较复杂的标准进行一些昂贵评估的函数调用。

Folks are not going to like this, but: 人们不会喜欢这样,但是:

    goto middle;
    do
    {
        printf("Error, please enter a positive integer\n");
middle:
        printf("Enter a positive integer: ");
        scanf("%d", &n);
    } while (n < 0);

If you are vehemently opposed to goto , you can use a stripped-down version of Duff's device : 如果您强烈反对goto ,则可以使用精简版的Duff设备

    switch (0)
    do
    {
        printf("Error, please enter a positive integer\n");
    case 0:
        printf("Enter a positive integer: ");
        scanf("%d", &n);
    } while (n < 0);

But you should not. 但是你不应该。

Footnote 脚注

1 Commonly, software engineers will have to work with code written by others, so they must be prepared to recognize and understand anything expressible in the language, even if that is just a first step toward rewriting it into better code. 1通常,软件工程师将不得不使用其他人编写的代码,因此他们必须准备好识别和理解该语言可表达的任何内容,即使这只是将其重写为更好的代码的第一步。 And occasionally situations arise where “ugly” code becomes desirable for commercial or other practical reasons. 有时会出现出于商业或其他实际原因而需要“丑陋”代码的情况。

This is something that IMO is best accomplished with a bit of refactoring: 这是通过一些重构可以最好地完成的:

#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");
   }
}

Give the operation a name , check that it fails, and only then print a message accordingly. 给操作起一个名字 ,检查它是否失败,然后才相应地打印一条消息。 The success or failure condition is only coded once here, in the named operation. 在指定的操作中,成功或失败条件仅在此处编码一次。

You could use: 您可以使用:

while (printf("Enter a positive integer: ") > 0 &&
       scanf("%d", &n) == 1 &&
       n < 0)
{
    printf("Error: please enter a positive integer\n");
}

This stops if the printf() fails, if the scanf() fails, or if the value in n is non-negative. 如果printf()失败, scanf()失败或n值为非负值,则此操作将停止。 It's a good idea to always check that the scanf() succeeds. 始终检查scanf()成功是个好主意。 It is merely convenient that printf() returns the number of characters it wrote (or a negative number on failure) so it can be used in a condition too. printf()返回它写入的字符数(或在失败时返回负数printf()只是方便的,因此它也可以在某种情况下使用。 You could add fflush(stdout) == 0 && into the stack of operations too. 您也可以将fflush(stdout) == 0 &&到操作堆栈中。

Or you could decide that the code in the condition should be in a function: 或者,您可以决定条件中的代码应该在函数中:

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;
}

and then the calling code is: 然后调用代码是:

while ((n = read_positive_integer()) < 0)
    printf("Error: please enter a positive integer\n");

There are many variations on the theme; 主题有很多变体。 you might wrap the while loop into a function; 您可以将while循环包装到一个函数中; you might make the prompts into parameters to the function. 您可以将提示变成函数的参数。 You might decide to be more careful about reporting what goes wrong (different actions if printf() fails compared with what happens if scanf() returns 0 (non-numeric data in the input) or EOF (no more data in the input). 您可能决定更谨慎地报告问题所在( printf()失败时采取不同的操作,而scanf()返回0(输入中为非数字数据)或EOF(输入中没有更多数据)会发生什么。

Another alternative is to split into a function: 另一种选择是将其拆分为一个函数:

int func(){
   int n;
   printf("Enter a positive integer: ");
   scanf("%d", &n);
   return scanf("%d", &n) == 1 ? n : -1;
}

and the loop becomes 循环变成

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

although the assignment in the condition check is not to everyone's taste. 尽管条件检查中的分配并不符合每个人的口味。 Note that I return -1 if the return value of scanf is not 1, something that you should always check. 请注意,如果scanf的返回值不为1,我将返回-1,您应始终检查该值。


What I do though in this situation (See Eric's answer) is to write 在这种情况下,我要做的是(请参阅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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM