提问人: 提问时间:1/15/2009 最后编辑:Ian G 更新时间:1/8/2020 访问量:48160
使用 while 块什么都不做是一件坏事吗?
Is using a while block to do nothing a bad thing?
问:
我目前正在学习“C 编程语言”中的摘录。这是我的解决方案之一:
int c;
while ((c=getchar()) != EOF) {
if (c == ' ') {
while ((c = getchar()) == ' ')
{} // do nothing?
putchar(' ');
}
putchar(c);
}
我在这里找到了一些与我的解决方案完全不同的解决方案,并使用一个额外的变量来跟踪正在发生的事情,而我只是使用 while 循环来跳过所有空格。我的解决方案感觉有点混乱,因为在大括号之间有一个没有任何东西的 while 循环似乎有点黑客。我想知道是否有任何充分的理由不这样做?感谢您的任何建议:-)
答:
我不认为程序是,但您的格式很奇怪。这没有错:
/* Eat spaces */
while ((c = getchar()) == ' ');
(也就是说,表示故意没有尸体)
评论
一点也不 - 我相信你会在 K&R 中找到这样的无所事事的循环,所以这几乎是官方的。
这是个人喜好的问题,但我更喜欢像这样无所事事的循环:
while(something());
其他人则更喜欢将分号放在单独的行上,以强调它是一个循环的事实:
while(something())
;
还有一些人更喜欢使用里面什么都没有的括号,就像你所做的那样:
while(something())
{
}
这一切都是有效的 - 你只需要选择你喜欢的风格并坚持下去。
评论
{}
continue;
我使用过这样的代码。如果情况需要,我认为真的没有任何理由不使用它。
我认为这是完全可以接受的。
我要么写:
//skip all spaces
while ((c = getchar()) == ' ') {}
很明显,这行代码只做了一件事。
或者我会这样写:
while ((c = getchar()) == ' ') {
//no processing required for spaces
}
以便它与代码的其余部分格式匹配。
就个人而言,我不喜欢
while ((c = getchar()) == ' ');
格式。我认为很容易忽略分号。
评论
好吧,如果你真的不喜欢空大括号,你可以将这个内部循环重构为
while (c == ' ') {c = getchar();}
不过,这需要额外的比较,所以 do while 循环会更好。
评论
我认为没有问题。你可以使用它,在许多情况下我更喜欢它。
我赞成:
while ((c = getchar()) == ' ') /* Eat spaces */;
众所周知,我还有一个名为 DoNothing 的程序,专门用于在此类情况下调用。它清楚地表明你真的不想做任何事情。
虽然不存在的循环体是完全可以接受的,但应该非常清楚它是故意的。
评论
您的问题“使用 while 块什么都不做是一件坏事吗?”也可以从浪费 CPU 周期的角度来回答。在这种情况下,答案是“否”,因为进程将在等待用户输入字符时进入睡眠状态。
只有在输入字符后,该进程才会唤醒。然后测试将发生,如果测试通过,即 c == ' ',该过程将再次进入睡眠状态,直到输入下一个字符。此操作将重复,直到输入非空格字符。
自古以来使用的规范方式,例如,看看里昂的书——是
while(condition) // Here's the whole thing
; // empty body.
事实上,通常,“单独行上的半色”约定用于 null 语句。例如,您偶尔会看到
if( condition-1)
;
else if (condition-2)
stmt;
else {
// do stuff here
}
这种情况要少得多,但会出现在条件 1 非常复杂的地方,所以你不想否定它并造成混淆,或者代码在其生命周期的一英寸内被手动优化,所以你首先想要最常见的情况。
这
while(condition) ;
形式是要被奴役地避免的,因为这是一个常见且令人讨厌的错别字:你应该明确表示你是故意这样做的。空括号
while(condition){
}
或其变体也很麻烦,因为它们要么不够突出,要么更糟的是导致其他错别字。
尚未提及的替代选项:
while(condition)
(void)0;
我真的不喜欢用这种方式写我的循环,但上学期我有一个助教这样做了。
评论
嗯,不是真的,但这取决于你的架构。
if (dosomething()) { ; }
上述内容将不断从您的本地堆栈中推送和弹出,这会产生内存开销。此外,您还将使用 noop 操作刷新处理器的管道。
一个什么都不做可能是一件坏事:while
while(!ready) {
/* Wait for some other thread to set ready */
}
...是一种非常非常昂贵的等待方式——只要是假的,它就会使用操作系统给它的 CPU 尽可能多的 CPU,窃取另一个线程可以做有用工作的 CPU 时间。ready
但是,您的循环并非无所事事:
while ((c = getchar()) == ' ')
{}; // skip
...因为它在调用每一次迭代。因此,正如其他人都同意的那样,你所做的很好。getchar()
评论
Thread.wait()
Thread.notify()
{};
很危险。(谷歌为悬空的别处)我建议。{;}
评论