7

Is another for loop allowed in the counter section (third part) of a for loop? In my attempt to get elegant in writing code to produce a right triangle, I wrote this but it wouldn't compile:

#include <stdio.h>
int main()
{   
    int i, j, N = 5;
    for (i = 1;
         i <= N; 
         (for (j = 1; j <= i; j++, printf("%c", '0'));), i++)
       printf("\n");
    }
    return 0;
}
10
  • 2
    Problems with your code: 1. What are the types of i, j, and N? 2. What is the value of N? 3. Where does the 3rd side get calculated? Commented Sep 7, 2014 at 17:15
  • 10
    "C/C++". There is no such language. Commented Sep 7, 2014 at 17:16
  • 13
    That construct seems to be more confusing than elegant to me. Commented Sep 7, 2014 at 17:18
  • 4
    @n.m. Metrowerks used to sell a compiler for the C/C++ language, with a pragma switching between compilation modes within a file. Although it is unlikely that the poster is using it or is even aware of it. Commented Sep 7, 2014 at 17:19
  • 4
    I don't think many people would consider a for-loop in the control section of another for-loop particularly "elegant" tbh. Commented Sep 7, 2014 at 17:45

8 Answers 8

7

No there are allowed only expressions or declarations.

EDIT: I am sorry. I thought you are speaking about the condition part of the loop. In the expression part of the loop there are allowed only expressions.

You could use a lambda expression that would contain this for loop. For example

for ( i = 1;
      i <= N;
      []( int i ) { for ( j = 1; j <= i; j++, printf("%c", '0' ) ); }( i ), i++)

Here is a demonstrative example

#include <iostream>

int main() 
{
    int N = 10;

    for ( int i = 1;
          i < N;
          []( int i ) 
          { 
            for ( int j = 1; j < i; j++, ( std::cout <<  '*' ) ); 
          }( i ), i++ )
    {
        std::cout << std::endl;
    }               

    return 0;
}

The output is

*
**
***
****
*****
******
*******
********

Or your could define the lambda expression outside the outer loop that to make the program more readable. For example

#include <iostream>

int main() 
{
    int N = 10;

    auto inner_loop = []( int i ) 
    { 
        for ( int j = 1; j < i; j++, ( std::cout <<  '*' ) ); 
    };


    for ( int i = 1; i < N; inner_loop( i ), i++ )
    {
        std::cout << std::endl;
    }               

    return 0;
}

Take into account that in general case the nested loops showed in other posts are unable to substitute the loop with the lambda-expression. For example the outer loop can contain continue statements that will skip the inner loop. So if you need that the inner loop will be executed in any case independing on the continue statements then this construction with the lambda expression will be helpful.:)

Sign up to request clarification or add additional context in comments.

4 Comments

That's a creative use of lambdas, but I hope nobody will actually write such code...
I would have given you the vote right away, but Burr beat you to it, and I used his idea as my answer.
@Vlad Then he should just invert the loops. I'd be surprised if there exists such an algorithm that would mandate this construct.
@Mihai Todor It is not possible always to invert the loops.
5

There is no need to do so. Because for loop can be easily replaced with while loop, every part of for loop can be placed in another place, where it's possible to use complex constructions. In your case, you can just change loop to the following:

for (i = 1; i <= N; i++) {
    printf("\n");
    for (j = 1; j <= i; j++) {
        printf("%c", '0');
    }
}

However, if you really have to place complex action, you may use gcc extension (compound statement):

for (i = 1;
     i <= N; 
     ({for (j = 1; j <= i; j++) putchar('0'); }), i++) {
   printf("\n");
}

3 Comments

I was looking for complex action, yes! I likes your answer since it does not use lambdas as the other answers do.
Did you edit on my edits? Please check the code for correctness. A final newline doesn't show up Here's the ideone that shows this.
The third block of for is executed after each loop. That's why printf() is not called last time.
4

In the counter section of a for() loop, expressions are allowed, but statements are not.
And every for() line in C/C++ forms a new statement (it's not an expression).

However, you can nest several for() loops if you want.
For example, since you want a new loop in the counter sections, that means that you need to perform a loop at the end of the main for() loop.

This is the scheme:

  for (int i = 0; i < i_max; i++) {
      // stuff...


      for (int j = 0; j < j_max; j++) {
            // stuff..
      }  
  }

Comments

3

You can't do that because condition and increment parts of a for can only contain expressions. A for loop is an iteration statement, though.

Simply nest the loops like sane programers do:

#include <stdio.h>
int main()
{   
    int N = 5;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= i; j++)
             printf("0");
        printf("\n");
    }
}

If you're not feeling well, though, you could use a lambda:

#include <stdio.h>
int main()
{   
    int N = 5;
    for (
        int i = 1;
        i <= N; 
        [=](){ for (int j = 1; j <= i; j++) printf("0"); }(), printf("\n"), i++
    ) ;
}

2 Comments

C++11, if needed. But that should be a default by now.
#jrok, C++11 is not default for my g++, anyway, I didn't even know I had to compile as C++ ... that's why gcc was giving errors
1

Elegance comes with clarity. When I want to create a string of characters, I construct a C++ object called std::string.

#include <iostream>
#include <string>

int main()
{
  char c = '0';
  const int n = 5;

  for (int i = 1; i <= n; ++i)
  {
    std::cout << std::string(i, c) << '\n';
  }
}

So there is no need for a nested for-loop in this particular case. Otherwise put a for-statement in the body of the outer loop as other answers suggested.

Comments

1

Shortest-possible solution:

main(i){for(i=1;i<11;printf("%0*d\n",i++,0));}

Output:

0
00
000
0000
00000
000000
0000000
00000000
000000000
0000000000

LIVE DEMO

9 Comments

Good to know. You can actually move the \n into the printf statement, and make it even smaller.
This is shorter: int N=10; for (int i=1; i<=N; printf("%0*d\n", i++, 0)) ;
@pablo1977: how about now?
@PiotrS.: Drop the unused j :)
This is Code Golfing in C89, a language that should be dead by now (but you can thank Microsoft for keeping it alive, though even GCC defaults to C89 mode compilations). Such code has no place outside of Code Golf, though.
|
1

Hat tip to Michael Burr for the suggestion to use lambda. And thanks to the commentators requesting me to use putchar().

#include <stdio.h>

int main() {
  int N;
  scanf("%d", &N);

  for (int i = 0; i < N; i++, [i] {
         for (int j = 1; j <= i; j++, putchar('0'))
           ;
       }(), printf("\n"))
    ;

  return 0;
}

LIVE DEMO

Comments

0

I think we should avoid obfuscated code unless we get paid for making the code complex.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.