I used the debugger to examine this code but not understanding a couple areas.
- Why does the for loop repeat after it exits to print a new line? If it exits the loop, shouldn’t it be done with it?
- Why is n incremented and not i as stated with i++?
int main(void)
{
int height = get_int("Height: ");
draw(height);
}
void draw(int n)
{
if (n <= 0)
{
return;
}
draw(n - 1);
for (int i = 0; i < n; i++)
{
printf("#");
}
printf("\n");
}
Recursion is a little easier to understand if you use
goto
instead of functions. Functions are a high level concept in the C language (and most other languages) but it gets compiled down to (essentially) the oldergoto
style of programming.Most modern languages don’t even have goto support, since functions are generally more reliable, however as a programmer you should be aware what’s going on under the hood. Here’s your code rewritten to use
goto
(I also generally rewrote the whole thing to be a bit easier to grok):int main(void) { int height = get_int("Height: "); int row = 1; int col = 0; draw: if (row > height) { goto end; } if (col < row) { printf("#"); col++; goto draw; } // Move to the next row printf("\n"); row++; col = 0; goto draw; end: return 0; }
I think it’s wrong to look at recursion that way. What you just showed is how to translate a recursive solution to an iterative one, which only makes recursion look like an inferior version of a loop. With recursion the idea is that you solve the problem for trivial/base cases (eg. we know that the first and second numbers of the Fibonacci sequence are both 1), then you assume a smaller problem has already been solved (eg. we already know what fibonacci(n-2) and fibonacci(n-1) is) and now you program the solution for the next step (fibonacci(n)).
In this case the problem we want to solve is drawing a triangle of a specific height with a base of the same width. The base case is the empty or negative-height triangle. In this case we draw nothing. Now we assume we already know how to draw a triangle of height
height - 1
. The question we ask ourselves now is how do we draw the triangle of heightheight
when we already have a solution for the problem of how to draw a triangle ofheight - 1
. We see that the triangle of heightheight
is simply the triangle of heightheight - 1
with another row of the same length as the height of the triangle added to the end. So what we do is we draw the triangle ofheight - 1
(which is done by using the same solution we are writing right now, but we shouldn’t meditate about what that entails when writing, since it’s just going to unnecessarily cause us headaches), and then draw a row of lengthheight
at the end. Now we have a solution for the base case (other problems such as the fibonacci function I mentioned can have more than one base case), and a solution for all the other cases written with the assumption that a previous problem has already been solved. This is how one is supposed to write all recursive functions. Find and write all the base cases and then write the solution for the problem assuming a simpler problem has already been solved.I’m not sure if you are talking about the concept of
goto
s or what happens when OP’s code is run. If it is the latter, then I have to say that most compilers very likely wouldn’t remove that recursive call in the final assembly. That’s why running the program with a large number results in a segfault. Because the stack overflowed, because it’s a recursive call.