0

I am reading a file using a small buffer and printing it. But after every time it after fread and printf some unrecognized characters appear. I do not know why.

I think it has something to do with printf and not fread. This is the small code:

 f = fopen(host_filename2, "r");

char chunks[4];
int size;
do {
    memset(chunks,0,sizeof chunks);
    size = fread(chunks, 1, sizeof chunks, f);
    if (size <= 0) break;
    printf("%s", chunks);
} while (size == sizeof chunks); 

fclose(f);
wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • 7
    `printf("%s", chunks);` - `chunks` is not a [null-terminated string](https://stackoverflow.com/questions/2037209/what-is-a-null-terminated-string), so `printf` continues to read and print characters until it hit a zero byte, which is undefined behavior. – kotatsuyaki Dec 21 '22 at 12:39
  • 4
    For the reason stated in the previous comment, change `printf("%s", chunks);` to `printf("%.*s", size, chunks);`, which will limit the number of characters printed to `size`. See the documentation for [`printf`](https://en.cppreference.com/w/c/io/fprintf) for further information. – Andreas Wenzel Dec 21 '22 at 12:41
  • What you really should do is read one less character and place a null-byte after the call to ```fread```. – Harith Dec 21 '22 at 12:53
  • Do you have any reason to believe rhat you are reading a text file? – stark Dec 21 '22 at 12:55
  • 1
    Instead of `printf`, use `fwrite`. – William Pursell Dec 21 '22 at 12:59

1 Answers1

2

printf("%s", chunks); expect chunks[] to be a string. Strings have a null character at the end and fread(chunks, 1, sizeof chunks, f) did not certainly read a '\0' and form a string.

Write what was read (Best)

// printf("%s", chunks);
fwrite(chunks, 1, size, stdout);

Write what was read up to a '\0'

"%.*s" writes a limited amount from a character array, stopping at the size or when a '\0' is detected.

// printf("%s", chunks);
printf("%.*s", size, chunks);

Append your own '\0'

This will perform like printf("%.*s", size, chunks).

char chunks[4 + 1];  // One bigger
int size;
do {
    // memset(chunks,0,sizeof chunks - 1);  // Not needed
    size = fread(chunks, 1, sizeof chunks - 1, f);
    if (size <= 0) break;
    chunks[size] = '\0';
    printf("%s", chunks);
} while (size == sizeof chunks - 1); 

Avoid naked magic numbers

Use size_t for array sizing.

#define CHUNK_SIZE 4
char chunks[CHUNK_SIZE];
size_t size;
size_t n = sizeof chunks/sizeof *chunks;
do {
    size = fread(chunks, sizeof *chunks, n, f);
    if (size <= 0) break;
    fwrite(chunks, sizeof *chunks, size, stdout);
} while (size == sizeof chunks); 
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256