86

在许多语言中,作业在条件下是合法的。我一直不明白这背后的原因。你为什么要写:

if (var1 = var2) {
  ...
}

代替:

var1 = var2;
if (var1) {
  ...
}
4

12 回答 12

122

循环比 if 语句更有用。

while( var = GetNext() )
{
  ...do something with var 
}

否则必须写

var = GetNext();
while( var )
{
 ...do something
 var = GetNext();
}
于 2008-09-30T05:32:39.460 回答
35

我发现它在通常涉及错误检测等的操作链中最有用。

if ((rc = first_check(arg1, arg2)) != 0)
{
    report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
    report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
    report error based on new rc
}
else
{
    do what you really wanted to do
}

替代方案(不使用条件中的分配)是:

rc = first_check(arg1, arg2);
if (rc != 0)
{
    report error based on rc
}
else
{
    rc = second_check(arg2, arg3);
    if (rc != 0)
    {
        report error based on new rc
    }
    else
    {
        rc = third_check(arg3, arg4);
        if (rc != 0)
        {
            report error based on new rc
        }
        else
        {
            do what you really wanted to do
        }
    }
}

通过延长错误检查,替代方案可以在页面的 RHS 之外运行,而条件分配版本则不会这样做。

错误检查也可以是“动作”——、、、first_action()——当然second_action()third_action()而不仅仅是检查。也就是说,可以在该功能管理的过程中检查它们的步骤。(大多数情况下,在我使用的代码中,函数与前置条件检查,或函数工作所需的内存分配,或类似的行一致)。

于 2008-09-30T05:59:00.410 回答
31

如果您正在调用一个函数,它会更有用:

if (n = foo())
{
    /* foo returned a non-zero value, do something with the return value */
} else {
    /* foo returned zero, do something else */
}

当然,你可以把 n = foo(); 在单独的语句 then if (n),但我认为上面是一个相当易读的习语。

于 2008-09-30T05:27:16.773 回答
24

如果您调用的函数返回要处理的数据或指示错误(或您已完成)的标志,这将很有用。

就像是:

while ((c = getchar()) != EOF) {
    // process the character
}

// end of file reached...

就个人而言,这是一个我不太喜欢的成语,但有时替代方案更丑陋。

于 2008-09-30T05:26:51.207 回答
15

如果您无意中尝试使用赋值作为真值,GCC 可以帮助您检测(使用 -Wall),以防它建议您编写

if ((n = foo())) {
   ...
}

即使用额外的括号表示这确实是您想要的。

于 2008-09-30T05:32:34.250 回答
9

当您编写while循环而不是if语句时,该成语更有用。对于if声明,您可以按照您的描述将其分解。但是如果没有这个结构,你要么必须重复自己:

c = getchar();
while (c != EOF) {
    // ...
    c = getchar();
}

或使用循环半结构:

while (true) {
    c = getchar();
    if (c == EOF) break;
    // ...
}

我通常更喜欢循环半形式。

于 2008-09-30T05:32:33.767 回答
4

简短的回答是面向表达式的编程语言允许更简洁的代码。它们不会强迫您将命令与查询分开

于 2008-09-30T06:36:29.493 回答
3

例如,在 PHP 中,它对于遍历 SQL 数据库结果很有用:

while ($row = mysql_fetch_assoc($result)) {
    // Display row
}

这看起来比:

$row = mysql_fetch_assoc($result);
while ($row) {
    // Display row
    $row = mysql_fetch_assoc($result);
}
于 2008-09-30T05:33:00.067 回答
2

另一个优点是在使用 gdb 期间。在下面的代码中,如果我们单步执行,则不知道错误代码。

while (checkstatus() != -1) {
    // process
}

相当

while (true) {
    int error = checkstatus();
    if (error != -1)
        // process
    else
        //fail
}

现在,在单步中,我们可以知道 checkstatus() 的返回错误代码是什么。

于 2013-10-10T06:39:30.620 回答
0

boost::optional我发现它对于返回可选项(或std::optional在 C++17 中)的函数非常有用:

std::optional<int> maybe_int(); // function maybe returns an int

if (auto i = maybe_int()) {
    use_int(*i);
}

这减少了我的变量的范围,使代码更紧凑并且不妨碍可读性(我发现)。

与指针相同:

int* ptr_int();

if (int* i = ptr_int()) {
    use_int(*i);
}
于 2019-11-22T18:39:54.673 回答
0

我今天在用 Arduino(C 语言)编程时使用它。

案子

我有一个发射器和一个接收器。发送器想要发送数据,直到它被接收到。我想在过程完成后设置一个标志。

while (!(newtork_joined = transmitter.send(data))) {
Serial.println("Not Joined");
}

这里:

  • "transmitter.send" - 传输成功时返回 true
  • “newtork_joined” - 是我成功时设置的标志

结果

  1. 传输不成功时,不设置标志,while循环为真,一直执行

  2. 成功时,设置标志,while循环为假,我们退出

不漂亮吗?

于 2021-05-27T11:48:52.337 回答
-4

原因是:

  1. 性能改进(有时)

  2. 更少的代码(总是)

举个例子:有一个方法someMethod(),在一个if条件下要检查方法的返回值是否为null. 如果没有,您将再次使用返回值。

If(null != someMethod()){
    String s = someMethod();
    ......
    //Use s
}

由于您两次调用相同的方法,因此会影响性能。而是使用:

String s;
If(null != (s = someMethod())) {
    ......
    //Use s
}
于 2016-11-18T12:24:40.923 回答