使用 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 块啥都不做是件坏事吗?的主要内容,如果未能解决你的问题,请参考以下文章