33

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

int c;

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

if (c == ' ') {

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

    {}  // do nothing?

    putchar(' ');

}

putchar(c);

}

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

4

12 回答 12

49

一点也不——我相信你会在 K&R 中找到像这样的无操作循环,所以这几乎是官方的。

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

while(something());

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

while(something())
  ;

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

while(something())
{
}

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

于 2009-01-15T05:03:00.347 回答
6

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

我要么写它:

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

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

或者我会这样写:

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

以便它与您的代码格式的其余部分匹配。

就个人而言,我不是

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

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

于 2009-01-15T05:06:00.887 回答
6

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

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

于 2009-01-15T06:10:08.183 回答
5

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

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

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

于 2009-01-15T05:10:21.423 回答
3

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

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

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

但是你的循环没有做任何事情:

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

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

于 2009-01-15T06:20:40.300 回答
1

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

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

(即表示故意没有实体)

于 2009-01-15T05:02:59.957 回答
1

我赞成:

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

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

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

于 2009-01-15T05:19:34.183 回答
1

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

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
}

它更不常见,但出现在条件 1非常复杂的地方,所以你不想否定它和机会混淆,或者代码在其生命的一英寸内被手动优化,所以你首先要最常见的情况。

while(condition) ;

form 是要严格避免的,因为这是一个常见且令人讨厌的错字:您应该明确表示您是故意这样做的。空大括号

 while(condition){
 }

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

于 2009-01-15T06:12:15.917 回答
0

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

于 2009-01-15T05:05:22.370 回答
0

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

于 2009-01-15T05:11:41.907 回答
0

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

if (dosomething()) { ; }

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

于 2009-01-15T06:20:32.953 回答
-1

尚未提及的替代选项:

while(condition)
    (void)0;

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

于 2009-01-15T06:19:26.123 回答