tags:

views:

1055

answers:

12

I'm currently working through the excercises in 'The C Programming Language'. Here's one of my solutions:

int c;

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

if (c == ' ') {

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

    {}  // do nothing?

    putchar(' ');

}

putchar(c);

}

I found some solutions here that are quite different to mine and use an extra variable to keep track of what's going on, whereas I just use a while loop to skip through all the spaces. My solution feels a bit messy, as it seems bit hackish to have a while loop with nothing between the curly braces. I was wondering if there are any good reasons not to do this? Thanks for any advice :-)

+1  A: 

I don't think the procedure is, but your formatting is pretty weird. There's nothing wrong with:

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

(that is, indicate there's intentionally not a body)

Dustin
Ah I didn't realise I could format it like that, lol :) Thanks!
good use of comments. I tend to avoid empty while loops. It always seems like a typo at first, so I to look at it twice before I realize that it was intentional, and then look at it a third time to figure out what it does. They just aren't all that readable IMO.
Al W
Readable is really subjective. I *always* put braces where I can, so this would stick out quite obviously to me in codebases I work on.
Dustin
+11  A: 

Not at all - I believe you'll find do-nothing loops like these in K&R, so that's about as official as it gets.

It's a matter of personal preference, but I prefer my do-nothing loops like this:

while(something());

Others prefer the semicolon to go on a separate line, to reinforce the fact that it's a loop:

while(something())
  ;

Still others prefer to use the brackets with nothing inside, as you have done:

while(something())
{
}

It's all valid - you'll just have to pick the style you like and stick with it.

Kyle Cronin
I tend to like to put a "continue" to an empty loop: "while (foo) continue;". This makes the no-op nature of the loop clearer to the reader, I think, but that's a very minor stylistic issue.
Lars Wirzenius
Never thought of that. Good idea liw.fi!
jmucchiello
A: 

I've used code like this. I don't think there's really any reason not to use it if the situation warrants it.

recursive
+4  A: 

I think it is perfectly acceptable.

I would either write it:

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

to make it obvious that this one line of code does one thing.

Or I would write it like this:

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

so that it matches the rest of your code's format.

Personally, I am not a fan of the

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

format. I think it is to easy to overlook the semi-colon.

BlueWaldo
+1 I posted a similar sentiment towards the semi-colon, but yours was more in-depth.
Alex Lyman
+4  A: 

Well if you really don't like the empty braces, you could refactor that inner loop into

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

This costs one extra comparison though, so a do while loop would be better.

Cebjyre
Better might be:do { c = getchar(); } while (c == ' ');Unless, of course, c is known to == ' ' prior to entering the loop.
Tim Post
In this case it is, but it's a good point to make.
Kyle Cronin
A: 

I thinks no problem in it. You can use it, In many situations i prefer it.

Nakul Chaudhary
A: 

I would favor

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

I've also been known to have a procedure named DoNothing specifically for calling in cases like this. It makes it very clear that you really mean to do nothing.

While non-existent loop bodies are perfectly acceptable it should be VERY clear that it's intentional.

Loren Pechtel
The only change I would make is to put the semicolon before the comment
Kyle Cronin
+4  A: 

Your question "Is using a while block to do nothing a bad thing?" may also be answered in terms of wasting CPU cycles. In this case the answer is "No", since, the process will sleep while it waits for the user to input a character.

The process will wake only after a character is input. Then the test will occur and if the test passes, i.e. c == ' ', the process will go to sleep again until a the next character is entered. This repeats until a non-space character is entered.

jeffD
A: 

The canonical way — used since time immemorial, have a look, eg, at the Lyons book — is

while(condition)       // Here's the whole thing
    ;                  // empty body.

In fact, in general the 'semicolor on a separate line' convention is used for a null statement. You will, for example, occassionally see

if( condition-1)
     ;
else if (condition-2)
     stmt;
else {
     // do stuff here
}

It's a lot more uncommon, but shows up either where condition-1 is very complicated, so you don't want to negate it and chance confusion, or where the code has been hand-optimized within an inch of its life, so that you want the most common case first.

The

while(condition) ;

form is to be slavishly avoided, because that's a common and annoying typo: you should make it clear that you did it on purpose. Empty braces

 while(condition){
 }

or its variants, are also trouble because they either don't stand out enough, or worse lead to other typos.

Charlie Martin
A: 

An alternative option which hasn't been mentioned yet:

while(condition)
    (void)0;

I really do not prefer to write my loops this way, but I had a TA last semester who did.

Anthony Cuozzo
Jonathan Leffler
@Jonathan: It wasn't my idea :-) I don't write loops that way.
Anthony Cuozzo
A: 

Well, not really but it depends on your architecture.

if (dosomething()) { ; }

The above is going to constantly be pushing and popping from your local stack, which has a memory overhead. Also, you will also be flushing your processors' pipelines with noop operations.

thesmart
A good compiler is not going to emit NOPs.
jmucchiello
+2  A: 

A while that does nothing probably is a bad thing:

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

... is a really, really, expensive way to block.

However your loop is not doing nothing:

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

... because it is calling getchar() on every iteration. Hence, as everyone else has agreed, what you've done is fine.

slim