3

I want to copy the contents of file1 to file2 exactly as they are (keeping spaces and newlines). I specifically want to copy these contents one small block of chars at a time(this is a small segment of a larger project so bear with me).

I have attempted the following:

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

#define MAX 5

int main(int argc, char *argv[]) {
    FILE *fin, *fout;
    char buffer[MAX];
    int length;
    char c;

    if((fin=fopen(argv[1], "r")) == NULL){
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    if((fout=fopen(argv[2], "w")) == NULL){
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    while(1){
        length = 0;
        while((c = fgetc(fin)) != EOF && length < MAX){
            buffer[length++] = (char) c;
        }
        if(length == 0){
            break;
        }
        fprintf(fout, "%s", buffer);
    }
    fclose(fout);
    fclose(fin);
}

However, this causes incorrect output to my file2. Any input would be appreciated.

nalzok
  • 14,965
  • 21
  • 72
  • 139

3 Answers3

1

Your buffer is not zero-terminated. Use fwrite instead of fprintf:

  fwrite(buffer, 1, length, fout);

And you should check the error too. So compare return code of fwrite to length and if it differs, either retry the write of remaining bytes (if positive) or print appropriate error message via perror("fwrite") (if return code is negative).

Additionally you may consider opening the files in binary mode which would cause difference on windows, i.e. pass "rb" and "wb" to fopen.

Last but not least, instead of looping and getting one character at a time, consider using fread instead:

length = fread(buffer, 1, MAX, fin);
Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
1

Here is a simple example.(with no error checking)

You should use fwrite() since the string you would write to file is not a "null-terminated". And also note that "b" mode is specified with fopen(), which means you want to open the file as a binary file.

#include <stdio.h>
#include <stdlib.h>
#define MAX 5
#define FILE_BLOCK_SIZE 50
int _tmain(int argc, _TCHAR* argv[])
{
    FILE *fin, *fout;
    unsigned char *BufContent = NULL;
    BufContent = (unsigned char*) malloc(FILE_BLOCK_SIZE);
    size_t BufContentSz;

    if((fin=fopen("E:\\aa.txt", "rb")) == NULL){
        perror("fopen");
        exit(EXIT_FAILURE);
    }
    if((fout=fopen("E:\\bb.txt", "wb")) == NULL){
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    while ((BufContentSz = fread(BufContent, sizeof(unsigned char), FILE_BLOCK_SIZE, fin)) > 0) 
    {
        fwrite(BufContent, sizeof(unsigned char), BufContentSz, fout);
    }

    fclose(fout);
    fclose(fin);

    delete BufContent;
    return 0;
}
Chanhee Jo
  • 199
  • 6
0

First off, change char buffer[MAX]; to int buffer[MAX];, and char c; to int c;, for a char can be either signed char or unsigned char, depending on your implementation. In the later case, c = EOF will give c a large positive number(It's unsigned ,anyway), so the loop will never end. A int will be large enough to hold all characters and EOF though.

Then, change your

fprintf(fout, "%s", buffer);

to

fwrite(buffer, 1, length, four);

This is because fprintf(fout, "%s", buffer); call for a C-style string, with ends with a '\0', but your buffer isn't zero-terminated. As a result, the program will keep copying the stuff in the stack, until a '\0' is met, leaving lots of garbage in file2.

nalzok
  • 14,965
  • 21
  • 72
  • 139