HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppModerate

To understand what recursion is, you must first understand recursion

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
youmustrecursionwhatunderstandfirst

Problem

This is the second assignment for my CS2 course:



-
Write a recursive C++ function writeLine() that writes a character repeatedly to form a line of n characters. For example:

writeLine('*', 5)




produces the output:



*****




-
Write a recursive [C++] function writeBlock() that uses writeLine to write m lines of n characters each. For example,

writeBlock('*', 5, 3)




produces the output:



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




-
Implement and test a recursive C++ function writePyramid(). The function should take in a character to build a pyramid with and the

height of the pyramid (the number of lines in it). Hint: Each line in
the pyramid should be generated by two calls to writeLine: the first

call generates the spaces and a second call to generate the line of

characters.
The in the output below represents a space character. This output is generated when the function is asked to generate a
pyramid of height 3 with the * character.



␣␣*
␣***
*****





Please feel free to rip the code apart! In my opinion, I think the switch in main() could be DRYed up a bit, but I wasn't sure how.

lab2.cpp:

```
#include
#include
#include "lab2functions.h"

char getSanitizedChar()
{
// absorb newline character (if existant) from previous input
if('\n' == std::cin.peek()) std::cin.ignore();
return std::tolower(std::cin.get());
}

int main()
{
char type = '*';
char shape = 'l';
int rows = 0;
int cols = 0;
do
{
std::cout > shape;

switch(shape)
{
case 'l':
std::cout > cols;
std::cout > rows;
std::cout > cols;
std::cout > rows;
std::cout << "Enter character to build with (*): ";
type = getSanitizedChar();
writePyramid(('\n' == type ? '*' : type), rows);
break;
default:
std::cout << "Invalid option";
break;
}
std::cout << "\nRun a calculation again (y/N

Solution

Usually we write recursive functions with the exit condition all by itself:

void writeLine(const char c, const int8_t num)
{
  if (num > 0)
  {
    std::cout << c;
    writeLine(c, num - 1);
  }
}


I would normally write this as:

void writeLine(const char c, const int8_t num)
{
  if (num <= 0)
  {
      return;
  }

  std::cout << c;
  writeLine(c, num - 1);
}


No real reason apart from tradition I suppose. But it does show tail recursion more clearly. The compiler can easily optimize tail recursion into a loop for you. But it also makes it obvious to the human eye where tail recursion is.

A static member of a recursive function!!!

void writePyramid(const char c, const int8_t h)
{
  static int count;
  count++;


That's a bit strange. You normally pass all values as parameters between iterations. If you need a defaulting starting value then you can either use a wrapper function that calls your recursive function and provides the initial value. Or have a parameter that defaults to the start value but internally you increment it (I choose the second here).

void writePyramid(const char c, const int8_t h, int count = 0)
{
  if (h <= 0)
  {
    return;
  }

  writeLine(' ', (2 * h - 1) / 2);
  writeLine(c, (2 * count - 1));
  std::endl(std::cout);
  writePyramid(c, h - 1, count + 1); 
}


I know that Static storage duration objects are zero initialized. But how many of your peers know this. It would have been nice to give them a hint.

static int count = 0;


Going back to your wrapper code:

All the switch statements contain the same bit of code:

std::cout > rows;
  std::cout > cols;
  std::cout << "Enter character to build with (*): ";
  type = getSanitizedChar();


Keep it DRY. Either move this into a separate function (called from each case). Or move it to before the switch intirally.

Code Snippets

void writeLine(const char c, const int8_t num)
{
  if (num > 0)
  {
    std::cout << c;
    writeLine(c, num - 1);
  }
}
void writeLine(const char c, const int8_t num)
{
  if (num <= 0)
  {
      return;
  }

  std::cout << c;
  writeLine(c, num - 1);
}
void writePyramid(const char c, const int8_t h)
{
  static int count;
  count++;
void writePyramid(const char c, const int8_t h, int count = 0)
{
  if (h <= 0)
  {
    return;
  }

  writeLine(' ', (2 * h - 1) / 2);
  writeLine(c, (2 * count - 1));
  std::endl(std::cout);
  writePyramid(c, h - 1, count + 1); 
}
static int count = 0;

Context

StackExchange Code Review Q#79814, answer score: 10

Revisions (0)

No revisions yet.