How does this "christmas tree" program work

Hello, I recently saw a a program that takes an integer, and prints a christmas tree (made of '*' s ) using the integer as the number of rows. Unfortunately the orginal guy didn't leave any comments, and i can't find out how his while loops work, help?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    int n, i, j;
    int chars[] = {' ', '*', '\n'};

    if (argc != 2)
        exit(1);
    n = atoi(argv[1]);
//understand most stuff above, but not below
    for (i = 0; i < n; i++)
        for (j = 0; j < n+i+2; j++)
            putchar(chars[(j>=n-i)+(j==n+i+1)]);
    

    for (j = 0; j < n+2; j++)
        putchar(chars[(j>=n)+(j==n+1)]);
}

Thanks in advance.
Firstly there's no while loops in that code, he uses for loops.
So if you don't know how they work yet, check that out.

Now the syntax of the body for any loops is the same for the if and else statements.
1
2
3
4
5
6
7
8
9
10
11
if(test)
    single-command;
//Back to main flow


if(test){//Braces used for multiple commands
    first-command;
    second-command;
    third-command;
    etc;
}//stop IF 


Some consider it bad practice to use the syntax that requires no braces, in my opinion I prefer it for IFs and ELSEs but I always use braces on loops, no matter how large/small there body is.

So the code you provided actually means this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
    int n, i, j;
    int char[] = {' ', '*', '\n'};

    if(argc != 2)
        exit(1);
    n = atoi(argv[1]);

    for(i=0; i<n; i++){
        for(j=0; j<n+i+2; j++){
            putchar(chars[(j<n-1)+(j==n+i+1)]); //I don't like this much
        }
    }
    for(j=0; j<n+2; j++){
        putchar(chars[(j>=n)+(j==n+1)]l //Don't like this much either XD
    }
}
closed account (j3Rz8vqX)
First, the program is taking an argument from the command line.
Therefore must be executed from the command line.
1
2
    if (argc != 2)
        exit(1);

Else it would exit with value 1.

 
n = atoi(argv[1]);//The value entered during command line is controlling the size of the Christmas tree! 


Possibly you don't know for-loops, so I am explaining it. If you do, then just look for what you need.

The below is a simple for loop.
First argument assigns i=0. Only during initial use of for-loop
Second argument compares "i" to "n". Compares every complete cycle.
Third argument increments i by 1 every cycle.
1
2
3
4
5
6
7
8
    for (i = 0; i < n; i++)//
    {
        for (j = 0; j < n+i+2; j++)//same as above, this time, j compares to i plus n plus 2
        {
            putchar(chars[(j>=n-i)+(j==n+i+1)]);//put char draws a character at array index [BOOL(j>n-i) + BOOL(j==n+i+1)]
            //BOOL will be 0 or 1; chars[(0 or 1 + 0 or 1)]
        }
    }


This persons algorithm is drawing blanks, asterisks, and newline depending on his index_algorithm, in the chars[?].

The first for-loop controls the y axis.
The second for-loop controls the x axis.
The second for-loop prints either ' ','*','\n'.

Third for-loop prints the trunk of the tree.

-----Second for-loop
putchar (chars[?]); printing out the character in the character_array chars, at index ?.

j>n-1 is going to be a value of 0 or 1
j==n+i+1 is going to be a value of 0 or 1

Add them together:
? minimum value is 0. (0+0)
? possible value is 1. (0+1) or (1+0)
? maximum value is 2. (1+1)

chars[0] == ' ';
chars[1] == '*'
chars[2] == '\n'

---third-loop similar to second loop

Hope this helps.
Last edited on
Op here, the "while" was a typo, sorry for that.

I understand most of it, but someone explain the loop conditions to me?

For example
 
for (j = 0; j < n+i+2; j++)

Not so sure why he put j < n+i+2, but i think the 2 has to do with the fact that each row has 2 more stars than the upper row, basically, i'm stuck on how this algorithm works.

Any mathematicians out there that can explain these loop conditions? XD

Thanks for explaining the other stuff, by the way.
the +2 isn't like what you are thinking:
the first one is because on the output the tree is pushed one step and the other one is to print '\n'
you can write it like that:
1
2
3
4
5
6
7
for (i = 0; i < n; i++)
    for (j = 0; j < n+i+1; j++)
        putchar(chars[(j>=n-i-1)+(j==n+i)]);
    

for (j = 0; j < n+1; j++)
    putchar(chars[(j>=n-1)+(j==n)]);

or
1
2
3
4
5
6
7
8
9
10
11
for (i = 0; i < n; i++)
{
    for (j = 0; j < n+i; j++)
	putchar(chars[(j>=n-i-1)]);
    putchar('\n');
}
    

for (j = 0; j < n; j++)
	putchar(chars[(j>=n-1)]);
putchar('\n');
Wouldn't this effectively do the same thing using a while loop with two embedded for loops? To me, it is much simpler to look at and comprehend.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

using namespace std;

int main()
{
    int stars=1,spaces=39,height=0;

    cout<<"Please enter the height desired: ";
    cin>>height;

    int n=0;
    while (n<height)
    {
        //output desired number of spaces
        for (int i=0;i<spaces;i++)
            cout<<" ";

        //output desired number of stars
        for (int i=0;i<stars;i++)
            cout<<"*";

        cout<<endl;//go to next line after each iteration
        //increment count,alter spacing and star quantity
        n++;//count times through while loop
        spaces--;//subtract a space
        stars+=2;//add two stars
    }
}

Looking at your original code, it is more difficult to understand how it works, but JewelCpp helps make it comprehensible. In this above example, +2 is more like how you were thinking earlier, while the original code made use of a character array. Similarly, I think a trunk is being created by the third loop, which probably uses something similar to the logic in this code which would be added following the while loop above.
1
2
3
4
5
6
7
8
9
10
11
12
13
    spaces=39;//restore default spacing
    //height of trunk
    int t=(height/10)+1;
    n=0;//reset counter for while loop
    while (n<t)
    {
        for (int i=0; i<spaces; i++)
            cout<<" ";

        cout<<"*";
        cout<<endl;
        n++;
    }
Last edited on
Topic archived. No new replies allowed.