tags:

views:

668

answers:

9

Sorry for the newb question. I'm still learning programming. So I'm using C++, and I need to do something like this:

int n;
do {
    n = get_data();
    if(n != -1)
        send(n);
} while(n != -1);

This is just a sketch. Anyway it doesn't feel real elegant. I have to have my test twice. I could just test once and set a flag, but that doesn't feel real elegant either since I have to check the flag twice. It just seems like there should be a way to do this more easily, since it's so easy what I want to do.

+13  A: 

Howabout using break:

int n;
while(1) {
    n = get_data();
    if(n == -1)
        break;
    send(n);
}

This way you only test once, and quit immediately if get_data doesn't return what you want.

Charlie
I prefer that because it is most expressive and scales even when get_data() gets more complex. In that case, I'd also add a comment describing the exit condition to the "eternal loop", e.g. // breaks when get_data() == -1.
peterchen
This is an instance of the well-known "Loop and a Half" construct: http://www.cs.duke.edu/~ola/patterns/plopd/loops.html#loop-and-a-half
Greg Hewgill
The most obvious and thus the most elegant it counts for me.
utku_karatas
+17  A: 
int n;
while (-1 != (n = get_data())) {
    send(n);
} // while
eed3si9n
I despise when people put the constant on the left side of the comparison.
SoapBox
Some of my former colleagues are offended by this construct (the side effect embedded in the conditional expression) and several textbooks tell you not to do that. I have never really understood why though - I think this is fine, but sometimes best avoided for political reasons.
finnw
You put the constant on the left so that it's a compiler error when you accidentally change == or != to the assignment operator (=). This isn't a problem anymore in most modern languages, especially with modern IDEs. I still do it in C++ code.
Bill the Lizard
Putting the constant on the left side of an expression does make it easier to avoid accidental bugs like if (n = -1)
Ed Marty
I'm surprised that no one commented on the '//while' at the end of such a short loop.
TM
Most compilers warn about making assignments within a statement that is being tested, and force you to put it inside another set of parentheses to enforce your intentions. If your compiler does not warn about this, or you ignore warnings, that is your problem, not the language's
dreamlax
Personally I like the -1 on the rhs (slightly easier to read (The compiler will warn on assignment and I compile with 0 warnings)). I have no problem with assignment in the condition where it makes the code easy to read. In this situation it is much easier to read than the original.
Martin York
Clinging to standards just because its not a good reason. The primary concern of any developer is maintenance of the code. Anything that makes the code easy(er) to understand (and thus maintain) overrides most concerns.
Martin York
Personally, I find SCFrench's easier to read.
Brian
+4  A: 

Your original version is fine.

In my last C programming job we had to follow the MISRA coding standards.

Under the MISRA rules, this:

int n;
while(1) {
    n = get_data();
    if(n == -1)
        break;
    send(n);
}

is prohibited because of the break, and this:

while((n = get_data()) != -1) { send(n); }

is prohibited because an assignment appears in a boolean context, so I am in the habit of writing loops similar to your original version.

You could a boolean variable if you think it will make your intention clearer or if the test is a complex expression:

int n;
bool valid;
do {
    n = get_data();
    valid = n != -1;
    if(valid)
        send(n);
} while(valid);

But for a simple test like "n != -1" it may not be worth making the program longer.

finnw
I could not find an online version of that MISRA standard (you can buy a book for $25, though...). From your description it feels kind of stupid, imposing a bulky coding style on the programmer.
Svante
Also, have a look at http://www.knosof.co.uk/misracom.html
Svante
@Harleqin, you're right, the resulting code can be bulky, some of the rules are overkill, and some others don't make sense outside embedded platforms.
finnw
MISRA enforces that no code gets to be write-only. Its rules are about making any program self-evident. Of course some may get you on performance, but as we all know, optimizations should be made after you have a functional program. If you get a clearly readable code, you allow others to re-use it.
jpinto3912
@jpinto3912 - from this examples it seems like MISRA can sometimes enforce the opposite.
orip
+12  A: 

Similar to eed3si9n's but arguably easier to read:

 int n;
 while (n = get_data(), n != -1)
 {
     send(n);
 }
SCFrench
I'd have to argue against the easrier to read. Most programmers don't understand the comma operator in C and stumble on this type of construct.
JaredPar
On the other hand, many programmers also have a hard time with the fact that operator= returns the assigned value, and its use can easily lead to bugs as mentioned elsewhere. But that's why I said "arguably" instead of "definitely" :-)
SCFrench
Even if your familiarity with the comma is lacking, this version does look much cleaner. I feel like someone who saw it but wasn't accustomed to commas would still be able to parse this faster than eed3si9n's version.
Brian
+8  A: 
for (int n = get_data(); n != -1; n = get_data()) {
  send(n);
}
Jonathan
Definitely the best/clearest solution to this.
Richard Corden
Take out the curly braces if you want to save a line :)
Jonathan
Yes, if you do want to make it shorter (which I don't), this would be the best way. A, at least, clever use of the for loop.
e-satis
A: 

Construct with a goto :)

int n;
goto inside; do {
  send(n);
inside:
  n=get_data();
} while(n!=-1);
lazyden
There's no difference between a do loop and a while loop if you never enter it from the top, is there? If not I would use the more familiar 'while' form.
finnw
Yes, you are right, there are no real difference. It is just a matter of personal taste :) I liked do-while form because lines with getting a data and line with a test over this data (loop condition) reside one after another.
lazyden
A: 
int get_data()
{
 ...
}

void _send(int )
{
 ...
}

int  send(int (*a) ())
{
   int n = a();

   if (n == -1)
      return n;

   _send(n);
   return 1;
}

int main()
{
  int (*fp)();
  fp = get_data;
  while ( send(fp)!= -1 );

  return 0;
}

HTH

plan9assembler
+1  A: 
int n;
n = get_data();
while (n != -1) {
  send(n);
  n = get_data();
}
gsarkis
A: 

In Python you would do this:

while True:
    n = get_data()
    if n == -1:
        break
    send(n)

As you can see, this is not much shorter than your C version. Usually, a Python code is 5 to 10 times smaller than its C equivalent. This is not the case here, so you can enjoy your readable, short enough, fast snippet, and focus on something else.

If you do want to make it shorter, check Jonathan's answer, but really this doesn't matter.

e-satis