2
#include <stdio.h>


void fillline(char *line, char c, int len){
    for(int i = 0; i<len-1; i++)
        line[i] = c;
    line[len-1] = '\n';
    line[len] = '\0';
}

int main() {
    
    char xs[4][30];
    fillline(xs[0], '-', 30);
    fillline(xs[1], '(', 30);
    fillline(xs[2], ')', 30);
    fillline(xs[3], 'Z', 30);

    printf("%s", xs[0]);
    printf("%s", xs[1]);
    printf("%s", xs[2]);
    printf("%s", xs[3]);
       
}

Hello, C-programming newbie here. I have a problem with the code above. I expect

-----------------------------
(((((((((((((((((((((((((((((
)))))))))))))))))))))))))))))
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

as command-line output generated from my code, but I get

-----------------------------
(((((((((((((((((((((((((((((
)))))))))))))))))))))))))))))
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
(((((((((((((((((((((((((((((
)))))))))))))))))))))))))))))
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
)))))))))))))))))))))))))))))
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

What am I doing wrong? I tried fflush(stdout) and setbuf(stdout, NULL) (although I am definitely not sure that this is a stdout-problem).

Thank you in advance.

Denan
  • 43
  • 5
  • 3
    You have not allowed room for a null-terminator to your strings. Consequently each one flows into the next. If you look carefully at the output pattern, first all 4 are printed, then 3, 2, and 1. – Weather Vane Aug 02 '20 at 17:24
  • 4
    `line[len] = '\0'` should raise red flags. You can't assign to an index equal to the length of the string. `len - 1` is the last valid index. – Carcigenicate Aug 02 '20 at 17:25

3 Answers3

4

The problem is because of two reasons.

  1. The strings ain't got a null terminator. Using it as string in printf("%s", xs[N]) causes undefined behavior.

  2. With

    line[len] = '\0';
    

    you also attempt to write '\0' into an not existing 31th element.

Note that array indexing starts at 0, not 1. This confusion is what caused your trouble here.

Both things, the use of an indeterminate string and writing beyond the bounds of an array invokes undefined behavior.


Solution(s):

1.

Change

void fillline(char *line, char c, int len) {
    for(int i = 0; i < len-1; i++)
        line[i] = c;
    line[len-1] = '\n';
    line[len] = '\0';
}

to

void fillline(char *line, char c, int len) {
    for(int i = 0; i < len-2; i++)
        line[i] = c;
    line[len-2] = '\n';
    line[len-1] = '\0';
}

OR

2.

Decrement len before the use in the loop by 1.

void fillline(char *line, char c, int len) {
    len--;
    for(int i = 0; i < len-1; i++)
        line[i] = c;
    line[len-1] = '\n';
    line[len] = '\0';
}

OR

3.

Call the function fillline with an third argument of value 29, not 30.

fillline(xs[0], '-', 29);
3

You are overwriting the end of your buffer.

void fillline(char *line, char c, int len){
    for(int i = 0; i<len-3; i++)
        line[i] = c;
    line[len-2] = '\n';
    line[len-1] = '\0';
}
Paul Baxter
  • 1,054
  • 12
  • 22
1

That is no '\0' at the end of string due to you are trying to write over the array, this will cause undefined behavior.

Sometimes it is a bad idea not performing bound checking in C.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39