C++ 最优雅的循环构造?

C++ 最优雅的循环构造?,c++,c,loops,C++,C,Loops,对不起,我问了个新问题。我还在学习编程。所以我使用C++,我需要做这样的事情:< /P> int n; do { n = get_data(); if(n != -1) send(n); } while(n != -1); 这只是个草图。不管怎么说,它感觉不太优雅。我得考试两次。我可以只测试一次并设置一个标志,但这也感觉不到真正的优雅,因为我必须检查标志两次。似乎应该有一种方法更容易做到这一点,因为我想做的事情非常简单。如何使用: 这样,您只需测试一次,如果ge

对不起,我问了个新问题。我还在学习编程。所以我使用C++,我需要做这样的事情:< /P>
int n;
do {
    n = get_data();
    if(n != -1)
        send(n);
} while(n != -1);
这只是个草图。不管怎么说,它感觉不太优雅。我得考试两次。我可以只测试一次并设置一个标志,但这也感觉不到真正的优雅,因为我必须检查标志两次。似乎应该有一种方法更容易做到这一点,因为我想做的事情非常简单。

如何使用:


这样,您只需测试一次,如果get_data没有返回您想要的数据,则立即退出。

您的原始版本没有问题

int n;
while (-1 != (n = get_data())) {
    send(n);
} // while
在我上一次的C编程工作中,我们必须遵循MISRA编码标准

根据MISRA规则,这:

int n;
while(1) {
    n = get_data();
    if(n == -1)
        break;
    send(n);
}
由于
中断
而被禁止,并且:

while((n = get_data()) != -1) { send(n); }
是禁止的,因为赋值出现在布尔上下文中,所以我习惯于编写类似于原始版本的循环

如果您认为布尔变量可以使您的意图更清晰,或者如果测试是一个复杂的表达式,则可以使用布尔变量:

int n;
bool valid;
do {
    n = get_data();
    valid = n != -1;
    if(valid)
        send(n);
} while(valid);

但是对于像“
n!=-1
”这样的简单测试,可能不值得将程序延长。

类似于eed3si9n,但可以说更易于阅读:

 int n;
 while (n = get_data(), n != -1)
 {
     send(n);
 }

使用
goto
:)进行构造


在Python中,您可以执行以下操作:

while True:
    n = get_data()
    if n == -1:
        break
    send(n)
如您所见,这并不比您的C版本短多少。通常,Python代码比其C等效代码小5到10倍。这里的情况并非如此,因此您可以享受可读、足够短、快速的代码片段,并专注于其他内容



如果你真的想把它缩短,请查看Jonathan的答案,但实际上这并不重要。

我更喜欢这样,因为它最具表现力,即使在get_data()变得更复杂时也能伸缩。在这种情况下,我还将添加一条注释,描述“永恒循环”的退出条件,例如://在get_data()==-1时中断。这是众所周知的“循环半”的一个实例构造:对我来说是最明显的,因此也是最优雅的。我鄙视人们把常数放在比较的左边。我以前的一些同事对这种构造(嵌入条件表达式中的副作用)很反感,一些教科书告诉你不要这样做。但我一直不明白为什么——我认为这很好,但有时出于政治原因最好避免。您将常量放在左侧,这样当您意外更改==或!=时,它就是编译器错误到赋值运算符(=)。在大多数现代语言中,尤其是在现代IDE中,这不再是一个问题。我仍然用C++代码来做。把常数放在表达式的左边确实可以避免意外的错误,如果(n=1)我惊讶的是,没有人在这样的短循环结束时对'// while '进行评论。我必须反对EasiRER来阅读。大多数程序员不理解C中的逗号运算符,因此无意中发现了这种类型的构造。另一方面,许多程序员也很难理解运算符=返回赋值的事实,而且它的使用很容易导致其他地方提到的错误。但这就是为什么我说“可以论证”而不是“肯定”:-)即使你对逗号不熟悉,这个版本看起来确实更干净。我觉得看到它但不习惯使用逗号的人仍然能够比eed3si9n的版本更快地解析它。我找不到MISRA标准的在线版本(不过,你可以花25美元买一本书……)。从你的描述来看,这感觉有点愚蠢,给程序员强加了一种庞大的编码风格。@Harleqin,你是对的,生成的代码可能会庞大,有些规则过于苛刻,有些规则在嵌入式平台之外没有意义。MISRA强制规定,任何代码都不能只写。它的规则是让任何程序都不言而喻。当然,有些可能会提高性能,但我们都知道,优化应该在您有了功能程序之后进行。如果你得到一个清晰可读的代码,你就允许其他人重复使用它。@jpinto3912-从这个例子来看,MISRA有时似乎可以执行相反的操作。如果你从不从顶部输入,do循环和while循环之间没有区别,是吗?如果不是,我会用更熟悉的while形式。是的,你是对的,没有真正的区别。这只是个人喜好的问题:)我喜欢使用while form,因为获取数据的行和对该数据进行测试的行(循环条件)一行接一行地驻留。我通常会对此投反对票,因为格式使其难以阅读,但这是一种有趣的方法。如果要保存行,请取出大括号:)是,如果你真的想把它缩短(我没有),这将是最好的方法。A、 至少,for循环的巧妙使用。老实说,我发现你的代码很容易阅读。花时间把它缩短(当你再次阅读它时,花更多的时间在你的头脑中打开它)并不是你能做的最好的投资。谁在乎呢:它有效、高效、可读。转到下一行。这是我们在cobol中学习循环的方法,很久以前。一个典型的编译器会倾向于以高效的形式编译它吗?据我所见,lazydens解决方案通常是编译器为了提高指令缓存效率而生成的
/* This is cleaner */ 
AGAIN:;
    int n = get_data();
    if (n != -1)
    {
        send(n);
        goto AGAIN;
    }


/* This has some charm as well */ 
int n;
while ((n = get_data()) != -1)
    send(n);
/* and now i see that this is the top answer.  Oh well */ 
int n;
goto inside; do {
  send(n);
inside:
  n=get_data();
} while(n!=-1);
int get_data()
{
 ...
}

void _send(int )
{
 ...
}

int  send(int (*a) ())
{
   int n = a();

   if (n == -1)
      return n;

   _send(n);
   return 1;
}

int main()
{
  int (*fp)();
  fp = get_data;
  while ( send(fp)!= -1 );

  return 0;
}
int n;
n = get_data();
while (n != -1) {
  send(n);
  n = get_data();
}
while True:
    n = get_data()
    if n == -1:
        break
    send(n)
/* This is cleaner */ 
AGAIN:;
    int n = get_data();
    if (n != -1)
    {
        send(n);
        goto AGAIN;
    }


/* This has some charm as well */ 
int n;
while ((n = get_data()) != -1)
    send(n);
/* and now i see that this is the top answer.  Oh well */