cfilefgetc

Why does fputc() append to my file and not overwrite it?


I'm writing a C Program that changes all uppercase characters to lowercase from a certain file. The problem is, after storing all characters (processed) in a string, and trying to print all characters inside that file, they are appended to that file, and not overwritten. I'm using "r+" as a permission.

This is my code:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define MAX 1024

int main(int argc, char **argv)
{
    if (argc != 2) {
        printf("Invalid number of arguments.\n");
        exit(1);
    }

    FILE *f = fopen(argv[1], "r+");
    if (f == NULL)
    {
        printf("Could not open specified file.\n");
        exit(2);
    }

    char buf[MAX];
    int len = 0;
    
    while(!feof(f))
    {
        int c = fgetc(f);
        if (c >= 'A' && c <= 'Z')
            c = tolower(c);
        if (c != EOF) {
            buf[len] = c;
            len++;
        }
    }

    for (int i = 0; buf[i] != '\0'; i++)
        fputc(buf[i], f);

    fclose(f);

    return 0;
}

Same problem with fputs(buf, f). Also even after appending, some "strange" characters appear at the end of the selected file.

What's the problem, exactly? How can I fix it? Thank you. Help would be appreciated.


Solution

  • Your program has incorrect and even undefined behavior for multiple reasons:

    Here is a modified version:

    #include <ctype.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        FILE *f;
        int c;
    
        if (argc != 2) {
            printf("Invalid number of arguments.\n");
            return 1;
        }
    
        if ((f = fopen(argv[1], "r+")) == NULL) {
            printf("Could not open file %s.\n", argv[1]);
            return 2;
        }
    
        while ((c = getc(f)) != EOF) {
            if (isupper(c) {
                fseek(f, -1L, SEEK_CUR);
                putc(tolower(c), f);
                fseek(f, 0L, SEEK_CUR);
            }
        }
        fclose(f);
        return 0;
    }
    

    Note that it would be more efficient and reliable to read from the file and write to a different file. You can try this simplistic filter and compare with the above code for a large file:

    #include <ctype.h>
    #include <stdio.h>
    
    int main() {
        int c;
        while ((c = getchar()) != EOF) {
            putchar(tolower(c));
        }
        return 0;
    }