C - print a specific template

The exercise asks me to create a program that takes an integer n

and prints the following pattern with height 2*n

.

\    *    /
 \  ***  /
  \*****/
   \***/
    \*/
    /*\
   /***\
  /*****\
 /  ***  \
/    *    \

      

What I have already done:

void arte(int n)
{
    int i, barrasE, aux, espacobarrasE, ebE, espaco;
    aux = n;

    for(i = 1; i <= n; i++)
    {
       if(aux < n) //Prints the spaces on the superior part.
       {
           espacobarrasE = n - aux;
           for(ebE = 0; ebE < espacobarrasE; ebE++)
               printf(" ");
       }
       for(barrasE = 1; barrasE <= aux; barrasE++) //Prints the backslashes on the superior part.
       {
           printf("\\");
           break;
       }
       for(espaco = 1; espaco < n; espaco++)
       {
           printf(" ");
       }
       aux = aux - 1;
       printf("\n");
   }
}

      

This only prints backslashes on top and I have no idea how to continue the code. I would like to know if this is a good way to do this, and what is the best way to continue the code.

+3


source to share


2 answers


I would develop the solution in stages, something like this. My solution insists on the parameter n

(which I am using n

in the code) is an odd number. The question does not show how to present the result if it is even. Persistence is reinforced by affirmations.

Stage 1 - print line function

#include <assert.h>
#include <stdio.h>

enum { FSLASH = '/', BSLASH = '\\' };

static inline void repeat_char(int num, char c) { for (int i = 0; i < num; i++) putchar(c); }

static void print_line(int l_blanks, char c1, int i_blanks, char c2, int nc, char c3)
{
    assert(i_blanks % 2 == 0);
    assert(nc % 2 == 1);
    repeat_char(l_blanks, ' ');
    putchar(c1);
    repeat_char(i_blanks, ' ');
    repeat_char(nc, c2);
    repeat_char(i_blanks, ' ');
    putchar(c3);
    //repeat_char(l_blanks, ' ');
    putchar('\n');
}

int main(void)
{
    print_line(0, BSLASH, 4, '*', 1, FSLASH);
    print_line(1, BSLASH, 2, '*', 3, FSLASH);
    print_line(2, BSLASH, 0, '*', 5, FSLASH);
    print_line(3, BSLASH, 0, '*', 3, FSLASH);
    print_line(4, BSLASH, 0, '*', 1, FSLASH);
    print_line(4, FSLASH, 0, '*', 1, BSLASH);
    print_line(3, FSLASH, 0, '*', 3, BSLASH);
    print_line(2, FSLASH, 0, '*', 5, BSLASH);
    print_line(1, FSLASH, 2, '*', 3, BSLASH);
    print_line(0, FSLASH, 4, '*', 1, BSLASH);
    putchar('\n');

    return 0;
}

      

The function repeat_char()

is a very simple loop that prints the specified character a specified number of times. Having done it static inline

, there is a good chance that the compiler will not call the function, but will place the body of the function in the calling code.

The function print_line()

characterizes each line as follows:

  • zero or more leading spaces.
  • one occurrence c1

  • zero or more internal spaces (this must be an even number)
  • nc

    occurrences c2

    (it must be an odd number)
  • zero or more internal spaces again
  • one occurrence c3

  • in other cases, it may be helpful to add trailing spaces; who commented
  • in these other cases the function will not print a newline

The code in c main()

calls this function with the appropriate hand-written arguments. It generates output:

\    *    /
 \  ***  /
  \*****/
   \***/
    \*/
    /*\
   /***\
  /*****\
 /  ***  \
/    *    \

      

Sounds like you are for N = 5. But these function argument lists have a lot of regularity for them. There must be a way to generate calls with numbers replaced by these expressions. This observation leads to stage 2.

Stage 2 - two loops

#include <assert.h>
#include <stdio.h>

enum { FSLASH = '/', BSLASH = '\\' };

static inline void repeat_char(int num, char c) { for (int i = 0; i < num; i++) putchar(c); }

static inline int max(int x, int y) { return (x > y) ? x : y; }
static inline int min(int x, int y) { return (x < y) ? x : y; }

static void print_line(int l_blanks, char c1, int i_blanks, char c2, int nc, char c3)
{
    assert(i_blanks % 2 == 0);
    assert(nc % 2 == 1);
    repeat_char(l_blanks, ' ');
    putchar(c1);
    repeat_char(i_blanks, ' ');
    repeat_char(nc, c2);
    repeat_char(i_blanks, ' ');
    putchar(c3);
    //repeat_char(l_blanks, ' ');
    putchar('\n');
}

static void driver_1(int N)
{
    assert(N % 2 == 1 && N > 0);

    for (int i = 0; i < N; i++)
    {
        int nb = max(0, (N-1-2*i)/2);
        int db = min(2*i+1, 2*(N-i)-1);
        print_line(i, BSLASH, 2*nb, '*', db, FSLASH);
    }

    for (int i = N-1; i >= 0; i--)
    {
        int nb = max(0, (N-1-2*i)/2);
        int db = min(2*i+1, 2*(N-i)-1);
        print_line(i, FSLASH, 2*nb, '*', db, BSLASH);
    }
    putchar('\n');
}

int main(void)
{
    int N = 5;
    assert(N % 2 == 1);

    driver_1(N);
    driver_1(N+2);
    driver_1(N-2);

    return 0;
}

      



Functions repeat_char()

and have print_line()

not changed before. The new function driver_1()

contains two loops, one for processing lines with 0, 1, ... N-1 headings, and the other for processing lines with N-1, N-2, ... 0 leading spaces. Functions over min()

and max()

over static inline

, so using them is unlikely to cause overhead function calls. The cycle index,, i

controls the number of leading blanks. Expressions for nb

and db

calculate the number of spaces and asterisks to display. These expressions are the same in both loops; the differences are in the direction of counting (up and down) and the order of the forward slash character arguments.

This generates the output:

\    *    /
 \  ***  /
  \*****/
   \***/
    \*/
    /*\
   /***\
  /*****\
 /  ***  \
/    *    \

\      *      /
 \    ***    /
  \  *****  /
   \*******/
    \*****/
     \***/
      \*/
      /*\
     /***\
    /*****\
   /*******\
  /  *****  \
 /    ***    \
/      *      \

\  *  /
 \***/
  \*/
  /*\
 /***\
/  *  \

      

This demonstrates that the functions work with requested requests of different sizes.

Stage 3 - single cycle

The final version of the code uses the symmetries of the two loops in driver_1()

and uses one loop in the range 0

.. 2* N - 1

to generate the correct call print_line()

. The only changes to the driver functions were renamed to driver_2()

(in part because they were developed in a single executable that also had driver_1()

). Again, function repeat_char()

and print_line()

do not change; and min()

and max()

used again.

The loop determines the value matched i

in driver_1()

using an expression (strictly that a definition, not an expression, but contains an expression) int i = min(j, 2*N-1-j);

. The term is j

counted; term is 2*N-1-j

counted; the value used is the lesser of the two. The test for j == i

allows you to correctly select the first and last character.

#include <assert.h>
#include <stdio.h>

enum { FSLASH = '/', BSLASH = '\\' };

static inline void repeat_char(int num, char c) { for (int i = 0; i < num; i++) putchar(c); }

static inline int max(int x, int y) { return (x > y) ? x : y; }
static inline int min(int x, int y) { return (x < y) ? x : y; }

static void print_line(int l_blanks, char c1, int i_blanks, char c2, int nc, char c3)
{
    assert(i_blanks % 2 == 0);
    assert(nc % 2 == 1);
    repeat_char(l_blanks, ' ');
    putchar(c1);
    repeat_char(i_blanks, ' ');
    repeat_char(nc, c2);
    repeat_char(i_blanks, ' ');
    putchar(c3);
    //repeat_char(l_blanks, ' ');
    putchar('\n');
}

static void driver_2(int N)
{
    assert(N % 2 == 1 && N > 0);
    for (int j = 0; j < 2*N; j++)
    {
        int i = min(j, 2*N-1-j);
        int nb = max(0, (N-1-2*i)/2);
        int db = min(2*i+1, 2*(N-i)-1);
        char c1 = (j == i) ? BSLASH : FSLASH;
        char c3 = (j == i) ? FSLASH : BSLASH;
        print_line(i, c1, 2*nb, '*', db, c3);
    }
    putchar('\n');
}

int main(void)
{

    int N = 5;
    assert(N % 2 == 1);

    driver_2(N);
    driver_2(N+2);
    driver_2(N+4);
    driver_2(N-2);
    driver_2(N-4);

    return 0;
}

      

This generates an output (note the almost degenerate case for N = 1):

\    *    /
 \  ***  /
  \*****/
   \***/
    \*/
    /*\
   /***\
  /*****\
 /  ***  \
/    *    \

\      *      /
 \    ***    /
  \  *****  /
   \*******/
    \*****/
     \***/
      \*/
      /*\
     /***\
    /*****\
   /*******\
  /  *****  \
 /    ***    \
/      *      \

\        *        /
 \      ***      /
  \    *****    /
   \  *******  /
    \*********/
     \*******/
      \*****/
       \***/
        \*/
        /*\
       /***\
      /*****\
     /*******\
    /*********\
   /  *******  \
  /    *****    \
 /      ***      \
/        *        \

\  *  /
 \***/
  \*/
  /*\
 /***\
/  *  \

\*/
/*\

      

So this is it. Full development cycle in 3 stages. Get something that works and demonstrate that it works. Then make the solution more general.

+3


source


There are many ways to accomplish this. One of them is the following



void print_pattern(int n) {

    int padding=0;
    int width=0;
    char char_begin='\\', char_end='/';

    assert(n>0);
    for(int x=0; x<n*2; x++) {
        if(padding==n) {
            padding--;
            char_begin='/';
            char_end='\\';
        }
        width=(n*2)-padding;
        for(int y=0;y<=width; y++) {
            if(y==padding)
                printf("%c",char_begin);
            else
                if (y==width)
                    printf("%c",char_end);
                else 
                    if (y>padding && y>=n-padding && y<=n+padding)
                        printf("*");
                    else
                        printf(" ");
        }
        printf("\n");
        if(x<n)
            padding++;
        else
            padding--;
    }
}

      

+2


source







All Articles