-
Printf Output Confusion
I'll state my problem first, the code is below if you need to see what I did.
I have the contents of a file being stored in a char array, if I use printf() with %c and loop through each item the correct output is displayed. If I used %s only a portion of the information is displayed, only the first couple characters in the array.
Any help in figuring out why that is would be greatly appreciated.
If you need to know, I'm using Dev-C++ 4.9.9.1
The file I'm opening is a Bitmap image of 1 white pixel, created in MS Paint saved as a 24bit bitmap. When you create it (at least in Windows), it should be a 58byte file.
Code:
#include <cstdlib>
#include <stdio.h>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
char ch='a'; // Char Buffer
char* fbuf=NULL; // Message Buffer
int flen=0; // File Length
fstream fin ("1px.bmp"); // Open File
if (fin.is_open())
// If the file is_open()
{
// First get the length of the file
fin.seekg(0, ios::end); // point to the end
flen = fin.tellg(); // get the position
fin.seekg(0, ios::beg); // return the pointer
fbuf = new char[flen]; // initialize Message Buffer
int tmp=0; // to track current position
// (i will use tellg() instead later)
while (!fin.eof())
// while we are not at the end of the file
{
fin.get(ch); // grab a single char
fbuf[tmp] = ch; // store it in the Message Buffer
tmp++; // incriment the temporary position int
}
fin.close(); // we're done with the file so close() it
}
printf ("Content (c):\n");
for (int j=0; j<flen; j++)
// here I incriment j:0->flen
{
printf ("%c", fbuf[j]); // printing out each char one at a time
}
printf ("\n\n");
printf ("Content (s):\n");
printf ("%s", fbuf); // here instead I print as a string (char array, correct?)
// the end
printf ("\n\n");
system ("PAUSE");
return EXIT_SUCCESS;
}
My output is as follows exactly:
Code:
Content (c):
BM: 6 ( ☺ ☺ ☺ ↑ ♦
Content (s):
BM:
-
First off, you should stick to either C or C++ for your I/O and not mix C++ I/O streams with C functions such as printf.
It seems likely that one of the characters you read into the buffer could be a NULL which would terminate the printing of anything beyond that NULL. If the data from the file contains such charaters, then you'll need to deal with it in some manner.
Code:
flen = fin.tellg(); // get the position
fin.seekg(0, ios::beg); // return the pointer
fbuf = new char[flen]; // initialize Message Buffer
If you intent is to use %s later to print out the entire file's data, then (even if the file's data were to not contain a NULL so you could use printf successfully with it) you would still need to add a NULL to the buffer manually at the end. The space you've reserved is insufficient, you need to add 1:
Code:
fbuf = new char[flen+1];
And later add in the NULL after the file read loop:
Code:
while (!fin.eof())
// while we are not at the end of the file
{
fin.get(ch); // grab a single char
fbuf[tmp] = ch; // store it in the Message Buffer
tmp++; // incriment the temporary position int
}
It is normally not good to use eof() to control ones loops. The eof condition is set only after an attempt has been made to read past the end of the file. This means that after the last character is read, eof is still false and so you'll go through the loop again whereupon the next get call will fail but you'll still attempt to store a bogus character into the buffer. You need to alter this loop a bit:
Code:
while( fin.get(ch) )
{
fbuf[tmp] = ch; // store it in the Message Buffer
tmp++; // incriment the temporary position int
}
The get call will return a reference to the file stream which will be interpreted in the context of the while loop's conditional as a true (stream is still good) or false (file encountered some error) value so the loop will not go beyond what you want it to. Better yet, just call the read function to get all the data at once:
Code:
fin.read(fbuf,flen); // Read all flen characters in one go into fbuf buffer
-
I really appreciate the informative reply, I guess I did have some missconceptions afterall, internet tutorials lack a lot of these minor details.
Maybe I'll invest in a good book instead, something that actually tells me things like you have about these things.