Why do I get additional weird characters in this C code with dynamically-allocated char arrays?

I’m quite new to dynamic memory allocation in general.
I’ve been looking for an error in this code for about 6 hours in the last 3 days now, it’s driving me crazy, that’s why I’ve decided to ask for help here.
Here’s the code:

char ch;
char* line=(char*)calloc(1, sizeof(char));

if(input!=NULL) {
    for(int num=1; (ch=fgetc(input)) != EOF; num++) //input is the pointer to the in file
        if(ch!=' ') {
            line=(char*)realloc(line, sizeof(char)*num+1);
            strcat(line, &ch);
        }
        else
            break;
}

I’m trying to read from a file the first of two whitespace-separated words, where the total size is not predetermined (I’ll need this to read even more from the file so it’s important, this was "just to try").
This is for a single line, not multiple lines (char** I think would be used in that case), and the idea was to allocate the first character of the line and set it to zero, then reallocate the memory incrementing its size by one character.
If I "num++", it crashes; if I don’t, its output will be, instead of "Nole", this: N☺o☺l☺e☺ (output is after the loop; how does it even increase if num remains the same?). I checked the ASCII codes and this is what I get: 78 1 111 1 108 1 101 1; there is a ‘1’ after every character, which is THE SAME value as "num" (in fact, if num==2, then I get ‘2’s instead of ‘1’s). I’ve tried it with different compilers and different machines but I always get the same result and I cannot explain why.
I’m really going crazy, also because I’m gonna have an exam in about two weeks and this is basically the only thing I haven’t learned yet among all the required topics.

Thank you so much in advance 😿

>Solution :

  • EOF is an int so you must use int ch;

  • As mentioned in comments, you pass a single ch to strcat and not a null terminated string, so it will go haywire. Quick fix: strcat(line, (char[2]){ch,'\0'});.

    Or if you add a counter, you could just do line[count] = ch; which is much more efficient. Though in that case you’ll have to remember to append the null terminator manually in the end.

Also, sizeof(char) is always 1 by the very definition of sizeof, so it’s just a needlessly bloated way of writing 1.

Leave a Reply