Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 替代“while(1)”简化分支_C - Fatal编程技术网

C 替代“while(1)”简化分支

C 替代“while(1)”简化分支,c,C,有时,我会使用while(1)块来展平一系列的if..else不成比例。它沿着这些路线走 而不是做: // process if (success) { // process if (success) { //process if (success) { // etc } } } 我有: 我对结尾的隐式跳转感到有点恼火,而。我可以用一个更精简的结构(即在结尾处不使用break)吗 我可以用一个变量(或寄存器?)交换最后的break。这并不是更

有时,我会使用
while(1)
块来展平一系列的
if..else
不成比例。它沿着这些路线走

而不是做:

// process 
if (success) {
  // process 
  if (success) {
    //process
    if (success) {
      // etc
    }
  }
}
我有:

我对
结尾的隐式跳转感到有点恼火,而
。我可以用一个更精简的结构(即在结尾处不使用
break
)吗

我可以用一个变量(或寄存器?)交换最后的
break
。这并不是更精简或更清晰

int once = 1;
while (once--) {
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
}
for循环看起来会更好一些(C99):

我想用一个开关盒。它看起来并没有好多少,尽管它会起作用

switch (1) { default:
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
}
在这种情况下,标签的概念似乎是无与伦比的

// process
if (!success) goto end;
// process
if (!success) goto end;
// process
if (!success) goto end;
// etc

end:

你们还知道/使用了什么方法?

以下是一种与循环非常类似的方法,但不需要在末尾使用计数器或
break
语句

do
{
    // process
    if (!success) break;
    // process
    if (!success) break;
    // process
    if (!success) break;
    ...
    // No need for a break statement here
}
while(0);

不清楚你为什么需要筑巢或休息。当序列在第一次失败时需要跳转时,我总是这样做:

// process

if (success) {
  // more process
}

if (success) {
  // still more process
}

if (success) {
  // even more process
}

摆弄比特提供了一种常见的方法。另一种常见的方法是使用单个状态变量/标志来实现类似的结果

bool bErr = false;

if (!bErr && success) {
   // do something
} else {
   bErr = true;
}
if (!bErr && success2) {
   // do something
} else {
   bErr = true;
}

if (bErr) {
   // hanlde cleanup from errors
}
你们还知道/使用什么方法

您可以将
while
循环封装在一个函数中(并在使用
while
循环的地方调用此函数):

任何编译器(例如,即使禁用了优化的
gcc
)都将内联
静态
函数(如果调用一次)。(当然,一些变量可能必须在
process
函数的词法范围内,在这种情况下,只需将它们作为函数的参数提供即可)

请注意,从上到下而不是水平地编写代码(例如,使用嵌套的
if
)的示例称为duffing。这里有一篇关于这个主题的好文章:

此外,在中还有针对水平代码的特定警告:

如果您需要3级以上的缩进,那么无论如何都会出错,应该修复您的程序


如果将生成
success
的每个条件块的主体安排为如下函数,或者可以将每个
//进程
简化为布尔表达式,例如:

success = f1() ; 
if( success ) 
{
  success = f2() ; 
  if( success ) 
  {
    success = f3() ; 
    if( success ) 
    {
      success = f4()
    }
  }
}
然后,您可以利用短路计算将其简化为单个布尔表达式:

success = f1() && 
          f2() && 
          f3() && 
          f4() ;

如果
f1()
返回false并且每次后续调用都返回false,则不会调用
f2()
,表达式求值将在第一个
&
操作数子表达式上中止以返回false。

另一个选项将使用简单的标志变量

bool okay = true;

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}

而像这样的循环是避免
goto
的奇怪方法<代码>转到
可以并且应该用于O.P.提到的情况。这是无限转到;break的目标定义明确且不可变。有了goto,你可以有任意数量的目标——break的限制性加强了结构。我可以想象复制和粘贴一块代码,例如忽略更改标签名称。@FiddlingBits人们被教导不要使用
goto
,因为这会导致复杂和混乱的代码。在这种特殊情况下,您实际上是通过使用
do/while
来复制
goto
的自然功能。如果不熟悉代码的人开始查看代码,他们将不知道为什么会有循环,直到他们遇到
while(0)
。它并没有立即传达代码应该做什么。@PavanYalamanchili:说得好,它至少应该得到一个明确的评论——对于可怜的(通常是缺乏经验的)维护人员来说!对goto的憎恨源于Dijkstra试图强迫结构化编程进入一个不想要它的世界。不使用goto不是“良好实践”;这是一个断章取义的40年历史的无关事件。OP的用例实际上是goto的标准用法——它是正确的语言特性:生成更干净、更简单、更快的代码。您可以将if语句更改为
if(!(bErr |=!success)){…}
(或类似的内容),并放弃对那些冗长的else语句的任何需要(我的意见)@Serge
else
语句的要点是设置错误标志。这一点是,如果任何单个块失败,就会设置错误标志,并且不再执行其他块。在我的示例中,每当成功为false时,bErr标志就会设置为true,或者即使成功为true,也会保持设置为true,并强制if语句失败。相同的想法,不同的实现。但是,是的,我知道有些人不喜欢在if语句中使用赋值运算符。@Serge是的,你应该真正避免在求值(即:
if
语句)中使用赋值,因为它可能“短路不存在”(),或者在日志或调试语句中,因为优化器甚至编译时设置(即:
ifdef
)可能会阻止分配的发生。当人们知道自己在做什么时(在
if
语句场景中),它们不会造成损害。短路应适用于
|124;
操作符(根据提供的源代码),而不是
if
语句本身。不过,这是简洁性与可读性的折衷。+1这也是一个很好的解决方案。不过,也许可以返回一个错误代码,而不是
void
。感谢这篇有用的文章。我尝试用谷歌搜索duffing的来源,但没有成功?@PhilippeA。如果你愿意,我认为它来自Duff的设备从未遇到过它,我强烈建议您阅读该页面,并注意到switch语句的奇怪结构,其中嵌入了
do while
语句。请参阅@ABFORCE-您真的知道单返回点建议的目的是什么,还是您只是遵循了这个邪教?我喜欢您的解决方案冷逻辑。但是它是n
success = f1() ; 
if( success ) 
{
  success = f2() ; 
  if( success ) 
  {
    success = f3() ; 
    if( success ) 
    {
      success = f4()
    }
  }
}
success = f1() && 
          f2() && 
          f3() && 
          f4() ;
bool okay = true;

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}