-1

I am currently trying to solve a problem on Hackerrank and I don't quite understand why my solution doesn't work. The task is to print a right-aligned staircase of '#'s. I tried this C code:

void staircase(int n) {
    char stair[n];
    memset(stair, ' ', n *(sizeof(char)));

    for(int i = n-1; i>= 0; i--)
    {
        stair[i] = '#';
        printf("%s\n", stair);
    }
}

It works fine if n = 8 or lower, but if n = 9 or higher it still prints the staircase, but with some garbage symbol at the end of every line. I just don't quite understand why this works for some numbers and not for others. Is there some problem with the way strings work in C or something? I know my solution for this problem might not be the most efficient in general, but for me this is about understanding why this specific piece of code doesn't work right.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Please include the output – Roshin Raphel Jul 20 '20 at 13:10
  • On a side note, `sizeof(char)` is always 1, by definition. – Fabio says Reinstate Monica Jul 20 '20 at 13:21
  • `sizeof(char)` is by definition 1. You should either remove it or write a more useful `sizeof(stair[0])`. And even better you should just get the size of the whole array at once with `sizeof(stair)`. – alx - recommends codidact Jul 20 '20 at 13:23
  • variable size array are considered bad practice in C, you should rather dynamically allocate your memory with something like : `char *stair = (char*) malloc((n+1)*sizeof(char))` Where you allocate memory for your n characters and the end of string char `\0`. And you should free the memory before exiting the function with `free(stair)` – Puck Jul 20 '20 at 13:24

2 Answers2

2

This array

char stair[n];

does not contain a string because it was initialized like

memset(stair, ' ', n *(sizeof(char)));

So the function invokes undefined behavior.

Either you need to define the array like

char stair[n+1];

and then write

memset(stair, ' ', n *(sizeof(char)));
stair[n] = '\0';

Or just change the call of printf the following way

printf("%.*s\n", n, stair);

Pay attention to that used by you the approach with declaring a character array is not efficient. You could do the same task without using an array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

When you use

memset(stair, ' ', n *(sizeof(char)));

the white space character ' ' is not equal to a null character '\0' (which you might think it is). This means in turn that the array elements of stair aren't set to 0 (which would determine a strings end).

They are just all initialized to contain white space but there is actually no indicator at all inside of the array, that determines where a string ends, when the array is addressed by string operating functions.

Such an operation encounters a specific amount of '#' hashtags first and thereafter only white space character/s, but no null character.

Printing a string with

printf("%s\n", stair);

is then undefined behavior, because there is no delimiter to determine the string's end.

Use

memset(stair, '\0', sizeof(char) * n);

or

memset(stair, 0, sizeof(char) * n);

instead.

As side note here, allocating an array might not be most efficient way to go. Better use an algorithm which uses a single character constant for '#' and prints increase the amount of it shown in the output per iteration.


To answer your concerns:

It works fine if n = 8 or lower, but if n = 9 or higher it still prints the staircase, but with some garbage symbol at the end of every line. I just don't quite understand why this works for some numbers and not for others.

It has nothing at all to do with the value of n. Undefined behavior does not need to provide wrong results. In fact, all of your executions were subject to undefined behavior regardless whether it showed the expected output or not.


Also variable length arrays (VLAs), like stair is, are not supported by every implementation and only mandatory to C99 conforming implementations. They are only made available by non-standard compiler extensions when compliant to other standards. May use malloc() instead to make your program more portable.