I am currently reading "A tour of C++" from Bjarne Stroustup, and I saw the following example:
bool accept()
{
cout << "Do you want to proceed (y or n)?\n"; // write question
char answer = 0; // initialize to a value that will not appear on input
cin >> answer; // read answer
if (answer == 'y')
return true;
return false;
}
I thought using multiple return statements wasn't recommended. Wouldn't it be better practice in this case to create a bool variable, initialize it to 0 and then modify it in the if condition, to finally return the value of this boolean variable? Or I am just making things up.
No, you're not entirely making things up, and no there is no recommendation of such that I know of.
Snippet According to your recommendation:
Int accept()
{
Int result=0;
cout << "Do you want to proceed (y or n)?\n"; // write question
char answer = 0; // initialize to a value that will not appear on input
cin >> answer; // read answer
if (answer != 'y')
result=1;
return result;
}
Looking closer you will notice no difference between the snippet above and the one you found in the book, they book use validation, the difference is the data-type used.
Now, it will be more easy to use a boolean if you need to simple use the function accept like below:
if(accept()) /*do something*/;
Rather than:
if(accept()==0) /*do something*/
Either way, you're good to go.
Another thing to consider is the size of your data-type, boolean is just 1bit while int is 4bytes so comparison time complexity will obviously be different but you will most likely never notice the difference.
Edit:
In java boolean is 1bit as said above but since it's c++, because of the issue of 1bit not addressable, it only make more sense to make it 8bit and then it can be given an address in the memory.
So, in C++ boolean is also 1byte or 8bit, and so the comparison time difference is not a thing to consider.
Both approaches are possible, but you will usually see the version using multiple return values. Take a look how this part of the code works:
if (answer == 'y')
return true;
return false;
At first you may see two branches in which the executed code can go, based on the value of answer. First one is connected with y choice, and the other one with anything else. This code could also look like this:
if (answer == 'y')
return true;
else
return false;
But it makes the program a bit more complicated - there is one more jmp instruction in assembly code, which means that the code is just a bit more complex, but its functionality is exactly the same as of the previous version.
Now, we can add the bool variable and let's see how it will look like:
bool is_answer_positive = false;
if (answer == 'y')
is_answer_positive = true;
else // we can get rid of this statement
is_answer_positive = false; // as we have defined variable earlier
return is_answer_positive;
The first thing which makes the code a bit more complex is a new variable, which does not add any vital value to the code, I would say it makes it only more complicated. This is the first instruction which makes the code bigger, but not better. Then if/else works similarly to the second version, but you also assign some values to the is_answer_positive, which also makes the code bigger, but not better. At the end, you return the value you got from if/else statement and the code is done. We can get rid of else statement, as is_answer_positive was initialized to be false, but this is still not the best solution.
Comparing those three possibilities: first version is the most used one, it is clear and probably the simplest, second version adds extra jump, which is unnecessary at all, and the third version adds extra variable, which makes the code a bit harder to read.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am very new to C++. My objective is to write the following logic:
if a = yes then print "ok", else return 0
Here is my code so far:
int a;
cin>>a;
if (a = "Yes") { // Error right here
cout<< "ok"; << endl;
}else{
return 0;
}
First of all, what do you want your program to do?
You need to distinguish assignment and equal to operator.
Please note that you need to understand the basics before proceeding to perform conditional statements.
A reasonable program should go like this:
int a;
cin>>a;
if (a == 5) { // 5 is an integer
cout<< "You entered 5!" << endl; // no semicolon after "
}
return 0; // must be out of the else statement
= assigns things.
Use == to compare, however you are comparing an int with a string.
If you are not careful, you compare the address of a char * with a number when dealing with strings.
Use a std::string instead.
#include <string>
//.... some context I presume
std::string a;
cin >> a;
if (a == "Yes") { // Error right here
cout<< "ok"; << endl;
}else{
return 0;
}
There are multiple errors in this code.
You need to use the comparison operator in your condition. This is denoted by the double equal sign "==". Your code is using assignment "=" which tries to assign the value "Yes" to the variable a. This is a common error in C/C++ so you need to be careful whenever you compare things.
The other error is that you have declared the variable a to be an integer, so you will get a type mismatch error when you try to compile because "Yes" is a string.
Your code is incorrect in terms of data types. You have a variable 'a' of type int which you are comparing to string "yes". Try to see it from a logical point of view; you can compare:
2 numbers (for example, 2 is greater than 1)
2 strings (for example, "food" is not the same word as "cat")
Etc...
In your case, you are comparing a number inputted(let's assume 5) to a word "yes". When you try to input a letter for var a, you will get a compilation error. Therefore, simply change the following:
string a;
Another problem with your code is when the if-then loop checks the condition; a comparison operator is 2 equal signs next to each other instead of a single equal sign. A single equal sign assigns the item on the right to the item on the left. For example, in:
int num = 5;
The variable num is assigned 5. But you want to make a comparison, not assign the variable its own condition!
Your loop is always true because you set the variable to the condition it is supposed to meet. You also need to do the following:
if (a == "yes")
This compares the value stored in var a to the value on the right side of the == .
Just some advice, I would recommend you to get some good books on c++. Search them online. You can also take online programming courses on edx, course record, etc... . There are a lot of other free learning resources online too which you can make use of. You may also want to dive into a simpler programming language; I would recommend scratch. It gives you a very basic idea about programming and can be done in less than a week.
** Note that I feel this is the simplest way; however, you can also set type of a to a char, accept input and then convert it back to a string. Good luck!
So I have a general question about the do/while loop. I'm learning C++ and I know that you can write something like that:
do{
....
} while(a<10 && cout<<"message");
The point is, that i know this is possible in c++, but do we really do that? I mean, the "cout" thing inside the while?
Your while loop is equivalent to
do {
...
cout << "message";
while(a < 10 && cout);
because cout << ... returns cout again.
Then, the question is, what does it mean to write statements like
while( cout );
or
if (cout) ...
The cout object has a conversion to boolean which is used here. It's implementation is checking !fail(), so
if (cout) ...
is equivalent to
if (!cout.fail()) ...
and
do { ... }
while(cout);
is equivalent to
do { ... }
while(!cout.fail());
Finally, fail returns true if the stream failed to produce output.
The fact is some people do this (i.e. run a function as part of the condition evaluation). It makes sense in a shell script, but if you're not using a shell script, it's sometimes not clear what the return value is for some functions. I couldn't tell you what cout<<"message" returns offhand, but I do know that if you write it inside the loop body, it would do what I want, and it would 'throw away' the return value if I don't use it.
To write cleaner code that others including your future-self can understand, I would only evaluate conditions which obviously return true/false as opposed to "0/not-0", or "0/1" which may different in different languages.
Bottom line is, let the compiler make things more efficient for you, and code for other people, not for the compiler.
If you want to perform the output after testing the condition, you would need to either do that or add another condition test inside the loop and maintain both of them, which is a bug waiting to happen.
do {
if (a < 10)
cout << "message";
} while (a < 10);
It's rare to see cout << by itself in any condition though, as you can usually assume that it will succeed unless your machine is on fire.
On the other hand the extraction operator, >>, usually belongs inside a condition;
while (cin >> x)
is idiomatic C++.
I'm trying to solve this problem as few lines of code as possible.
problem statement:
someone managed to say hello if several letters can be deleted from the typed word so that it resulted in the word "hello"... I'm testing if he could or not
#include <iostream>
int main() {
char c;
int i=0;
while(i!=5 && (cin>>c) && c!='\n'){
if(c=="hello"[i])
i++;
}
cout<<((i==5)?"YES":"NO");
}
There's a bug when it should print "NO". The program waits for more input. I think the loop doesn't finish until i==5 but it never finishes when c=='\n'.
Before you pack your program to minimize the LOC (and I assume that you have a really good reason to care about this because otherwise it is a foolish thing to do) make it right!
Try putting the i != 5 test BEFORE the cin >>c test. Otherwise you read one extra character when you do get a "hello"
Edit: Just to be clear, the code in the question has now been modified to incorporate this suggestion.
You have a while loop there
while(i!=5 && (cin>>c) && c!='\n')
{ ... }
...which you can rewrite for easier debugging. In general, instead of any loop...
while (X)
{ Y }
...you can also write...
while (true)
{
if (!X) break;
Y
}
For your loop, that would be this code:
while (true)
{
if (!(i!=5 && (cin>>c) && c!='\n'))
break;
...
}
Now, I assume you are aware of the short circuit evaluation of the logical AND operator. If not, search the web for that term! With that knowledge, you can rewrite your loop like this:
while (true)
{
if (!(i!=5))
break;
if (!(cin>>c))
break;
if (!(c!='\n'))
break;
...
}
Of course, you can still simplify a few double negations there, but the idea should be clear. This change now allows you to e.g. step through this in a debugger to evaluate each loop exit condition separately. This is important, because the second loop condition also has side effects! In addition, you could e.g. add some debug output that tells you the reason why the loop was exited. Further, for the check that has side effects, you can inspect the intermediate state (or output the state, if you prefer that way), which will give you further insight on the issue.
Lastly, all >> operators on istreams by default skip whitespace, which includes spaces, tabs and newlines, so your last check will never cause the loop to exit. You can tell the stream to not skip whitespace though, if that's what you want. How to do that should be really simple to find out using another websearch. ;)
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Inadvertent use of = instead of ==
C++ compilers let you know via warnings that you wrote,
if( a = b ) { //...
And that it might be a mistake that you certainly wanted to write:
if( a == b ) { //...
But is there a case where the warning should be ignored, because it's a good way to use this "feature"?
I don't see any code clarity reason possible, so is there a case where it’s useful?
Two possible reasons:
Assign & Check
The = operator (when not overriden) normally returns the value that it assigned. This is to allow statements such as a=b=c=3. In the context of your question, it also allows you to do something like this:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
//if x is equal to true, return 4
if (global=x)
return 4;
//otherwise return 3
return 3;
}
...which is equivalent to but shorter than:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
global=x;
//if x is equal to true, return 4
if (global==true)
return 4;
//otherwise return 3
return 3;
}
Also, it should be noted (as stated by Billy ONeal in a comment below) that this can also work when the left-hand argument of the = operator is actually a class with a conversion operator specified for a type which can be coerced (implicitly converted) to a bool. In other words, (a=b) will evaulate to true or false if a is of a type which can be coerced to a boolean value.
So the following is a similar situation to the above, except the left-hand argument to = is an object and not a bool:
#include <iostream>
using namespace std;
class Foo {
public:
operator bool (){ return true; }
Foo(){}
};
int main(){
Foo a;
Foo b;
if (a=b)
cout<<"true";
else
cout<<"false";
}
//output: true
Note: At the time of this writing, the code formatting above is bugged. My code (check the source) actually features proper indenting, shift operators and line spacing. The <'s are supposed to be <'s, and there aren't supposed to be enourmous gaps between each line.
Overridden = operator
Since C++ allows the overriding of operators, sometimes = will be overriden to do something other than what it does with primitive types. In these cases, the performing the = operation on an object could return a boolean (if that's how the = operator was overridden for that object type).
So the following code would perform the = operation on a with b as an argument. Then it would conditionally execute some code depending on the return value of that operation:
if (a=b){
//execute some code
}
Here, a would have to be an object and b would be of the correct type as defined by the overriding of the = operator for objects of a's type. To learn more about operator overriding, see this wikipedia article which includes C++ examples: Wikipedia article on operator overriding
while ( (line = readNextLine()) != EOF) {
processLine();
}
You could use to test if a function returned any error:
if (error_no = some_function(...)) {
// Handle error
}
Assuming that some_function returns the error code in case of an error. Or zero otherwise.
This is a consequence of basic feature of the C language:
The value of an assignment operation is the assigned value itself.
The fact that you can use that "return value" as the condition of an if() statement is incidental.
By the way, this is the same trick that allows this crazy conciseness:
void strcpy(char *s, char *t)
{
while( *s++ = *t++ );
}
Of course, the while exits when the nullchar in t is reached, but at the same time it is copied to the destination s string.
Whether it is a good idea, usually not, as it reduce code readability and is prone to errors.
Although the construct is perfectly legal syntax and your intent may truly be as shown below, don't leave the "!= 0" part out.
if( (a = b) != 0 ) {
...
}
The person looking at the code 6 months, 1 year, 5 years from now, at first glance, is simply going to believe the code contains a "classic bug" written by a junior programmer and will try to "fix" it. The construct above clearly indicates your intent and will be optimized out by the compiler. This would be especially embarrassing if you are that person.
Your other option is to heavily load it with comments. But the above is self-documenting code, which is better.
Lastly, my preference is to do this:
a = b;
if( a != 0 ) {
...
}
This is about a clear as the code can get. If there is a performance hit, it is virtually zero.
A common example where it is useful might be:
do {
...
} while (current = current->next);
I know that with this syntax you can avoid putting an extra line in your code, but I think it takes away some readability from the code.
This syntax is very useful for things like the one suggested by Steven Schlansker, but using it directly as a condition isn't a good idea.
This isn't actually a deliberate feature of C, but a consequence of two other features:
Assignment returns the assigned value
This is useful for performing multiple assignments, like a = b = 0, or loops like while ((n = getchar()) != EOF).
Numbers and pointers have truth values
C originally didn't have a bool type until the 1999 standard, so it used int to represent Boolean values. Backwards compatibility requires C and C++ to allow non-bool expressions in if, while, and for.
So, if a = b has a value and if is lenient about what values it accepts, then if (a = b) works. But I'd recommend using if ((a = b) != 0) instead to discourage anyone from "fixing" it.
You should explicitly write the checking statement in a better coding manner, avoiding the assign & check approach. Example:
if ((fp = fopen("filename.txt", "wt")) != NULL) {
// Do something with fp
}
void some( int b ) {
int a = 0;
if( a = b ) {
// or do something with a
// knowing that is not 0
}
// b remains the same
}
But is there a case where the warning
should be ignored because it's a good
way to use this "feature"? I don't see
any code clarity reason possible so is
there a case where its useful?
The warning can be suppressed by placing an extra parentheses around the assignment. That sort of clarifies the programmer's intent. Common cases I've seen that would match the (a = b) case directly would be something like:
if ( (a = expression_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression_with_zero_for_failure' (might be a function call, e.g.)
}
else if ( (a = expression2_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression2_with_zero_for_failure'
}
// etc.
As to whether writing this kind of code is useful enough to justify the common mistakes that beginners (and sometimes even professionals in their worst moments) encounter when using C++, it's difficult to say. It's a legacy inherited from C and Stroustrup and others contributing to the design of C++ might have gone a completely different, safer route had they not tried to make C++ backwards compatible with C as much as possible.
Personally I think it's not worth it. I work in a team and I've encountered this bug several times before. I would have been in favor of disallowing it (requiring parentheses or some other explicit syntax at least or else it's considered a build error) in exchange for lifting the burden of ever encountering these bugs.
while( (l = getline()) != EOF){
printf("%s\n", l);
}
This is of course the simplest example, and there are lots of times when this is useful. The primary thing to remember is that (a = true) returns true, just as (a = false) returns false.
Preamble
Note that this answer is about C++ (I started writing this answer before the tag "C" was added).
Still, after reading Jens Gustedt's comment, I realized it was not the first time I wrote this kind of answer. Truth is, this question is a duplicate of another, to which I gave the following answer:
Inadvertent use of = instead of ==
So, I'll shamelessly quote myself here to add an important information: if is not about comparison. It's about evaluation.
This difference is very important, because it means anything can be inside the parentheses of a if as long as it can be evaluated to a Boolean. And this is a good thing.
Now, limiting the language by forbidding =, where all other operators are authorized, is a dangerous exception for the language, an exception whose use would be far from certain, and whose drawbacks would be numerous indeed.
For those who are uneasy with the = typo, then there are solutions (see Alternatives below...).
About the valid uses of if(i = 0) [Quoted from myself]
The problem is that you're taking the problem upside down. The "if" notation is not about comparing two values like in some other languages.
The C/C++ if instruction waits for any expression that will evaluate to either a Boolean, or a null/non-null value. This expression can include two values comparison, and/or can be much more complex.
For example, you can have:
if(i >> 3)
{
std::cout << "i is less than 8" << std::endl
}
Which proves that, in C/C++, the if expression is not limited to == and =. Anything will do, as long as it can be evaluated as true or false (C++), or zero non-zero (C/C++).
About valid uses
Back to the non-quoted answer.
The following notation:
if(MyObject * p = findMyObject())
{
// uses p
}
enables the user to declare and then use p inside the if. It is a syntactic sugar... But an interesting one. For example, imagine the case of an XML DOM-like object whose type is unknown well until runtime, and you need to use RTTI:
void foo(Node * p_p)
{
if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
{
// this is a <body> node
}
else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
{
// this is a <span> node
}
else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
{
// this is a <div> node
}
// etc.
}
RTTI should not be abused, of course, but this is but one example of this syntactic sugar.
Another use would be to use what is called C++ variable injection. In Java, there is this cool keyword:
synchronized(p)
{
// Now, the Java code is synchronized using p as a mutex
}
In C++, you can do it, too. I don't have the exact code in mind (nor the exact Dr. Dobb's Journal's article where I discovered it), but this simple define should be enough for demonstration purposes:
#define synchronized(lock) \
if (auto_lock lock_##__LINE__(lock))
synchronized(p)
{
// Now, the C++ code is synchronized using p as a mutex
}
(Note that this macro is quite primitive, and should not be used as is in production code. The real macro uses a if and a for. See sources below for a more correct implementation).
This is the same way, mixing injection with if and for declaration, you can declare a primitive foreach macro (if you want an industrial-strength foreach, use Boost's).
About your typo problem
Your problem is a typo, and there are multiple ways to limit its frequency in your code. The most important one is to make sure the left-hand-side operand is constant.
For example, this code won't compile for multiple reasons:
if( NULL = b ) // won't compile because it is illegal
// to assign a value to r-values.
Or even better:
const T a ;
// etc.
if( a = b ) // Won't compile because it is illegal
// to modify a constant object
This is why in my code, const is one of the most used keyword you'll find. Unless I really want to modify a variable, it is declared const and thus, the compiler protects me from most errors, including the typo error that motivated you to write this question.
But is there a case where the warning should be ignored because it's a good way to use this "feature"? I don't see any code clarity reason possible so is there a case where its useful?
Conclusion
As shown in the examples above, there are multiple valid uses for the feature you used in your question.
My own code is a magnitude cleaner and clearer since I use the code injection enabled by this feature:
void foo()
{
// some code
LOCK(mutex)
{
// some code protected by a mutex
}
FOREACH(char c, MyVectorOfChar)
{
// using 'c'
}
}
... which makes the rare times I was confronted to this typo a negligible price to pay (and I can't remember the last time I wrote this type without being caught by the compiler).
Interesting sources
I finally found the articles I've had read on variable injection. Here we go!!!
FOR_EACH and LOCK (2003-11-01)
Exception Safety Analysis (2003-12-01)
Concurrent Access Control & C++ (2004-01-01)
Alternatives
If one fears being victim of the =/== typo, then perhaps using a macro could help:
#define EQUALS ==
#define ARE_EQUALS(lhs,rhs) (lhs == rhs)
int main(int argc, char* argv[])
{
int a = 25 ;
double b = 25 ;
if(a EQUALS b)
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
if(ARE_EQUALS(a, b))
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
return 0 ;
}
This way, one can protect oneself from the typo error, without needing a language limitation (that would cripple language), for a bug that happens rarely (i.e., almost never, as far as I remember it in my code).
There's an aspect of this that hasn't been mentioned: C doesn't prevent you from doing anything it doesn't have to. It doesn't prevent you from doing it because C's job is to give you enough rope to hang yourself by. To not think that it's smarter than you. And it's good at it.
Never!
The exceptions cited don't generate the compiler warning. In cases where the compiler generates the warning, it is never a good idea.
RegEx sample
RegEx r;
if(((r = new RegEx("\w*)).IsMatch()) {
// ... do something here
}
else if((r = new RegEx("\d*")).IsMatch()) {
// ... do something here
}
Assign a value test
int i = 0;
if((i = 1) == 1) {
// 1 is equal to i that was assigned to a int value 1
}
else {
// ?
}
My favourite is:
if (CComQIPtr<DerivedClassA> a = BaseClassPtr)
{
...
}
else if (CComQIPtr<DerivedClassB> b = BaseClassPtr)
{
...
}
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.]
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?
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.
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"?
From "The C++ Programming Language", 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
Avoiding the do/while loop is a recommendation included in the C++ Core Guidelines as ES.75, avoid do-statements.
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))
#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.
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.
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.
Pseudocode:
Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
do {
process( params ); //process found file
} while( ( handle = FindNextFile( params ) ) != Error ) );
}
do { ... } while (0) is an important construct for making macros behave well.
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/SC instructions. These need to be used in a loop, like so:
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.)
LL and SC are an excellent example of a situation where do/while is significantly cleaner than the equivalent while form:
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.
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:
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 true the 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.
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(true)
{
// .... code .....
if(condition_satisfied)
break;
}
(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.
In our coding conventions
if / while / ... conditions don't have side effects and
varibles must be initialized.
So we have almost never a do {} while(xx)
Because:
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 );
}
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 A that 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.
First of all, I do agree that do-while is less readable than while.
But I'm amazed that after so many answers, nobody has considered why do-while even exists in the language. The reason is efficiency.
Lets say we have a do-while loop with N condition checks, where the outcome of the condition depends on the loop body. Then if we replace it with a while loop, we get N+1 condition checks instead, where the extra check is pointless. That's no big deal if the loop condition only contains a check of an integer value, but lets say that we have
something_t* x = NULL;
while( very_slowly_check_if_something_is_done(x) )
{
set_something(x);
}
Then the function call in first lap of the loop is redundant: we already know that x isn't set to anything yet. So why execute some pointless overhead code?
I often use do-while for this very purpose when coding realtime embedded systems, where the code inside the condition is relatively slow (checking the response from some slow hardware peripheral).
This is cleanest alternative to do-while that I have seen. It is the idiom recommended for Python which does not have a do-while loop.
One caveat is that you can not have a continue in the <setup code> since it would jump the break condition, but none of the examples that show the benefits of the do-while need a continue before the condition.
while (true) {
<setup code>
if (!condition) break;
<loop body>
}
Here it is applied to some of the best examples of the do-while loops above.
while (true) {
printf("enter a number");
scanf("%c", &c);
if (!(c < '0' || c > '9')) break;
}
This next example is a case where the structure is more readable than a do-while since the condition is kept near the top as //get data is usually short yet the //process data portion may be lengthy.
while (true) {
// get data
if (data == null) break;
// process data
// process it some more
// have a lot of cases etc.
// wow, we're almost done.
// oops, just one more thing.
}
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.
If you look above, the reply from TimW, it speaks for itself. The second one with Handle, especially is more messy in my opinion.
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.
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
LoopBody()
while(cond) {
LoopBody()
}
I hardly ever use them simply because of the following:
Even though the loop checks for a post-condition you still need to check for this post condition within your loop so that you don't process the post condition.
Take the sample pseudo code:
do {
// get data
// process data
} while (data != null);
Sounds simple in theory but in real world situations it would probably turn out to look like so:
do {
// get data
if (data != null) {
// process data
}
} while (data != null);
The extra "if" check just isn't worth it IMO. I have found very few instances where it's more terse to do a do-while instead of a while loop. YMMV.
In response to a question/comment from unknown (google) to the answer of Dan Olson:
"do { ... } while (0) is an important construct for making macros behave well."
#define M do { doOneThing(); doAnother(); } while (0)
...
if (query) M;
...
Do you see what happens without the do { ... } while(0)? It will always execute doAnother().
A do-while loop can always be rewritten as a while loop.
Whether to use only while loops, or while, do-while, and for-loops (or any combination thereof) depends largely on your taste for aesthetics and the conventions of the project you are working on.
Personally, I prefer while-loops because it simplifies reasoning about loop invariants IMHO.
As to whether there are situations where you do need do-while loops: Instead of
do
{
loopBody();
} while (condition());
you can always
loopBody();
while(condition())
{
loopBody();
}
so, no, you never need to use do-while if you cannot for some reason. (Of course this example violates DRY, but it's only a proof-of-concept. In my experience there is usually a way of transforming a do-while loop to a while loop and not to violate DRY in any concrete use case.)
"When in Rome, do as the Romans."
BTW: The quote you are looking for is maybe this one ([1], last paragraph of section 6.3.3):
From my experience, the do-statement is a source of error and confusion. The reason is that its body is always executed once before the condition is tested. For the correct functioning of the body, however, a similar condition to the final condition has to hold in the first run. More often than I expected I have found these conditions not to be true. This was the case both when I wrote the program in question from scratch and then tested it as well as after a change of the code. Additionally, I prefer the condition "up-front, where I can see it". I therefore tend to avoid do-statements.
(Note: This is my translation of the German edition. If you happen to own the English edition, feel free to edit the quote to match his original wording. Unfortunately, Addison-Wesley hates Google.)
[1] B. Stroustrup: The C++ programming language. 3rd Edition. Addison-Wessley, Reading, 1997.
consider something like this:
int SumOfString(char* s)
{
int res = 0;
do
{
res += *s;
++s;
} while (*s != '\0');
}
It so happens that '\0' is 0, but I hope you get the point.
My problem with do/while is strictly with its implementation in C. Due to the reuse of the while keyword, it often trips people up because it looks like a mistake.
If while had been reserved for only while loops and do/while had been changed into do/until or repeat/until, I don't think the loop (which is certainly handy and the "right" way to code some loops) would cause so much trouble.
I've ranted before about this in regards to JavaScript, which also inherited this sorry choice from C.
Well maybe this goes back a few steps, but in the case of
do
{
output("enter a number");
int x = getInput();
//do stuff with input
}while(x != 0);
It would be possible, though not necessarily readable to use
int x;
while(x = getInput())
{
//do stuff with input
}
Now if you wanted to use a number other than 0 to quit the loop
while((x = getInput()) != 4)
{
//do stuff with input
}
But again, there is a loss in readability, not to mention it's considered bad practice to utilize an assignment statement inside a conditional, I just wanted to point out that there are more compact ways of doing it than assigning a "reserved" value to indicate to the loop that it is the initial run through.
I like David Božjak's example. To play devil's advocate, however, I feel that you can always factor out the code that you want to run at least once into a separate function, achieving perhaps the most readable solution. For example:
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
could become this:
int main() {
char c = askForCharacter();
while (c < '0' || c > '9') {
c = askForCharacter();
}
}
char askForCharacter() {
char c;
printf("enter a number");
scanf("%c", &c);
return c;
}
(pardon any incorrect syntax; I'm not a C programmer)