Never seen before C++ for loop

C#C++For Loop

C# Problem Overview


I was converting a C++ algorithm to C#. I came across this for loop:

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

It gives no error in C++, but it does in C# (cannot convert int to bool). I really can't figure out this for loop, where is the condition?

Can someone please explain?

PS. Just to check, to adapt a VECTOR to a LIST does b.back() correspond to b[b.Count-1] ?

C# Solutions


Solution 1 - C#

The condition of the for loop is in the middle - between the two semicolons ;.

In C++ it is OK to put almost any expression as a condition: anything that evaluates to zero means false; non-zero means true.

In your case, the condition is u--: when you convert to C#, simply add != 0:

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE

Solution 2 - C#

Lots of accurate answers, but I think it's worth writing out the equivalent while loop.

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

Is equivalent to:

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

You might consider refactoring to the while() format as you translate to C#. In my opinion it is clearer, less of a trap for new programmers, and equally efficient.

As others have pointed out -- but to make my answer complete -- to make it work in C# you would need to change while(u--) to while(u-- != 0).

... or while(u-- >0) just in case u starts off negative. (OK, b.size() will never be negative -- but consider a general case where perhaps something else initialised u).

Or, to make it even clearer:

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

It's better to be clear than to be terse.

Solution 3 - C#

The condition is u--;, because it is in the second position of the for instruction.

If the value of u--; is different from 0, it will be interpreted as true (i.e., implicitly casted to the boolean value true). If, instead, its value is 0, it will be casted to false.

This is very bad code.

Update: I discussed the writing of "for" loops in this blog post. Its recommendations can be summarized in the following paragraphs:

> A for loop is a practical, readable (once you get used to it) and > terse construct, but you need to use it well. Because of its uncommon > syntax, using it in a too imaginative way is not a good idea. > > All parts of the for loop should be short and readable. Variable names > should be chosen to make it easy to understand.

This example clearly violates these recomendations.

Solution 4 - C#

This will be the C# form of your loop.

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

Just replace equivalent for size() and back().

What it does is reverses the list and stores in an array. But in C# we directly have system defined function for this. So you don't need to write this loop also.

b = b.Reverse().ToArray();

Solution 5 - C#

u = b.size(), v = b.back()

is initialization.

u--

is the condition.

v = p[v]

is the iteration

Solution 6 - C#

The condition is the result of u--, which is the value of u before it was decremented.

In C and C++, an int is convertible to bool by implicitly doing a != 0 comparison (0 is false, everything else is true).

b.back() is the last element in a container, which is b[b.size() - 1], when size() != 0.

Solution 7 - C#

In C everything non-zero is true in "boolean" contexts, such as the loop end condition or a conditional statement. In C# you have to make that check explicit: u-- != 0.

Solution 8 - C#

As stated by others, the fact that C++ has implicit casting to boolean means the conditional is u--, which will be true if the value is non-zero.

It's worth adding, that you've a false assumption in asking "where's the conditional". In both C++ and C# (and other similarly syntaxed languages) you can have an empty conditional. In this case it always evaluates to true, so the loop continues forever, or until some other condition exits it (via return, break, or throw).

for(int i = 0; ; ++i)
  doThisForever(i);

Indeed, any part of the for statement can be left out, in which case it's just not performed.

In general, for(A; B; C){D} or for(A; B; C)D; becomes:

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

Any one or more of A, B, C or D can be left out.

As a result of this, some favour for(;;) for infinite loops. I do because while while(true) is more popular, I read that as "until truth ends being true", which sounds somewhat apocalyptic compared to my reading for(;;) as "forever".

It's a matter of taste, but since I'm not the only person in the world to like for(;;) it's worth knowing what it means.

Solution 9 - C#

all the answers are correct :-

for loop can be used in a variety of ways as follows :

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.

Solution 10 - C#

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

In above code, u and v are initialized with b.size() and b.back().

Every time the condition is checked, it executes decrement statement too i.e. u--.

The for loop will exit when u will become 0.

Solution 11 - C#

The error encountered in C# itself clears the doubt. The for-loop searches for a

> FALSE

condition to terminate. And as we know,

> (BOOL) FALSE = (int) 0

but C# cannot process this on its own unlike as C++. So the condition you are searching for is

> u--

but you have to explicitly give the condition in C# as

> u-- != 0

or

> u-- > 0

But still try to avoid this kind of coding practice. The

> while loop

stated above in answer is one of the most simplified version of your

> for-loop.

Solution 12 - C#

If you're used to C / C++ this code isn't so hard to read, though it's pretty terse and not that great of code. So let me explain the parts that are more Cism than anything else. First off the general syntax of a C for loop looks like this:

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

The initialization code gets run once. Then the condition gets tested before every loop and lastly the increment gets called after every loop. So in your example you'll find the condition is u--

Why does u-- work as a condition in C and not C#? Because C implicitly converts a lot of things too bools and it can cause trouble. For a number anything that is non-zero is true and zero is false. So it will count down from b.size()-1 to 0. Having the side-effect in the condition is a bit annoying and it would be preferable to put it in the increment part of the for loop, though a lot of C code does this. If I were writing it I would do it more like this:

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

The reason for this is, to me at least, it's clearer. Each part of the for loop does it's job and nothing else. In the original code the condition was modifying the variable. The increment part was doing something that should be in the code block etc.

The comma operator may be throwing you for a loop also. In C something like x=1,y=2 looks like one statement as far as the compiler is concerned and fits into the initialization code. It just evaluates each of the parts and returns the value of the last one. So for example:

std::cout << "(1,2)=" << (1,2) << std::endl;

would print out 2.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThomasView Question on Stackoverflow
Solution 1 - C#Sergey KalinichenkoView Answer on Stackoverflow
Solution 2 - C#slimView Answer on Stackoverflow
Solution 3 - C#Daniel DaranasView Answer on Stackoverflow
Solution 4 - C#NarendraView Answer on Stackoverflow
Solution 5 - C#huseyin tugrul buyukisikView Answer on Stackoverflow
Solution 6 - C#Bo PerssonView Answer on Stackoverflow
Solution 7 - C#JoeyView Answer on Stackoverflow
Solution 8 - C#Jon HannaView Answer on Stackoverflow
Solution 9 - C#birubishtView Answer on Stackoverflow
Solution 10 - C#ApteView Answer on Stackoverflow
Solution 11 - C#AbhineetView Answer on Stackoverflow
Solution 12 - C#Matt PriceView Answer on Stackoverflow