Thread: Printf Output Confusion

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    162

    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:

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    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:
    fbuf[flen] = 0;

    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
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Jul 2006
    Posts
    162
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I have some questions :(
    By geekrockergal in forum C Programming
    Replies: 19
    Last Post: 02-01-2009, 09:44 AM
  2. Data Structure Eror
    By prominababy in forum C Programming
    Replies: 3
    Last Post: 01-06-2009, 09:35 AM
  3. Weird output of scanf and printf.
    By omnificient in forum C Programming
    Replies: 2
    Last Post: 12-05-2007, 01:28 PM
  4. menu problem!!! need U R G E N T help!!!
    By catcat28 in forum C Programming
    Replies: 16
    Last Post: 11-19-2007, 01:32 PM
  5. Simple C question: user input to repeat a loop
    By evernaut in forum C Programming
    Replies: 2
    Last Post: 11-18-2006, 09:23 AM