Ilian Zapryanov Ilian Zapryanov - 2 months ago 8
C++ Question

Simple drawing with ASCII algorithm

I am trying to draw a simple shapes in ASCII, when I try to draw a simple triangle, my last line is always omitted. Can you give me a hand? Maybe I am missing something?

static void set_char_at(char* mat, int cols, int x, int y, char c)
{
mat[x*cols+y] = c;
}

int test3()
{
int n;
cin >> n;
char* mat = new char[(n*n)]; // newlines
for(int i=0; i < n*n; i++) {
mat[i] = ' ';
}
for(int i=0; i <= n; i++) {
for(int j=0; j < i; j++) {
set_char_at(mat, n, i, -j, '^');
}
set_char_at(mat, n, i, 0, '\n');
}
cout << mat;
}


EDIT: Input is 5, the desired output is:

^
^^
^^^
^^^^
^^^^^


In the right end of the screen as seen. I am missing the last line of "^".

Answer
char* mat = new char[(n*n)]; // newlines
for(int i=0; i < n*n; i++)
    mat[i] = ' ';

Lets say that n is 1. The array, mat, will be size 1*1. This can hold 1 character. In C++ a string (not a std::string) is an array of characters terminated by a nul-byte, which requires N+1 bytes.

char* mat = new char[(n*n) + 1];
for(int i=0; i < n*n; i++)
    mat[i] = ' ';
mat[n*n] = 0;

Back to your code, if n is 2:

for(int i=0; i <= n; i++) {
    for(int j=0; j < i; j++) {
        set_char_at(mat, n, i, -j, '^');
    }

this will call:

        set_char_at(mat, n, 1, -0, '^');  => mat[1*2-0] => 2
        set_char_at(mat, n, 2, -0, '^');  => mat[2*2-0] => 4
        set_char_at(mat, n, 2, -1, '^');  => mat[2*2-1] => 3

Note the indexes on the right hand side, there's one more line in your loop:

for(int i=0; i <= n; i++) {
    for(int j=0; j < i; j++) {
        set_char_at(mat, n, i, -j, '^');
    }
    set_char_at(mat, n, i, 0, '\n');

This translates to:

        set_char_at(mat, n, 1, -0, '^');  => mat[1*2-0] => 2
    set_char_at(mat, n, 1, 0, '\n');      => mat[1*2+0] => 2
        set_char_at(mat, n, 2, -0, '^');  => mat[2*2-0] => 4
        set_char_at(mat, n, 2, -1, '^');  => mat[2*2-1] => 3
    set_char_at(mat, n, 2, 0, '\n');      => mat[2*2+0] => 4

You need to allow room for carriage returns:

#include <iostream>

void testf(size_t n)
{
    const size_t matSize = (n+1) * n + 1;
    char* mat = new char[matSize] {};
    for (size_t i = 0; i < matSize - 1; ++i)
        mat[i] = ' ';
    mat[matSize - 1] = 0;

    for (size_t i = 0; i < n; ++i) {
       for (size_t j = 0; j <= i; ++j)
           mat[i*(n+1)+(n-j-1)] = '^';
       mat[i*(n+1) + n] = '\n';
    }

    std::cout << "--- start " << n << "\n";
    std::cout << mat;
    std::cout << "--- end\n";
}

int main()
{
    testf(4);
}

Live demo: http://ideone.com/mhY7iS