I suspect you are using Microsoft Windows. In Microsoft’s C/C++ implementation, binary streams and text streams are different. If you had opened the file with "rb"
passed to fopen_s
as its third parameter, the file would be opened with a binary stream, and fread
would return the actual bytes in the file.
Since you opened the file with "r"
, it was opened as a text stream. In this mode, some processing is performed when reading and writing the file. Notably, Windows uses two characters, a new-line '\n'
and a carriage-return '\r'
, at the end of each line. When reading the file as a text stream, these two characters are reduced to a single '\n'
. Conversely, when writing a text stream, writing a '\n'
produces '\n'
and '\r'
in the file.
For a binary stream, ftell
gives the number of bytes from the beginning of the file. For a text stream, the C standard only specifies that ftell
is usable for resetting the stream position using fseek
—it is not necessarily the number of bytes (in the actual file) or characters (appearing in the stream) from the beginning of the file. A C implementation might implement ftell
so that it gives the number of bytes from the beginning of the file (and that is the 78 you are seeing), but, even if it does, you cannot easily use that to know how many characters are in the text stream.
Additionally, as others have noted in comments, this code is wrong:
for (int i = 0; !feof(file); i++)
{
fread(tmp + i, 1, 1, file);
size = i + 1;
}
The standard library routines do not know the end of the file file has been reached until you attempt a read and it fails because the end of the file was reached. For example, if there is one character in the file, and you read it, feof(file)
is still false—the end of the file has not been encountered. It is not until you try to read a second character and fread
fails that feof(file)
becomes true.
Because of this, the above loop ultimately sets size
to one more than the number of characters read because, at the beginning of the file iteration, !feof(file)
was true, so fread
was attempted, it failed, and then size
was set to i + 1
even though no byte was just read.
Because this is how feof
works, you could not use it for controlling a loop like this. Instead, you should write the loop so that it tests the result of fread
and, if it fail to read any characters, the code exits the loop. That code could be something like:
int i = 0;
do
{
size_t result = fread(tmp + i, 1, 1, file);
if (result == 0)
break;
i++;
}
size = i;
(Note that, if you were reading more than one byte at a time with fread
, additional code would be needed to handle the case where the number of bytes read was between zero and the number requested.)
Once that loop is fixed, you should see the number of characters in the stream reported as 75. Most likely, your file f.txt contains three lines of text with 72 characters total excluding the line endings. When read as a text stream, there are three '\n'
characters, so the total is 75. When read as a binary stream, there are three '\n'
characters and three '\r'
characters, so the total is 78.