You are here:

# C++/Triangles in C

Question
Hi
good day, i was wondering if you could help me in programming. i'm trying out this program i found in this book, but i'mnot sure if what i am doing is correct. i want to draw an equilateral triangle but it came out weird, here is my code:

#include <stdio.h>

main()
{
int n, /* user defined */
test, /* to make n odd */
sp, /* space */
x,y,z; /* counters */

printf("Enter a number: ");
scanf("%d", &n);

test=2%3;

if(n%test==0) n=n+1;
else goto step2;

step2: { for(x=1;x<=n;x=x+2)
{
for(y=1;y<=n;y++)
{
for(z=y;z<=x;z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
}          getche();
}

this is the out put
n=7
*-------
***-**-*-----
*****-****-***-**-*---
*******-******-*****-****-***-**-*-

i really wated something like this (but aligned so its an equalateral triangle)
n=7
*
***
*****
*******

i've been stuck on this for awhile now, any help of tips will be extremely helpful. i've been programming on the side, its like a new hobby for me, and its distracting me from my real school work. if you could give me some tips or advice that would be awesome! thank you in advance!

First a few points:

You are asking this C question of a C++ expert. While I have of course written quite a lot of C in my time I have not done it on a daily basis for over 10 years now.

You might bear that in mind when I answer as although the program you show is not complex my reply may be based on current C++ idioms rather than C - although I will avoid using C++ only features.

OK to the program.

The first thing that strikes me is that the indentation is wrong. Now this may be due to posting through AllExperts but some of the code seems sensibly indented. The section that is not looks to me as follows (note: you should view code using a single-spaced font like Courier):

step2: { for(x=1;x<=n;x=x+2)
{
for(y=1;y<=n;y++)
{
for(z=y;z<=x;z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
}          getche();
}

Again this may be screwed up by posting through AllExperts - so I apologise if this is the case. The start of the bodies of the for loops are partially indented with respect to each other. The contents of those loops is not (i.e. the calls to printf). This makes it hard to see what is going on.  The getche call seems to be on the end of a line out on its own - did you accidentally remove a newline? Do not be afraid to add spaces to make the code clearer. The compiler may not care but yourself and others (like me) have to read it. This is one way that I think is clearer:

step2:
{
for(x=1; x<=n; x=x+2)
{
for(y=1; y<=n; y++)
{
for(z=y; z<=x;z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
getche();
}

} // end of the function

In fact most of us would indent like this:

step2:
{
for(x=1; x<=n; x=x+2)
{
for(y=1; y<=n; y++)
{
for(z=y; z<=x; z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
getche();
}

} // end of the function

Or like this:

step2:
{
for(x=1; x<=n; x=x+2)
{
for(y=1; y<=n; y++)
{
for(z=y; z<=x; z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
getche();
}

} // end of the function

Once again I hope that AllExperts do not remove whitespace and mess up the layout...

The next line I find odd is:

test=2%3;

This is because the result will always be the same: the remainder when dividing 2 by 3 is always 2.

Next you have the if .. else clause:

if(n%test==0) n=n+1;
else goto step2;

Which just says if n is even add one to make it odd, otherwise jump to point step2 - which is the next piece of code anyway - so did you remove some code?

Apart from the use of goto which should be banned in 99.99999% of all cases, the meaning is the same as without the else clause - if n is even it is incremented, and then code at the label step2 is executed, otherwise, the if statement is not executed and the processing falls through to the code at the step2 point anyway.

Taking these two points together I would remove test altogether and remove the else and the label step2. I think the variable sp is also not used:

#include <stdio.h>

main()
{
int n, /* user defined */
test, /* to make n odd */
sp, /* space */
x,y,z; /* counters */

printf("Enter a number: ");
scanf("%d", &n);

if( n%2==0 )
{
n = n + 1;
}

for(x=1; x<=n; x=x+2)
{
for(y=1; y<=n; y++)
{
for(z=y; z<=x; z++)
{
printf("*");
}
printf("-");
}
printf("\n");
}
getche()
} // end of the function

Notice that I also always add braces around statements that might be compound as in the case of the if ( n%2==0 ) statement. This is because such one liners have a nasty habit of becoming 2 or more liners later on and then you really need those braces - also it makes clear that the statement(s) is / are those executed for the if-true condition.

Ok so what does the code do?

Ignoring the setup code and looking straight at the loops I can say it never prints any spaces for a start - it only outputs '*', '-' or a new line. I can see this immediately from the printf calls you are using. - by the way you might want to look at putc and puts which just write a single character or string to the console - printf is a bit of a sledge hammer to crack a nut here as you are only outputting a single character at a time.

The outer loop iterates for approximately n/2 times so this should be the number of new lines you get - in this case 4 (x = 1, 3, 5, 7; the next iteration would have x=9 and 9 is not <= n so the loop terminates; n=7 according to your question).

The middle (y) loop iterates n times - seven in this case. So for each line you will get 7 '-' characters printed on it before the new line is output.

Each time around this middle loop the inner (z) loop executes and it prints a star each time it iterates. Now the number of times this loop iterates is complex. It starts with a value equal to the current value of the middle loop variable y and increments until z has a value greater than the current value of the outer loop variable x is reached. So if x=1 then y=1 will be OK and a star is printed. If y=2 or more then no star is printed, as z starts at a value greater than the value of the x end-loop value. This is what we see in the first line: A star is printed, then the hyphen for that iteration of the middle loop, then the inner loop does not execute at all for y values 2 .. 7 so we just get the other hyphens printed. In the next iteration of the outer loop x=3 so we see stars printed out for y=1, 2 and 3 - each time one less is printed - ***, **, *, and each star group is followed by the hyphen printed at the end of each middle loop iteration, the end of the line just finishes with the remaining hyphens:

***-**-*-----
I shall leave it to you to figure out how the output for line 3 and 4 are produced (when x has the values 5 and 7).

So what should the code be doing. Well you have the correct number of lines output and the value of x for each line represents the correct number of stars to print on each line: 1, 3, 5, and 7. All you are missing are the spaces at the start of the line - and the correct number of stars on each line. The outline of the code should look something line so:

For each line where x = number of stars to print
PrintSpaces( n, x )
PrintStars( x )
PrintNewLine
End For

You have the PrintNewLine stage correct. You do not have the spaces and stars correct. You code looks more like:

For each line where x = number of stars to print
PrintLine( n, x )
PrintNewLine
End For

And PrintLine looks like:

For each value y from 1 up to n
PrintStars( y, x )
PrintHyphen
End For

So each time you print a line you print seven groups of stars - many of which groups a zero stars long - followed by a hyphen. That is you have the star stage inside the space stage - which for some reason prints hyphens after the stars instead of spaces before the stars.

Whereas what you want is for the space stage to happen before the star stage.

Here are some things you should know to help you write the loops for the PrintSpaces and PrintStars stages:

1/ the number of spaces is equal to the value of n minus the value of x divided by 2, so for n = 7

then x = 1, spaces = 3 = (7 - 1) / 2
x = 3, spaces = 2 = (7 - 3) / 2
x = 5, spaces = 1 = (7 - 5) / 2
x = 7, spaces = 0 = (7 - 7) / 2

2/ the number of stars is equal to the value of x for each line: 1, 3, 5, 7.

So with this is mind we can write the loop code thus:

for ( x = 1; x <=n; x = x + 2 )
{
/* PrintSpaces: */
int numberOfSpaces = (n - x) / 2;
for ( y=0; y<numberOfSpaces; ++y )
{
printf(" ");
}

/* PrintStars: */
for ( z = 0; z < x; ++z )
{
printf("*");
}

/* PrintNewLine */
printf("\n");
}

You might notice some things about my code:
- It is usual for loops in C to start at zero rather than one unless there is a reason not to such as the outer x loop. In these cases the end condition is usually < (Less than) rather than <= (less than or equals). This is because C arrays are indexed from zero and many loops iterate over arrays.

- I have added comments above each stage that refers to my outline above. When you learn more you could re-write this code placing such stages in their own functions called PrintSpaces and PrintStars – although a PrintNewLine function is probably a little over the top.

- I have used a variable local to the scope of the outer for loop to hold the computed value of the required number of spaces. You will notice its name says exactly what it does. Please get into the habit of giving your variables long enough names to be descriptive of their purpose.

Hope this helps.

C++

Volunteer

#### Ralph McArdell

##### Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

##### Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials