Search code examples
cfilefgetc

fgetc() adds carriage return to line feed


I'm trying to make a program that concatenates multiple files to one. The code that i currently have is the following:

#include <string.h>
#include <stdio.h>

void main(int n, char** args) {
    if (n < 2) printf("Too few arguments. Format: <output> [files...]");

    FILE* output = fopen(args[1], "w");

    for (int i = 2; i < n; i++) {
        FILE* curr = fopen(args[i], "rb");

        while (!feof(curr)) {
            int c = fgetc(curr);

            fputc(c, output);
        }

        fclose(curr);
    }

    fclose(output);
}

But, when I have \n in a file, fgetc adds \r behind the \n in the new file. I've tried to open the file as binary, but it still adds the additional \r behind all \n-s.

How do I get rid of this functionality?


Solution

  • Since you open the input files in binary mode ("rb"), you get the CR/LF end-of-line sequences as separate bytes '\r' and '\n', which get stored into the output files as sequences of CR/CR/LF on legacy systems, because the output file opened in text mode converts '\n' as CR/LF and stores '\r' unchanged as CR.

    Just open the output file in binary mode as well, with "wb".

    Also fix some other problems as shown here:

    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char **argv) {
        if (argc < 2) {
            fprintf(stderr, "Missing arguments. Format: <output> [files...]\n");
            return 2;
        }
    
        FILE *output = fopen(argv[1], "wb");
        if (output == NULL) {
            fprintf(stderr, "Cannot open output file '%s': %s\n",
                    argv[1], strerror(errno));
            return 1;
        }
    
        for (int i = 2; i < argc; i++) {
            int c;
            FILE *curr = fopen(argv[i], "rb");
            if (curr == NULL) {
                fprintf(stderr, "Cannot open input file '%s': %s\n",
                        argv[i], strerror(errno));
                continue;
            }
            while ((c = fgetc(curr)) != EOF) {
                fputc(c, output);
            }
            fclose(curr);
        }
    
        fclose(output);
        return 0;
    }