C++ 是否需要“do {...} while ()”循环?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/994905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there ever a need for a "do {...} while ( )" loop?
提问by Dustin Boswell
Bjarne Stroustrup (C++ creator) once said that he avoids "do/while" loops, and prefers to write the code in terms of a "while" loop instead. [See quote below.]
Bjarne Stroustrup(C++ 的创造者)曾经说过他避免使用“do/while”循环,而是更喜欢用“while”循环来编写代码。[请参阅下面的报价。]
Since hearing this, I have found this to be true. What are your thoughts? Is there an example where a "do/while" is much cleaner and easier to understand than if you used a "while" instead?
自从听到这个,我发现这是真的。你怎么看?有没有一个例子,其中“do/while”比使用“while”更清晰、更容易理解?
In response to some of the answers: yes, I understand the technical difference between "do/while" and "while". This is a deeper question about readability and structuring code involving loops.
回应一些答案:是的,我理解“do/while”和“while”之间的技术区别。这是一个关于可读性和结构化涉及循环的代码的更深层次的问题。
Let me ask another way: suppose you were forbidden from using "do/while" - is there a realistic example where this would give you no choice but to write unclean code using "while"?
让我问另一种方式:假设你被禁止使用“do/while”——是否有一个现实的例子,这会让你别无选择,只能使用“while”编写不干净的代码?
From "The C++ Programming Language", 6.3.3:
来自“C++ 编程语言”,6.3.3:
In my experience, the do-statement is a source of errors and confusion. The reason is that its body is always executed once before the condition is evaluated. However, for the body to work correctly, something very much like the condition must hold even the first time through. More often than I would have guessed, I have found that condition not to hold as expected either when the program was first written and tested, or later after the code preceding it has been modified. I also prefer the condition "up front where I can see it." Consequently, I tend to avoid do-statements.-Bjarne
根据我的经验,do-statement 是错误和混乱的根源。原因是它的主体总是在评估条件之前执行一次。然而,为了让身体正常工作,即使第一次通过,也必须保持非常类似的情况。比我预想的更多的是,我发现无论是在程序第一次编写和测试时,还是在其前面的代码被修改之后,这种情况都没有按预期保持。 我也更喜欢“在我可以看到的地方”的条件。因此,我倾向于避免使用 do 语句。-Bjarne
回答by David Bo?jak
Yes I agree that do while loops can be rewritten to a while loop, however I disagree that always using a while loop is better. do while always get run at least once and that is a very useful property (most typical example being input checking (from keyboard))
是的,我同意 do while 循环可以重写为 while 循环,但是我不同意总是使用 while 循环更好。do while 总是至少运行一次,这是一个非常有用的属性(最典型的例子是输入检查(从键盘))
#include <stdio.h>
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
This can of course be rewritten to a while loop, but this is usually viewed as a much more elegant solution.
这当然可以重写为 while 循环,但这通常被视为更优雅的解决方案。
回答by sharptooth
do-while is a loop with a post-condition. You need it in cases when the loop body is to be executed at least once. This is necessary for code which needs some action before the loop condition can be sensibly evaluated. With while loop you would have to call the initialization code from two sites, with do-while you can only call it from one site.
do-while 是一个带有后置条件的循环。在循环体至少要执行一次的情况下,您需要它。这对于在合理评估循环条件之前需要一些操作的代码来说是必要的。使用 while 循环,您必须从两个站点调用初始化代码,而使用 do-while 则只能从一个站点调用它。
Another example is when you already have a valid object when the first iteration is to be started, so you don't want to execute anything (loop condition evaluation included) before the first iteration starts. An example is with FindFirstFile/FindNextFile Win32 functions: you call FindFirstFile which either returns an error or a search handle to the first file, then you call FindNextFile until it returns an error.
另一个例子是当你在第一次迭代开始时已经有一个有效的对象,所以你不想在第一次迭代开始之前执行任何东西(包括循环条件评估)。一个例子是 FindFirstFile/FindNextFile Win32 函数:您调用 FindFirstFile,它返回一个错误或第一个文件的搜索句柄,然后调用 FindNextFile 直到它返回一个错误。
Pseudocode:
伪代码:
Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
do {
process( params ); //process found file
} while( ( handle = FindNextFile( params ) ) != Error ) );
}
回答by Dan Olson
do { ... } while (0)
is an important construct for making macros behave well.
do { ... } while (0)
是使宏表现良好的重要结构。
Even if it's unimportant in real code (with which I don't necessarily agree), it's important for for fixing some of the deficiencies of the preprocessor.
即使它在实际代码中并不重要(我不一定同意),但对于修复预处理器的一些缺陷很重要。
Edit: I ran into a situation where do/while was much cleaner today in my own code. I was making a cross-platform abstraction of the paired LL/SCinstructions. These need to be used in a loop, like so:
编辑:我遇到了今天在我自己的代码中 do/while 更干净的情况。我正在对成对的LL/SC指令进行跨平台抽象。这些需要在循环中使用,如下所示:
do
{
oldvalue = LL (address);
newvalue = oldvalue + 1;
} while (!SC (address, newvalue, oldvalue));
(Experts might realize that oldvalue is unused in an SC Implementation, but it's included so that this abstraction can be emulated with CAS.)
(专家可能会意识到在 SC 实现中没有使用 oldvalue,但它被包含在内,以便可以用 CAS 模拟这种抽象。)
LL and SC are an excellent example of a situation where do/while is significantly cleaner than the equivalent while form:
LL 和 SC 是一个很好的例子,说明 do/while 比等效的 while 形式要干净得多:
oldvalue = LL (address);
newvalue = oldvalue + 1;
while (!SC (address, newvalue, oldvalue))
{
oldvalue = LL (address);
newvalue = oldvalue + 1;
}
For this reason I'm extremely disappointed in the fact that Google Go has opted to remove the do-while construct.
出于这个原因,我对 Google Go选择删除 do-while 结构这一事实感到非常失望。
回答by hasen
It's useful for when you want to "do" something "until" a condition is satisfied.
当您想“做”某事“直到”满足条件时,它很有用。
It can be fudged in a while loop like this:
它可以像这样在一个 while 循环中被篡改:
while(true)
{
// .... code .....
if(condition_satisfied)
break;
}
回答by Suvesh Pratapa
(Assuming you know the difference between the both)
(假设您知道两者之间的区别)
Do/While is good for bootstrapping/pre-initializing code before your condition is checked and the while loop is run.
Do/While 有利于在检查条件和运行 while 循环之前引导/预初始化代码。
回答by TimW
In our coding conventions
在我们的编码约定中
- if / while / ... conditionsdon't have side effects and
- varibles must be initialized.
- if / while / ... 条件没有副作用并且
- 必须初始化变量。
So we have almost never a do {} while(xx)
Because:
所以我们几乎从来没有do {} while(xx)
因为:
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
is rewritten in:
改写为:
int main() {
char c(0);
while (c < '0' || c > '9'); {
printf("enter a number");
scanf("%c", &c);
}
}
and
和
Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
do {
process( params ); //process found file
} while( ( handle = FindNextFile( params ) ) != Error ) );
}
is rewritten in:
改写为:
Params params(xxx);
Handle handle = FindFirstFile( params );
while( handle!=Error ) {
process( params ); //process found file
handle = FindNextFile( params );
}
回答by Svante
The following common idiom seems very straightforward to me:
以下常用习语对我来说似乎很简单:
do {
preliminary_work();
value = get_value();
} while (not_valid(value));
The rewrite to avoid do
seems to be:
要避免的重写do
似乎是:
value = make_invalid_value();
while (not_valid(value)) {
preliminary_work();
value = get_value();
}
That first line is used to make sure that the test always evaluates to truethe first time. In other words, the test is always superfluous the first time. If this superfluous test wasn't there, one could also omit the initial assignment. This code gives the impression that it fights itself.
第一行用于确保测试在第一次总是评估为真。换句话说,第一次测试总是多余的。如果没有这个多余的测试,也可以省略初始分配。这段代码给人的印象是它在自我战斗。
In cases such like these, the do
construct is a very useful option.
在这种情况下,do
构造是一个非常有用的选择。
回答by Ron Klein
It's all about readability.
More readable code leads to less headache in code maintenance, and better collaboration.
Other considerations (such as optimization) are, by far, less important in most cases.
I'll elaborate, since I got a comment here:
If you have a code snippet Athat uses do { ... } while()
, and it's more readable than its while() {...}
equivalent B, then I'd vote for A. If you prefer B, since you see the loop condition "up front", and you think it's more readable(and thus maintainable, etc.) - then go right ahead, use B.
My point is: use the code that is more readable to your eyes (and to your colleagues'). The choice is subjective, of course.
这都是关于可读性的。
更具可读性的代码可以减少代码维护的麻烦,并更好地协作。
到目前为止,其他考虑因素(例如优化)在大多数情况下并不重要。
我会详细说明,因为我在这里得到了一条评论:
如果您有一个使用的代码片段Ado { ... } while()
,并且它比while() {...}
等效的B更具可读性,那么我会投票给A。如果您更喜欢B,因为您在“前面”看到循环条件,并且您认为它更具可读性(因此可维护等) - 然后继续使用B。
我的观点是:使用对你的眼睛(和你的同事)来说更具可读性的代码。当然,选择是主观的。
回答by ?οδεMεδι?
It is only personal choice in my opinion.
在我看来,这只是个人选择。
Most of the time, you can find a way to rewrite a do ... while loop to a while loop; but not necessarily always. Also it might make more logical sense to write a do while loop sometimes to fit the context you are in.
大多数时候,你可以找到一种方法将 do ... while 循环重写为 while 循环;但不一定总是。此外,有时编写 do while 循环以适应您所处的上下文可能更合乎逻辑。
If you look above, the reply from TimW, it speaks for itself. The second one with Handle, especially is more messy in my opinion.
如果你看上面,来自 TimW 的回复,它不言自明。带有 Handle 的第二个,尤其是在我看来更凌乱。
回答by ?οδεMεδι?
Read the Structured Program Theorem. A do{} while() can always be rewritten to while() do{}. Sequence, selection, and iteration are all that's ever needed.
阅读结构化程序定理。do{} while() 总是可以重写为 while() do{}。序列、选择和迭代都是需要的。
Since whatever is contained in the loop body can always be encapsulated into a routine, the dirtiness of having to use while() do{} need never get worse than
由于循环体中包含的任何内容始终可以封装到例程中,因此必须使用 while() do{} 的肮脏性永远不会比
LoopBody()
while(cond) {
LoopBody()
}