printf outputs too often

Viewed 103
#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.

3 Answers

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);

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';
}

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.

Related