1

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 ?

Imobilis
  • 1,475
  • 8
  • 29
  • 1
    Presumably, that means that your older question [Appending characters at the end of a specific range of lines in a file](http://stackoverflow.com/questions/32132572/appending-characters-at-the-end-of-a-specific-range-of-lines-in-a-file) is no longer relevant. Please remove it. – Jonathan Leffler Aug 23 '15 at 07:09
  • I suggest you use binary mode for your files: `fopen(..., "...b")` – pmg Aug 23 '15 at 07:19
  • @pmg it doesn't work at all in binary mode (data converted to unsigned char) – Imobilis Aug 23 '15 at 07:21

2 Answers2

2

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.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
0

Maybe you can put one more condition in your loop:

if(lines >= offsetLine && lines < endLine)
{
    ...//your code here before 'memcpy(p, " !!", 3);'
    if(lines==endline)
    {
        memmove(p + 3, p, strlen(p));    
    }
    //the end of your code here:
    memcpy(p, " !!", 3);//your code here
    i += 3;
    ln++;
}

Then you will move 3 more characters if this is the last line and put '!!' just after this.

Nicolas C
  • 225
  • 2
  • 8