Is using a while block to do nothing a bad thing? - c

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 :-)

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.

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.

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.

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.

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 wait -- it'll use as much CPU as the OS will give it, for as long as ready is false, stealing CPU time with which the other thread could be doing useful work.
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.

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)

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.

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.

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

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

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.

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.

Related

Why not combine the "for" and "while" loop to a single loop?

I'm currently making my own programming language for fun using Ruby and wondering why having a "while" and "for" loop is something so universal. Why is it be bad to just have a single "loop" keyword?
ex)
loop (True) # acts as a while loop with a condition
loop var in 1..20 # acts as a for loop
loop var in list # acts as a for each loop
Would this somehow be disadvantageous or is the "while" and "for" loop simply just for semantic and readability?
In fact, there are even more loop-variants. For example do-while.
To answer your question:
Yes, all of them can be used to do the same thing. However, depending on the loop-variant you use, you implicitly say what this loop does.
For example, you only use a for-loop if you know how often you want to loop (e.g. for each item in a list (i know, there is also a foreach in many languages)). It is considered bad habit to modify the loop variable inside a for-loop.
So if you are not sure how often you will loop, you should most likely use something else than a for-loop... for example a while-loop.
Here are some simple code examples:
for(i = 0; i < someList.Length; i++) {
// do some stuff x times
}
while(someValue < someOtherValue) {
someValue = someValue * someValue;
}
For me it is clear, that i should not use a for-loop for the 2nd loop.
To sum up: Yes, you only need one loop construct. However, I personally (!) like to have the advantage to actually say something just by the choice which loop i take.
Would this somehow be disadvantageous or is the "while" and "for" loop simply just for semantic and readability?
I think that your idea would not be disadvantageous and, yes, while and for are chosen for semantics/readability (or even historical reasons). Then, there are slightly different meanings in every language. Often, the for loop implies that you have a control variable. From the classic basic
for i=1 to 10 ... (next i)
to pascal, and even in more advanced constructs (iterators) from python, this idea is respected. Moreover, in some languages (pascal, for example) a for implies that the low-high limits are pre-calculated. This pascal code for example:
B := 5;
for i := 1 to B do begin
B := 25
end;
can give warnings or errors, or can lead to 5 iterations even if in the body of the loop the upper limit is modified. The C language, which also has for, is totally different, even if the general idea of "control variable" is respected in 99% of the cases. The C for does not pre-compute limits (by design), can have more than one control variable, or even none at all:
for ( ; ; ) ...
is a valid for loop which does not have a control variable (and no meaning to break the loop!).
On the other hand, while, repeat, do ... while and so on are semantically clear (you can "talk" the code with your voice, and everything is self explaining), and do not imply variables (they imply nothing).
The above loops all have a common problem: they have a test which is performed at the beginning (or the end) of every iteration. Suppose you want to read characters from standard input, do something with them, and stop when this character is EOF. The C way is:
while ( ( ch=getchar() ) != EOF) ... ; // do something with ch
The C language can do this because an assignment is also an expression. If it was not so, one had to write:
ch=getchar();
while (ch != EOF) {
.... ; // do something with ch
ch = getchar();
}
// I must use two times the statement "ch = getchar();"
// or...
do {
ch = getchar();
if (ch == EOF) break;
... ; // do something with ch
} while (true)
// I use getchar() only once, but I end up with an awful "while (true)"
In your new language, you could invent a different cycle which goes like this:
cycle
// statements always executed at least once
when (condition)
// statement executed if the condition is true
// and, if true, the cycle restarts
end
With this syntax, the example about getchar() would become:
cycle ch=getchar(); when (ch != EOF) ... ; // do something bla bla bla...
The normal while, while (true) and do-while loops would become:
cycle when (condition); BODY // while
cycle BODY; // while (true)
cycle BODY; when (condition) // do-while
Think about it... :-)
Most languages have for and while for historical reasons and familiarity. Familiarity is important: if you reuse the same concepts and keywords as other languages, your language is easier to learn. Many languages use "!" for the negation for this reason (many other languages use "not"). Look at this page comparing syntax across languages, you'll see lots of similarities: http://rigaux.org/language-study/syntax-across-languages.html
Now, to answer your question. Although most languages have the while keyword, you really don't need it.
Best example I can think of is Go:
// C-like for
for i := 0; i < 10; i++ {
sum += i
}
// while
for sum < 1000 {
sum += sum
}
// infinite loop
for {
}
// do .. while
for ok := true; ok; ok = condition {
...
}
// range-for
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
So, as you can see, it's perfectly possible to use a single keyword for all loops.
Main reason for having both for and while is familiarity and readability. But you can easily do without.

Is it possible for an IF statement to be in the for loop's third expression (C)?

While learning from K&R, I tried to modify the while loop in exercise 1.5.3 in to a for loop:
#include <stdio.h>
main()
{
int c, nl;
for (nl = 0; (c = getchar()) != EOF; if (c == '\n'){++nl}){}
printf("%d\n", nl);
}
SIDE NOTE: I apologize if this code looks abominable. For now, I am just trying to write valid C code, and when I feel that I have adapted to the language's general concepts, I will start writing code for "humans."
When I try to build and run the code, this message appears,
error: expected expression before 'if'
I tried to search this error, but I could only find answers that either referred to other languages or ternary operations, which I would like to avoid if possible. Thanks in advance for any insight into resolving this issue, if it even is one.
No, but if you really want to squeeze it in the loop (although I would not recommend it), you could do
nl += (c == '\n')? 1: 0
Or, as #LogicG8 suggested, just
nl += (c == '\n')
although it is a bit less clear and may violate some coding guidelines.
No, not possible. The third clause has to be an expression and if statements are statements, not expressions.
if is a statement, the header of a for loop can only contain expressions, not statements.
You can use a ternary operator there, it's the way to perform a conditional in an expression.
for (nl = 0; (c = getchar()) != EOF; (c == '\n') ? ++nl : 0) {}
In short: This is not possible, you could use some inline-ifs somehow, though.
But, even in case it would work, you shouldn't do it because....
...the simpler the for-loop, the better the optimization. Don't confuse the compiler.
...you might also confuse other developers if they have to read and unerstand that code.
Keep it simple whenever possible.

shorthand C while loop

Quick one. Are the following equivalent? And are any of them more economical or "correct" than the others?
while (x==y) {}, while (x==y) ; & while (x==y);.
Note the white space between the closing expression bracket and the semicolon in the second one and not in the third.
I have tended to use the first one in the past.
Ta
There's no difference between the second and third one.
The only difference for the first is readability - you're explicitly stating you want an infinite loop, not that you have a typo (extra ;).
They're all exactly equivalent and should produce identical programs with any half-sane compiler. The whitespace is not significant and both {} and ; represent the empty statement.
Usually when you'd doing something like this, you still put the semicolon on its own line to make it clear that it wasn't just added by acident:
while (whatever)
;
Of course, you usually only do that when whatever has side-effects, such as:
// skip to end of line:
while (((ch=getchar()) != '\n') && (ch != EOF))
;
The exact syntactic form of empty statement you use is extremely unlikely to affect the code produced though, so this is purely about optimizing for the reader, not the compiler.

Lower cpu usage on searching a big char array

I'm searching for few bytes in a char array. The problem is that on slower machines the process gets up to 90%+ cpu usage. How to prevent that? My code is:
for(long i = 0; i < size - 5; ) {
if (buff[++i] == 'f' && buff[++i] == 'i' && buff[++i] == 'l' && buff[++i] == 'e') {
printf("found at: %d\n", i);
}
}
EDIT:
The string "file" is not null-terminated.
This looks like an attempt at very naive string search, I'd suggest you use either the standard functions provided for this purpose (like strstr) and/or research string search algorithms like Boyer-Moore.
The linked Wikipedia article on Boyer-Moore shows quite well why moving along one character at a time on a mismatch (like you do) is not necessary - it's an interesting read.
EDIT: also look at this page, it has a nice animated presentation that shows how BM does its job.
EDIT2: regarding the string not being nullterminated: either you
buff[size] = 0;
terminate it yourself, and use strstr, or you have a look at the BM code from the page I linked, that works with lengths, ie it will work with strings without terminating 0.
There is nothing wrong with getting 90% utilisation, since the algorithm is CPU-bound. But...
Unless you expect the search term to be on a 32-bit word boundary, the code is broken. If the word 'file' begins on the second character of the buffer, you will simply skip over it. (EDIT: Short-circuit eval means the code is correct as it stands. My mistake.)
Don't roll your own code for this; use strstr.
Try just storing a list of values where 'file' is found and print them out after the loop. It will prevent context switches and will enable the CPU to use the cache better. Also put i in a register.

Is the code "while(condition);" valid and what does it mean?

Can we put semicolon like while(condition); in a C Programming?
If while(condition); is valid, what does it mean?
while (condition);
is the same as
while (condition)
{
}
It can be used for waiting loops, e.g.:
while (!isLightGreen()); // waits until isLightGreen() returns true
go();
It means the body of the loop is empty. Typically this pattern is used when the condition itself does some work.
For example, this loop can copy bytes within the condition:
while ( '\0' != (*pt++ = *ps++))
;
If you're using a semicolon, it's a good idea to put it on a separate line so that it looks less like a mistake. I personally tend to use empty braces -- {}, and sometimes a comment that the empty block is intentional.
Edit:
In the second comment, Tom Anderson notes an improvement over a lone semicolon. Google's C++ style guide recommends either this or {}.
while ( '\0' != (*pt++ = *ps++))
continue;
Yes, you can. It just means that the while loop will keep looping until condition is false. For example:
#include<stdio.h>
int x = 10;
int func()
{
printf("%d\n", x);
return --x;
}
int main()
{
while(func());
return 0;
}
But generally people don't do this, as it would make more sense to put the logic in the body of the loop.
Edit:
There are some examples of this in use, for example, copying a null-terminated string:
char dest[256];
char *src = "abcdefghijklmnopqrstuvwxyz";
while(*(dest++) = *(src++));
Because the condition may actually have side effects, such a construct is allowed. Consider the following:
while (*p && *p++ != ' ');
This would advance the p pointer to the first character that is a space.
You may even use the comma operator to have ordinary statements inside the condition:
while (do_something(), do_something_else(), i < n);
Because statements connected with the comma operator evaluate to the rightmost statement, in that case i < n, the above is identical to:
do {
do_something();
do_something_else();
} while (i < n);
It will keep evaluating condition until it's false. It is a loop without a body.
Programmers often add a space before the semicolon, i.e.
while(condition) ;
or empty braces:
while(condition) {}
to show the empty body is intentional and not just a typo. If you are reading some existing source code and wondering why there is an empty loop there you should read the next few lines as well to see if the semicolon should really be there or not (i.e. do the next few lines look like the body of a loop or not?).
Yes, it's correct. It will loop the condition until it's false.
while ( condition() );
I always write this as:
while (condition())
continue;
So that it's obvious that it wasn't a mistake. As others have said, it only makes sense when condition() has side effects.
while() is a loop. You're probably looking to do a "do-while" loop. Do-while loops run in this format:
do
{
// Your process
// When something goes wrong or you wish to terminate the loop, set condition to 0 or false
} while(condition);
The one you have listed above, however, is an empty loop.
while() loops work nearly the same; there is simply no "do" portion.
Good luck!
It means that keep checking condition until it evaluate to false
The key to understanding this is that the syntax of the while loop in "C" is as follows:
while (condition) statement
Where statement can be any valid "C" statement. Following are all valid "C" statements:
{ statements } // a block statement that can group other statements
statement; // a single statement terminated by a ;
; // a null statement terminated by a ;
So, by the rules of the while loop, the statement part (null statement in your example) will execute (do nothing) as long as condition is true. This is useful because it amounts to a busy wait till the condition turns false. Not a good way to wait, but useful nevertheless. You could use this construct, for example, if you want to wait for another thread (or a signal handler) to set a variable to some value before proceeding forward.
The code while(condition); is perfectly valid code, though its uses are few. I presume condition is a variable, not a function — others here discuss functional condition.
One use of while(condition); may be to block while waiting for a signal e.g. SIGHUP, where the signal handler changes the variable condition. However, this is usually not the best way to wait for a signal. One would typically use a sleep in the loop i.e. while(condition) { sleep(1); }.
The absence of any sleep means that the loop will be continually processing in the interim, and likely wasting processing cycles. Unless the process has its resources managed (and even there...), I think this is only suitable where the loop needs to be broken in an interval less than the granularity of the available sleep command (i.e. sleep is granulated by the second, but you need the code after the look executed with sub-second response time). That being said, a blocking pipe or socket may be preferable to signals, performance wise – though I don't have any emperical data to back that up offhand, and I suspect performance may vary significantly depending on the platform.
One could have condition modified by a parallel thread of the same process, but I'd think one should prefer to do that by way of a mutex or semaphore (i.e. condition may need to be more than a simple variable).
I hope that's helpful, or at least food for thought!
It is just an empty loop. It would help if you explained what the condition is.
If the evaluation of the condition does not modify a value that influences the condition itself, while(condition); is an empty infinite loop, meaning it will never terminate (and never do anything except consuming CPU time).
it is absolutely correct. it means doing nothing in the loop,just polling the condition.And it is common in embedded system`s codes.
Its just a while loop with no execution body
while(condition);
is same as
while(condition)
{
}
Just another usage not described here:
do
{
if(out_of_memory)
break;
if(file_does_not_exist)
break;
return ok;
} while(0);
return error;
This allows you to avoid several return calls or goto statements.

Resources