Understanding the enhanced syntax of for loop - c

I found the following for loop that I cannot understand why it looks different than the traditional one, i.e. (init; condition; increment):
int parent, i, indx;
for (; indx; indx = parent) {
parent = (indx - 1) / 2;
if (h->queue[parent] >= value) break;
h->queue[indx] = h->queue[parent];
}
Can someone explain how to convert it to be in the form of (init; condition; increment)?

In a for loop, each of the initialization, termination, and step expressions can be omitted. If the initialization step is skipped, there's no initialization done. If the step is skipped, no step is performed. If the test is skipped, the loop runs until it's broken out of.
Rather than trying to rewrite this loop to include all three expressions, I'd recommend investing the time to learn this syntax, since statements like these aren't all that uncommon.

for (; indx; indx = parent)
is the standard C for-loop. It simply has a blank (no instructions) for the initialization option.

Related

Iterative Statements

So, I have been studying iterative statements for a report. While I was reading, I came across the developmental history of definite iteration and eventually learn the for loop. We know that the syntax for the for loop in C,C++, and java is
for (expression1; expression2; expression3)
statement
And it says here that we can omit any of the expression and that it is legal to have a for loop that look like this
for (;;)
My question is how does that work? I cant find any more resources for this one.
A for loop declared as:
for (init-statement; condition; iteration-expression) body;
Is equivalent to:
init-statement;
while (condition) {
body;
iteration-expression;
}
It's easy to see how init-statement or iteration-expression could be omitted. If the condition is omitted, it is assumed to be true.
A reasonable resource that explains this is the Explanation section of the for loop documentation at cppreference.com.
Basically, for (;;) is legal, but you will need to put something inside the body of that for loop, otherwise the loop will never stop.
int counter = 0;
int limit = 5;
for (;;) {
if (counter > limit) break;
counter++;
}

Can someone explain how this works? [duplicate]

I saw this code:
if (cond) {
perror("an error occurred"), exit(1);
}
Why would you do that? Why not just:
if (cond) {
perror("an error occurred");
exit(1);
}
In your example it serves no reason at all. It is on occasion useful when written as
if(cond)
perror("an error occured"), exit(1) ;
-- then you don't need curly braces. But it's an invitation to disaster.
The comma operator is to put two or more expressions in a position where the reference only allows one. In your case, there is no need to use it; in other cases, such as in a while loop, it may be useful:
while (a = b, c < d)
...
where the actual "evaluation" of the while loop is governed solely on the last expression.
Legitimate cases of the comma operator are rare, but they do exist. One example is when you want to have something happen inside of a conditional evaluation. For instance:
std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
// Do something to each backslash in `example`
}
It can also be used in places where you can only place a single expression, but want two things to happen. For instance, the following loop increments x and decrements y in the for loop's third component:
int x = 0;
int y = some_number;
for(; x < y; ++x, --y)
{
// Do something which uses a converging x and y
}
Don't go looking for uses of it, but if it is appropriate, don't be afraid to use it, and don't be thrown for a loop if you see someone else using it. If you have two things which have no reason not to be separate statements, make them separate statements instead of using the comma operator.
The main use of the comma operator is obfuscation; it permits doing two
things where the reader only expects one. One of the most frequent
uses—adding side effects to a condition, falls under this
category. There are a few cases which might be considered valid,
however:
The one which was used to present it in K&R: incrementing two
variables in a for loop. In modern code, this might occur in a
function like std::transform, or std::copy, where an output iterator
is incremented symultaneously with the input iterator. (More often, of
course, these functions will contain a while loop, with the
incrementations in separate statements at the end of the loop. In such
cases, there's no point in using a comma rather than two statements.)
Another case which comes to mind is data validation of input parameters
in an initializer list:
MyClass::MyClass( T const& param )
: member( (validate( param ), param) )
{
}
(This assumes that validate( param ) will throw an exception if
something is wrong.) This use isn't particularly attractive, especially
as it needs the extra parentheses, but there aren't many alternatives.
Finally, I've sometimes seen the convention:
ScopedLock( myMutex ), protectedFunction();
, which avoids having to invent a name for the ScopedLock. To tell
the truth, I don't like it, but I have seen it used, and the alternative
of adding extra braces to ensure that the ScopedLock is immediately
destructed isn't very pretty either.
This can be better understood by taking some examples:
First:
Consider an expression:
x = ++j;
But for time being, if we need to assign a temporarily debug value, then we can write.
x = DEBUG_VALUE, ++j;
Second:
Comma , operators are frequently used in for() -loop e.g.:
for(i = 0, j = 10; i < N; j--, i++)
// ^ ^ here we can't use ;
Third:
One more example(actually one may find doing this interesting):
if (x = 16 / 4), if remainder is zero then print x = x - 1;
if (x = 16 / 5), if remainder is zero then print x = x + 1;
It can also be done in a single step;
if(x = n / d, n % d) // == x = n / d; if(n % d)
printf("Remainder not zero, x + 1 = %d", (x + 1));
else
printf("Remainder is zero, x - 1 = %d", (x - 1));
PS: It may also be interesting to know that sometimes it is disastrous to use , operator. For example in the question Strtok usage, code not working, by mistake, OP forgot to write name of the function and instead of writing tokens = strtok(NULL, ",'");, he wrote tokens = (NULL, ",'"); and he was not getting compilation error --but its a valid expression that tokens = ",'"; caused an infinite loop in his program.
The comma operator allows grouping expression where one is expected.
For example it can be useful in some case :
// In a loop
while ( a--, a < d ) ...
But in you case there is no reason to use it. It will be confusing... that's it...
In your case, it is just to avoid curly braces :
if(cond)
perror("an error occurred"), exit(1);
// =>
if (cond)
{
perror("an error occurred");
exit(1);
}
A link to a comma operator documentation.
There appear to be few practical uses of operator,().
Bjarne Stroustrup, The Design and Evolution of C++
Most of the oft usage of comma can be found out in the wikipedia article Comma_operator#Uses.
One interesting usage I have found out when using the boost::assign, where it had judiciously overloaded the operator to make it behave as a comma separated list of values which can be pushed to the end of a vector object
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope
{
vector<int> values;
values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container
}
Unfortunately, the above usage which was popular for prototyping would now look archaic once compilers start supporting Uniform Initialization
So that leaves us back to
There appear to be few practical uses of operator,().
Bjarne Stroustrup, The Design and Evolution of C++
In your case, the comma operator is useless since it could have been used to avoid curly braces, but it's not the case since the writer has already put them. Therefore it's useless and may be confusing.
It could be useful for the itinerary operator if you want to execute two or more instructions when the condition is true or false. but keep in mind that the return value will be the most right expression due to the comma operator left to right evalutaion rule (I mean inside the parentheses)
For instance:
a<b?(x=5,b=6,d=i):exit(1);
The boost::assign overloads the comma operator heavily to achieve this kind of syntax:
vector<int> v;
v += 1,2,3,4,5,6,7,8,9;

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.

For versus while versus do loop statements

Is there a difference between for and while statements? Is it just syntax?
#include <stdio.h>
void main() {
int cent_temp = 0;
int fah_temp;
while (cent_temp <= 20) {
fah_temp = (9 * cent_temp) / 5 + 32;
printf("%d degrees C = %d degrees F\n", cent_temp, fah_temp);
cent_temp++;
}
}
This means to me....
While the value of cent_temp is less than 20 then calculate fah_temp. Then increase the value of cent_temp by 1 and check it is still less than 20; then go round the loop again.
Regarding the syntax:
printf("%d degrees C = %d degrees F\n", cent_temp, fah_temp);
This means %d means print to the screen, replace with a decimal number the value of cent_temp and %d means replace with a decimal number the value of fah_temp.
#include <stdio.h>
void main() {
int cent_temp;
int fah_temp;
for (cent_temp = 0; cent_temp <= 20; cent_temp++) {
fah_temp = (9 * cent_temp) / 5 + 32;
printf("%2d degrees C = %2d degrees F\n", cent_temp, fah_temp);
}
}
My interpretation of the above is:
for cent_temp = 0 repeat while cent_temp less than 20 and then execute cent_temp+1 at the end. So cent_temp 0 goes into the loop to calculate fah_temp and gets printed to the screen. Then cent_temp goes up by one then goes round the loop again. Here I've used %2d instead of %d to signify that it should have 2 spaces for a decimal number (and they line up when executed). Both codes will not execute if cent_temp > 20.
Similarly rearranging the statement in a do while loop has a similar effect and doesn't really have an impact on the result.
Does each type of loop have a different application?
Please correct me if I wrong!
Is there a difference between 'for' and 'while' statements? Is it just
syntax?
To me, it is just syntax.
From K&R section 3.5 Loops -- While and For, I quote:
The for statement
for (expr1; expr2; expr3)
statement
is equivalent to
expr1;
while (expr2) {
statement
expr3;
}
except for the behavior of continue.
Grammatically, the three components of a for loop are expressions.
Most commonly, expr1 and expr3 are assignments or function calls
and expr2 is a relational expression.
Notes
As user #chqrlie has mentioned in the comments, control statements like break and continue make the situation slightly murkier.
There are some situations where the modify statement is necessary in the loop body. For example Erase-remove idiom with std::set failing with constness-related error (in C++ though)
Example
As an example, let us write a loop to print all the odd numbers between 1 and 100.
int i = 1;
while (i <= 100) {
printf("%d\n", i);
i += 2;
}
for (int i = 1; i <= 100; i += 2) {
printf("%d\n", i);
}
Opinion
I am not a language expert, but in most situations in practice I find them transformable.
I personally prefer using for syntax because:
loop control structure is in one single place (the for header) making it easy to read, and
the loop variable (e.g. i) is not exposed to the outer scope.
for(cent_temp = 0; cent_temp <= 20; cent_temp++)
{ /* code */ }
is 100% equivalent to
cent_temp = 0;
while(cent_temp <= 20)
{
/* code */
cent_temp++;
}
But a do-while is different since it puts the condition check at the end.
As for when to use which loop, it is a matter of style and therefore a bit subjective. The industry de facto standard style, used by the majority of all C programmers, goes like this:
for loops should always be used when performing a known number of iterations. It is then considered the most readable form.
while loops should be used the the number of iterations is unknown in advance, or when the loop is turning complex for some reason. For example if you need to alter the loop iterator variable inside the loop body, then you should use a while loop instead of a for loop.
do while loops should be used for special cases where you need to skip the condition check the first lap of the loop, for example do { result = send(); } while(result == ok);.
I looked at my Code Complete by Steve McConnell (the bible).
Here is what you can read in chapter 16:
A for loop is a good choice when you need a loop that executes a specified number of times. [...]
Use for loops for simple activities that don't require internal loops controls. Use them when the loop involves simple increments or simple decrements, such as iterating through the elements in a container. The point of a for loop is that you set it up at the top of the loop and then forget about it. You don't have to do anything inside the loop to control it. If you have a condition under which execution has to jump out of a loop, use a while loop instead.
Likewise, don't explicitly change the index value of a for loop to force it to terminate. Use a while loop instead. The for loop is for simple uses. Most complicated looping tasks are better handled by a while loop.
In general, you would use a for loop to iterate over a finite set of values, whereas you'd use a while or do-while loop to iterate while a specific condition or set of conditions is true. In most of C's contemporaries (Basic, Pascal, Fortran, etc.), a for loop can only iterate over a scalar index:
Fortran:
DO 10 i=1,10
statements
10 CONTINUE
Pascal:
for i := 1 to 10 do
begin
statements
end;
Both of these snippets loop exactly 10 times. The index i is initialized and updated by the loop automagically. I'd have to go back and check, but I'm pretty sure you cannot write to i in the loop body.
C actually blurred the lines between a for and while loop by adding the control expression:
for ( init-expr ; control-expr ; update-expr )
statement
In C, a for loop can iterate over a scalar just like Fortran or Pascal:
for( i = 0; i < 10; i++ )
{
do_something_with( i );
}
Or it can iterate over multiple scalars:
for ( i = 0, j = 0; i < 10 && j < 10; i++, j++ )
{
do_something_with( i, j );
}
Or it can iterate over the contents of a file:
for( c = fgetc( in ); c != EOF; c = fgetc( in ) )
{
do_something_with( c );
}
Or it can iterate over a linked list:
for( cur = head; cur != NULL; cur = cur->next )
{
do_something_with( cur );
}
In Fortran and Pascal, those last three loops would have to be expressed as while loops (which I'm not going to do, because I've pretty much exhausted my Fortran and Pascal knowledge already).
The other big difference between a C for loop and those of Fortran or Pascal is that you can write to the loop index (i, j, c, or cur) in the loop body; it's not specially protected in any way.
A while or do-while loop is used to iterate as long as a specific condition or set of conditions is true:
while( control-expr )
statement
do
statement
while( control-expr );
In both a for and while loop, the condition is tested before the loop body executes; in a do-while loop, the condition is tested after the loop body executes, so a do-while loop will always execute at least once.
In C, you can use either a for loop or a while loop in many circumstances:
while ( ( c = fgetc( in ) ) != EOF )
do_something_with( c );
for ( c = fgetc( in ); c != EOF; c = fgetc( in ) )
do_something_with( c );
Both loops do exactly the same thing; it's just a matter of which one you think more clearly expresses your intent, or which you think would be easier for other people to understand.
From the point of view of algorithmic for and while are not the same. Shortly, in algorithmic, for should be used when bounds are known and while when you don't know if the condition can be met or when it can be. For is to repeat something n times (n known), which is exactly the case of your example computation; a for loop should be used (don't you think what the loop makes is more clearly stated in the for loop ?). If you want an example of a must be used while loop, look at something like Collatz sequence. From a point of view of computability, for loops can always be transformed in while loops but not the converse.
From the point of view of computer languages it is now common to fuse both, in C for example, it makes no difference, only syntactic. But remember that in some other language that could be very different, for example in Pascal for loops are very limited.
Source code is written not only to be compiled and executed by computers but also to be read and understood by humans.
A computer doesn't really mind whether a for loop, a while loop or a goto is used. On the other hand, a human expects different meanings for different structures.
computing values over a known range of inputs is best shown with a for loop;
reading a file up to its end is best shown with a while loop.
Choosing which structure to use is similar as choosing a variable name.

Can an empty for-loop be "correct"?

I have a doubt about the for loop of the following code in C:
main()
{
int i=1;
for(;;)
{
printf("%d",i++);
if(i>10)
break;
}
}
I saw this code in a question paper. I thought that the for loop won't work because it has no condition in it. But the answer says that the code has no error. Is it true ? If true, how ?
The regular for loop has three parts:
Initialization
Condition
Increment
Usually they are written like this:
for (initialization; condition; increment) { statements }
But all three parts are optional. In your case, all parts are indeed missing from the for loop, but are present elsewhere:
The initialization is int i=1
The condition is if (i>10) break
The increment is i++
The above code can be equivalently written as:
for (int i=1; i <= 10; i++) {
printf("%d", i);
}
So all the parts necessary for a for loop are present, except they are not inside the actual for construct. The loop would work, it's just not a very readable way to write it.
The for (;;) loop is an infinite loop, though in this case the body of the loop takes actions that ensure that it does not run forever. Each component of the control is optional. A missing condition is equivalent to 1 or true.
The loop would be more clearly written as:
for (int i = 1; i < 11; i++)
printf("%d", i);
We can still debate whether the output is sensible:
12345678910
could be produced more easily with:
puts("12345678910");
and you get a newline at the end. But these are meta-issues. As written, the loop 'works'. It is syntactically correct. It also terminates.
You are not specifying any parameters or conditions in your for loop, therefore, it would be an endless loop. Since there is a break condition based on another external variable, it would not be infinite.
This should be re-written as:
for (int i = 1; i <= 10; i++)
printf("%d",i++);
It's an infinite loop. When there is not a condition in for and we use ;; the statements in the body of for will be executed infinitely. However because there is a break statement inside it's body, if the variable i will be greater than 10, the execution will be stopped.
As it is stated in MSDN:
The statement for(;;) is the customary way to produce an infinite loop which can only be exited with a break, goto, or return statement.
For further documentation, please look here.
Even if a for loop is not having any condition in it, the needed conditions are specified inside the for loop.
The printf statement has i++ which keeps on increasing the value of i and next we have if statement which will check if value of i is less than 10. Once i is greater than 10 it will break the loop.

Resources