C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old October 17th, 2012, 04:54 PM
ChokolAwt's Avatar
ChokolAwt ChokolAwt is offline
The bad and the ugly...
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jan 2007
Location: Oz... No??? Neverland then?
Posts: 142 ChokolAwt Negative: is most likely a SPAMMER and a traitor to the cause. 
Time spent in forums: 1 Day 6 h 21 m 2 sec
Reputation Power: 0
Send a message via ICQ to ChokolAwt Send a message via AIM to ChokolAwt
C++ binary file reader

Hello again dev-shed users,

I was tasked with writing a binary file viewer for homework. I've got my code running, and everything works great... but it seems to read/print out past the end of the file.

Basically, it displays 20 lines at a time, with 16 bits of hex followed by 16 bits of ASCII. After the 20 lines have printed, it pauses and waits for you to hit enter before printing the following 20 lines. Once it reaches the end of the file it quits.

Code:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <ios>

//
//function prototype
void PressEnterToContinue();


using namespace std;


void main(int argc, char *argv[])
{
	int n = 0; //used for prompting input file name
	int r;
	int x = 0, m = 0, a = 0;
	ifstream filename; //start filestream
	int size; //for file size
	char *file_buffer; //buffer for storing file

	//if user calls program from cmd prompt incorrectly or with "/?"
		if((argc < 2) || (strcmp(argv[1],"/?") == 0)) 
			{
				cout << "This program reads a file and prints each character as a hexadecimal\n";
				cout << "\n";
				cout << "Usage: hw5 [input filename]\n";
				exit(0);
			}
	
		//
		//prompt user for file name and continue to do so until a valid file name is given
		do
		{	
			filename.open(argv[1], ios::binary | ios::ate); //open file in binary mode
			if ( !filename )
				{
					cout << "Please enter a valid file name.\n";
					cin >> argv[1]; 
				}
			else	
				{
					n = 1; //end while loop since file is open
				}
		} while (n != 1);
		
		
		filename.seekg(0, ios::end); //seek EOF
		size = filename.tellg(); //return pointer at that position
		file_buffer = new char[size]; 
		filename.seekg(0, ios::beg); //seek beginning of file
		filename.read(file_buffer, size); //read file, up to int size, into file_buffer
		
		
		//print 20 lines in binary followed by ASCII
		do
		{
			for (int g = 0; g <= 20; g++)
			{
				
				for (x; x < 16 + a; x++)
					{
						r = file_buffer[x]; //caste cout to type int, so 'hex' can work
						cout << hex << setw(2) << uppercase << r << " ";
					}
				
				cout << "\t"; //align ASCII portion on right	
				
				for (m; m < 16 + a; m++)
					{
					//catch control character (endet/new line) and print '.' in it's place
						if (iscntrl(file_buffer[m]))
							cout << "."; 
						else	
							cout << file_buffer[m];
					}
				
				//increment a to print the next 16 bits
				a+=16;
				cout << endl;
			}
			
			//pause and wait for 'Enter' to continue
			PressEnterToContinue();

		//EOF is an int. file_buffer only stores characters. 
		//can't use file_buffer[x]		
		} while (x <= size ); 
		
		
		//
		//close file at program exit
		filename.close();
}

void PressEnterToContinue( )
 {
	cout << "Press ENTER to continue... ";
	cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
 }



Phew, so everything works great except when it reach the end of the file. Say there's not a full 20 lines left to print, it runs over and displays gobledeegook before exiting.

I think I'm going to need an if/else statement in my for loops to catch an EOF, but I'm having trouble wrapping my head around what flag to actually use.

file buffer is a type char * array, so it's an array of type string.

EOF is an int, in my case -1... so its going to stop at it, but not read it into the array. so i can't use:
Code:
file_buffer[x] != EOF 
since there is no -1 in my buffer.

help??



Thanks
~Tim
__________________
"Life is not a journey with the intent on arriving at the finish line in a pretty and well preserved body. But rather to skid in broadside, totally worn out, thoroughly used up and loudly proclaiming, "Wow! What a ride!" -Anonymous
Halo! || Diablo 2 LOD Modding || OLGA's BACK!

Reply With Quote
  #2  
Old October 17th, 2012, 05:28 PM
G4143 G4143 is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2012
Posts: 71 G4143 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 1 Day 7 h 39 m 39 sec
Reputation Power: 1
Are you saving the amount of bytes read with each filename.read(file_buffer, size) ? You need this value when you display your buffer so that you only display the values read.

Actually my bad, you have to call gcount() to find the number of characters read. Something like below:

Code:
#include <iostream>
#include <fstream>

int main(int argc, char** argv)
{
    char buffer[100];
    
    std::ifstream fin ("testfile", std::ifstream::binary);
    
    fin.read(buffer, 100);
    
    std::cout << fin.gcount() << std::endl;
	
	for (size_t i = 0; i < fin.gcount(); ++i)
		std::cout << (unsigned long)buffer[i] << std::endl;
    
    fin.close();
    return 0;
}

Reply With Quote
  #3  
Old October 19th, 2012, 10:37 AM
ChokolAwt's Avatar
ChokolAwt ChokolAwt is offline
The bad and the ugly...
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jan 2007
Location: Oz... No??? Neverland then?
Posts: 142 ChokolAwt Negative: is most likely a SPAMMER and a traitor to the cause. 
Time spent in forums: 1 Day 6 h 21 m 2 sec
Reputation Power: 0
Send a message via ICQ to ChokolAwt Send a message via AIM to ChokolAwt
that would work. I just ended up using the same closing statement as my do/while loop in an if/else inside my for loops.

only issue now is spacing for that last line. say i only write out 6 hex instead of 16, that
Code:
cout << "/t";
is no longer enough to get the ASCII portion to line up with the right side of the screen.

Reply With Quote
  #4  
Old October 20th, 2012, 03:16 PM
tariq82 tariq82 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2012
Posts: 1 tariq82 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 9 m 9 sec
Reputation Power: 0
Use a check inside the 2nd for loop.

Quote:
Originally Posted by ChokolAwt
Hello again dev-shed users,

I was tasked with writing a binary file viewer for homework. I've got my code running, and everything works great... but it seems to read/print out past the end of the file.

Basically, it displays 20 lines at a time, with 16 bits of hex followed by 16 bits of ASCII. After the 20 lines have printed, it pauses and waits for you to hit enter before printing the following 20 lines. Once it reaches the end of the file it quits.

Code:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <ios>

//
//function prototype
void PressEnterToContinue();


using namespace std;


void main(int argc, char *argv[])
{
	int n = 0; //used for prompting input file name
	int r;
	int x = 0, m = 0, a = 0;
	ifstream filename; //start filestream
	int size; //for file size
	char *file_buffer; //buffer for storing file

	//if user calls program from cmd prompt incorrectly or with "/?"
		if((argc < 2) || (strcmp(argv[1],"/?") == 0)) 
			{
				cout << "This program reads a file and prints each character as a hexadecimal\n";
				cout << "\n";
				cout << "Usage: hw5 [input filename]\n";
				exit(0);
			}
	
		//
		//prompt user for file name and continue to do so until a valid file name is given
		do
		{	
			filename.open(argv[1], ios::binary | ios::ate); //open file in binary mode
			if ( !filename )
				{
					cout << "Please enter a valid file name.\n";
					cin >> argv[1]; 
				}
			else	
				{
					n = 1; //end while loop since file is open
				}
		} while (n != 1);
		
		
		filename.seekg(0, ios::end); //seek EOF
		size = filename.tellg(); //return pointer at that position
		file_buffer = new char[size]; 
		filename.seekg(0, ios::beg); //seek beginning of file
		filename.read(file_buffer, size); //read file, up to int size, into file_buffer
		
		
		//print 20 lines in binary followed by ASCII
		do
		{
			for (int g = 0; g <= 20; g++)
			{
				
				for (x; x < 16 + a; x++)
					{
						r = file_buffer[x]; //caste cout to type int, so 'hex' can work
						cout << hex << setw(2) << uppercase << r << " ";
					}
				
				cout << "\t"; //align ASCII portion on right	
				
				for (m; m < 16 + a; m++)
					{
					//catch control character (endet/new line) and print '.' in it's place
						if (iscntrl(file_buffer[m]))
							cout << "."; 
						else	
							cout << file_buffer[m];
					}
				
				//increment a to print the next 16 bits
				a+=16;
				cout << endl;
			}
			
			//pause and wait for 'Enter' to continue
			PressEnterToContinue();

		//EOF is an int. file_buffer only stores characters. 
		//can't use file_buffer[x]		
		} while (x <= size ); 
		
		
		//
		//close file at program exit
		filename.close();
}

void PressEnterToContinue( )
 {
	cout << "Press ENTER to continue... ";
	cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
 }



Phew, so everything works great except when it reach the end of the file. Say there's not a full 20 lines left to print, it runs over and displays gobledeegook before exiting.

I think I'm going to need an if/else statement in my for loops to catch an EOF, but I'm having trouble wrapping my head around what flag to actually use.

file buffer is a type char * array, so it's an array of type string.

EOF is an int, in my case -1... so its going to stop at it, but not read it into the array. so i can't use:
Code:
file_buffer[x] != EOF 
since there is no -1 in my buffer.

help??



Thanks
~Tim


You can put a check inside the 2nd for loop. Like this:
if (x>size) {return 0;}..Here is what you can try for the following part of your code and it should work:

Code:
while (x <= size )
		{
			for (int g = 0; g <= 20; g++)
			{
				
				for (x; x < 16 + a; x++)
					{
                                         if (x>size) {
                                            return 0;
                                          }
                                         else{
						r = file_buffer[x]; //caste cout to type int, so 'hex' can work
						cout << hex << setw(2) << uppercase << r << " ";
                                       }
					}
				
				cout << "\t"; //align ASCII portion on right	
				
				for (m; m < 16 + a; m++)
					{
					//catch control character (endet/new line) and print '.' in it's place
						if (iscntrl(file_buffer[m]))
							cout << "."; 
						else	
							cout << file_buffer[m];
					}
				
				//increment a to print the next 16 bits
				a+=16;
				cout << endl;
			}
			
			//pause and wait for 'Enter' to continue
			PressEnterToContinue();

		//EOF is an int. file_buffer only stores characters. 
		//can't use file_buffer[x]		
		} 

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > C++ binary file reader

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap