Ilian Zapryanov
Ilian Zapryanov

Reputation: 1158

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 "^".

Upvotes: 0

Views: 1204

Answers (3)

mvw
mvw

Reputation: 5105

for(int i=0; i <= n; i++) {

You should use a less operator (<) here, as your x coordinate is from [0,n-1].

set_char_at(mat, n, i, -j, '^');

Your y cooridinate seems to be from [0,n-1] as well, so just -j is not a good choice, perhaps you mean n-j?

set_char_at(mat, n, i, 0, '\n');

You probably want to add a n+1 th column for a line feed character (\n).

char* mat = new char[(n*n)]:

In this case you have to dimensionate for (n+1)*n instead of n*n. Then x = n would be a valid argument.

cout << mat;

You use the character array as string. In this case you have to add a 0 as last character in the array. And you have to add one to the dimension, so it should look like

char* mat = new char[(n+1)*n + 1];

Upvotes: 0

kfsone
kfsone

Reputation: 24249

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

Upvotes: 2

Alexi
Alexi

Reputation: 391

You are overwritting in this line set_char_at(mat, n, i, 0, '\n'); the previous character "^". I mean, when j=0, you execute the line set_char_at(mat, n, i, 0, '^');, and later you execute set_char_at(mat, n, i, 0, '\n');

Upvotes: 0

Related Questions