Search code examples
cfilememoryiomemmove

Unwanted spaces in the output file


I am trying to create a function that appends !! at the very end of each line from(inclusive)-to(exclusive) of a text file. After I had several complications I actually succeeded. But not entirely.


int incldue_auto (char *script, unsigned int offsetLine, unsigned int endLine)
{
    size_t  fileSize;
    size_t  content = (endLine - offsetLine) * 3; // New characters
    char    *buffer;
    FILE*   fp;

    if((fp = fopen(script, "r")) == NULL)                               //return(1);
    if(fseek(fp, 0l, SEEK_END) != 0)                                    //return(2);
    if((fileSize = ftell(fp)) == (-1l))                                 //return(3);
    if(fseek(fp, 0l, SEEK_SET) != 0)                                    //return(2);
    if((buffer = calloc(fileSize + content, sizeof(char))) == NULL)     //return(4);
    if(fread(buffer, sizeof(char), fileSize, fp) != fileSize)           //return(5);
    if(fclose(fp) == EOF)                                               //return(6);
    {
        int i, i2;
        int lines = 0, ln = 0;
        for(i = 0; i < fileSize; i++)
        {
            if(ln >= (endLine - offsetLine) || i[buffer] == '\0') break;
            if(i[buffer] == '\n')
            {
                lines++;

                if(lines >= offsetLine && lines < endLine)
                {
                    char* p = (buffer + i); // \n

                    //if(*(p - 1) == '\n') continue;

                    memmove(p + 3,
                            p,
                            strlen(p)); // <-- Problematic line (I think)

                    memcpy(p, " !!", 3);

                    i += 3;
                    ln++;
                }
            }
        }

        fp = fopen(script, "w");
        fwrite(buffer, fileSize + content, sizeof(char), fp);
        fclose(fp);
    }
    free(buffer);
    return 0;
}

It relatively works just fine, except for that it doesn't append to the last line. And it fills the text file with spaces (NULLs maybe) at the end. I think it is because I am also moving the enzero-ed additional area content with that:

memmove(p + 3,
        p,
        strlen(p)); // <-- Problematic line (I think)

enter image description here So maybe I need to figure out what is the appropriate formula I have to use in order to make this work. Any ideas of how to make this work ?


Solution

  • Your loop condition is wrong:

    for(i = 0; i < fileSize; i++)
    

    After you have appended content to some lines, the end of the last line is moved beyond filesize and thus will no longer be treated.

    You test whether the end of the buffer has been reached with i[buffer] == '\0', but that may lead to reading beyond the buffer after having done all shifts and there are nio more trailing zeroes. This shouldn't happen, because the end line condition is checked first, but better be safe by callocing one more char, which will then make buffer a zero-terminated string.

    When you shift fewer lines than requested, because the file doesn't have the requested lines – say you shift lines 20 to 40 in a 30-line file – you still print out the trailing zeroes. You could either print the zero-terminated buffer as a string or you should keep track of the actual amount of data being appended.

    You keep two redundant line counts, lines and ln. Pick one and remove the other; it only needlessly confuses the code.