使用 while 块啥都不做是件坏事吗?

Posted

技术标签:

【中文标题】使用 while 块啥都不做是件坏事吗?【英文标题】:Is using a while block to do nothing a bad thing?使用 while 块什么都不做是件坏事吗? 【发布时间】:2010-10-01 12:51:18 【问题描述】:

我目前正在完成“C 编程语言”中的练习。这是我的解决方案之一:

int c;

while ((c=getchar()) != EOF) 

if (c == ' ') 

    while ((c = getchar()) == ' ')

      // do nothing?

    putchar(' ');



putchar(c);


我找到了一些解决方案here,它们与我的完全不同,并使用一个额外的变量来跟踪正在发生的事情,而我只是使用一个 while 循环来跳过所有的空格。我的解决方案感觉有点混乱,因为在大括号之间没有任何内容的 while 循环似乎有点骇人听闻。我想知道是否有充分的理由不这样做?感谢您的任何建议:-)

【问题讨论】:

你需要担心如果内部while循环遇到EOF会发生什么。目前,您可能会输出字符 0xFF (y-umlaut) 作为最后一个字符。如果外部循环的主体是缩进的,它也会更清晰。 【参考方案1】:

完全没有——我相信你会在 K&R 中找到像这样的无操作循环,所以这几乎是官方的。

这是个人喜好问题,但我更喜欢这样的无操作循环:

while(something());

其他人更喜欢将分号放在单独的行上,以强调它是一个循环的事实:

while(something())
  ;

还有一些人喜欢使用里面没有任何内容的括号,就像你所做的那样:

while(something())


这一切都有效 - 你只需要选择你喜欢的风格并坚持下去。

【讨论】:

我倾向于在空循环中添加“继续”:“while (foo) continue;”。我认为,这使得循环的无操作性质对读者来说更清楚,但这是一个非常小的文体问题。 从来没想过。好主意 liw.fi! 在另一个线程中,有人指出,Google 风格指南官方推荐continue;,因为单独的分号可能看起来像是do-while 循环的结束。 google-styleguide.googlecode.com/svn/trunk/…【参考方案2】:

我认为这是完全可以接受的。

我会写它:

//skip all spaces
while ((c = getchar()) == ' ')  

让这一行代码做一件事很明显。

或者我会这样写:

while ((c = getchar()) == ' ') 
    //no processing required for spaces

使其与代码的其余格式相匹配。

我个人不喜欢

while ((c = getchar()) == ' ');

格式。我认为很容易忽略分号。

【讨论】:

+1 我对分号发表了类似的观点,但你的观点更深入。 没有称职的 C 程序员编写不测试 EOF 的输入循环。【参考方案3】:

您的问题“使用 while 块什么都不做是件坏事吗?”也可以用浪费 CPU 周期来回答。在这种情况下,答案是“否”,因为进程在等待用户输入字符时会休眠。

只有在输入字符后进程才会唤醒。然后将进行测试,如果测试通过,即 c == ' ',则进程将再次进入睡眠状态,直到输入下一个字符。重复此过程,直到输入非空格字符。

【讨论】:

【参考方案4】:

如果你真的不喜欢空括号,你可以将内部循环重构为

while (c == ' ') c = getchar();

不过,这需要额外的比较,所以使用 do while 循环会更好。

【讨论】:

更好的可能是:do c = getchar(); 而 (c == ' ');当然,除非 c 在进入循环之前知道 == ' '。【参考方案5】:

一个什么都不做的while可能一件坏事:

while(!ready) 
   /* Wait for some other thread to set ready */

... 是一种非常非常昂贵的等待方式——只要ready 为假,它将使用操作系统提供的尽可能多的 CPU,从而窃取其他线程的 CPU 时间可以做有用的工作。

但是你的循环没有什么都不做:

while ((c = getchar()) == ' ')
    ;  // skip

... 因为它在每次迭代时都调用getchar()。因此,正如其他人都同意的那样,您所做的一切都很好。

【讨论】:

什么是不昂贵的屏蔽方式? 如果你需要在其他线程上等待,那么你需要在其他线程上等待......没有什么可做的,不是吗? @dwanderson 如果你需要在另一个线程上等待,你应该使用Thread.wait()Thread.notify() ; 很危险。 (google for dangling else)我建议改为;【参考方案6】:

我不认为程序是,但你的格式很奇怪。没有错:

/* Eat spaces */
while ((c = getchar()) == ' ');

(即表示故意没有实体)

【讨论】:

啊,我没有意识到我可以这样格式化它,大声笑 :) 谢谢! 善用 cmets。我倾向于避免空的while循环。起初它似乎总是一个错字,所以我看了两遍才意识到这是故意的,然后再看第三遍,弄清楚它的作用。它们只是不是所有可读的 IMO。 可读性真的很主观。我总是尽可能地放大括号,所以这在我工作的代码库中对我来说很明显。【参考方案7】:

规范的方式——自远古以来就使用,看看里昂的书——是

while(condition)       // Here's the whole thing
    ;                  // empty body.

事实上,一般来说,'semicolor on a separate line' 约定用于空语句。例如,您会偶尔看到

if( condition-1)
     ;
else if (condition-2)
     stmt;
else 
     // do stuff here

这种情况比较少见,但是会出现在 condition-1 非常复杂的地方,因此您不想否定它和机会混淆,或者代码已经过手动优化在其生命的一英寸之内,因此您首先要最常见的情况。

while(condition) ;

应严格避免使用表单,因为这是一个常见且烦人的错字:您应该明确表示您是故意这样做的。空大括号

 while(condition)
 

或其变体也很麻烦,因为它们要么不够突出,要么更糟糕地导致其他错别字。

【讨论】:

【参考方案8】:

我赞成:

while ((c = getchar()) == ' ') /* Eat spaces */;

我还知道有一个名为 DoNothing 的过程,专门用于在这种情况下调用。这很清楚地表明你真的什么都不做。

虽然不存在的循环体是完全可以接受的,但应该非常清楚这是故意的。

【讨论】:

我要做的唯一改变是将分号放在评论之前【参考方案9】:

我使用过这样的代码。如果情况允许,我认为没有任何理由不使用它。

【讨论】:

【参考方案10】:

我认为这没有问题。你可以使用它,在很多情况下我更喜欢它。

【讨论】:

【参考方案11】:

嗯,不是真的,但这取决于你的架构。

if (dosomething())  ; 

上面的内容会不断地从本地堆栈中推送和弹出,这会产生内存开销。此外,您还将使用 noop 操作刷新处理器的管道。

【讨论】:

【参考方案12】:

尚未提及的替代选项:

while(condition)
    (void)0;

我真的不喜欢这样写循环,但我上学期有个助教。

【讨论】:

为什么不“继续;”对于循环体?我更喜欢在一行中单独使用分号,如大师 K&R 所示。 @Jonathan:这不是我的主意 :-) 我不会那样写循环。

以上是关于使用 while 块啥都不做是件坏事吗?的主要内容,如果未能解决你的问题,请参考以下文章

在这种情况下,谨慎(啥都不做)是勇气(猜测)的更好部分吗?

Java:创建“系统”类是件坏事吗? [关闭]

为啥 justify-content space-between 啥都不做?

C# 要么返回 false 要么啥都不做

如何创建啥都不做的#define?

cuPrintf 啥都不做(程序使用固定+映射内存,CUBLAS 也是)