1

Simply problem, but slightly weird because of requirements.

Basically, I am trying to prevent buffer overflow when I am reading in file use file I/O because I am reading the file with a buffer size of 32. I feel like this should have been answered somewhere, but for the life of me my searching is not turning it up.

A simplified version of my code is here:

#include <stdio.h>                
#include <string.h>               
#define BUFFER_SIZE 32              
 
int main(int argc, char *argv[]) {
    FILE * read_file;
       
    char buffer[BUFFER_SIZE];
    read_file = fopen("test.txt","r");
    
    size_t num_rec = BUFFER_SIZE;
    while(fread(buffer, 1,num_rec, read_file) > 0) {
        printf("%s", buffer);
    }
    fclose(read_file);
    
    return 0;
}

Say I am trying to read a test.txt that has the contents:

This is a test file. 
The file is a test. 
I am having an overflow problem.
My C is not the best.

I get a output like this:

This is a test file.                                                                                                                                                               
The file is a test.                                                                                                                                                                
I am having an overflow problem.                                                                                                                                                   
My C is not the best.w problem.                                                                                                                                                    
My C is not the best

I understand that the simplest way of solving this is reading in 1 char at a time not 32, however, is there a way to solve this while still reading in 32 chars at a time?

1
  • 3
    printf expects a null terminated string, but you never arranged for buffer to be null terminated. Commented Feb 2, 2021 at 0:25

2 Answers 2

3

The fread() function reads binary data and doesn't add null bytes. You need to tell printf() how many bytes to print, which should be the number returned by fread().

size_t nbytes;
while((nbytes = fread(buffer, 1, num_rec, read_file)) > 0)
    printf("%.*s", (int)nbytes, buffer);

Note that fread() returns a size_t, but the .* operation in printf() requires an int; hence the cast (though it would be possible to save the value from fread() in an int and use that without the cast).

Sign up to request clarification or add additional context in comments.

Comments

3

The following saves the return value of fread then uses it to printf the characters that have been read, and no more than that.

size_t read_bytes;
while((read_bytes = fread(buffer, 1,num_rec, read_file)) > 0) {
    printf("%.*s", (int)read_bytes, buffer);
}

4 Comments

Remarkably similar to my proposed code. Great minds think alike, or something.
I am of the opinion that printf doesn't deserve all the bad press that it gets, and this was a chance to show how it can be used right ;-)
Yes. On the whole, printf() is mostly sane enough. It tends to be scanf() that earns people's ire, and that at least somewhat justifiably. One of the major omissions in scanf() is the analogue of * in printf() — although scanf() does support *, it has a completely different meaning (suppress assignment, not specify size dynamically).
Right, and the missing other * has long been one of my pet peeves about scanf.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.