Structure record binary file, refuses to display contents.

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

39 Replies - 5097 Views - Last Post: 30 September 2012 - 10:21 AM Rate Topic: -----

#1 mgrex  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 188
  • Joined: 25-March 10

Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 07:32 PM

The program is able to create a new inventory.dat file, in the executive directory.

After creating a basic/bogues record, I open the .dat file directly with Microsoft notepad, and I recognize that there contents indeed added to the file.

Back to the program, I can't seem to have the contents of binary file display on the screen properly.

Using the following statement, with ios::in included: fstream dataFile("inventory.dat", ios::out | ios::binary);
Will allow me call/select the, void display(), and void allContent(), functions, but inventory.dat file won't be created at run time.

Using fstream dataFile("inventory.dat", ios::out | ios::binary);

Would require me to declare a "dFile2", fstream variable, but void display and void allContent (to display every record at once), will result in a runtime error, when they are actually selected from the menu.

The author's closes example to this program, showed him first using a for loop to initialize 5 empty records. The directions to this assignment calls for no such thing.

Directions:

Quote

The program should have a menu that allows the user to perform the following tasks:
• Add new records to the file.
• Display any record in the file.
• Change any record in the file.


#include <iostream> 
#include <fstream> 
#include <string>
using namespace std;

struct Items
{
	string desc;
	int quantity;
	int wholeCost, retailCost;
	string dateAdded;
};

void options();
void addNew(fstream&);
void display(fstream&);
void allContent(fstream&);
//void change();

int main()
{
	//Items call;
	int option;

	//fstream dataFile("inventory.dat", ios::out | ios::binary);
	fstream dataFile("inventory.dat", ios::out | ios::in | ios::binary);	// ::in, won't allow program to create a blank .dat file on its own
	//Items record = {" ", 0, 0, 0, " "};
	//dataFile.write(reinterpret_cast<char *>(&record),sizeof(record)); //writes blank record

	do
	{
		options();
		cout << "Your selection: ";
		cin >> option;
		cout << endl;

		switch (option)
		{
		case 1:
			addNew(dataFile);
			break;
		case 2:
			display(dataFile);
			break;
		case 4:
			allContent(dataFile);
			break;
		case 3:
			//change();
			break;
		}


	} while (option > 0  && option < 5);

	cout << "\nBye-bye.\n";

	dataFile.close();

	system("pause");
	return 0;
}

void options()
{
	cout << "\nPress 1, to add a new record.\n";
	cout << "Press 2, to display current records.\n";
	cout << "Press 3, to change a record.\n";
	cout << "Press 4, to view all contents.\n";
	cout << "Press 0, to quit.\n\n";
}


void addNew(fstream& dFile)
{
	//fstream dFile2 ("Inventory.dat", ios::out | ios::binary);  
	Items call;  

	cout << "Enter Description: "; 
	cin.ignore();				//must be executed atleast once to allow user input later.
	getline(cin, call.desc);	//use this instead of cin >>, so content after spaces can be recognized
	//cin.getline(call.desc);	//
	cout << "Quantity	: ";
	cin >> call.quantity;
	cout << "Wholesale cost	: "; 
	cin >> call.wholeCost;
	cout << "Retail cost	: ";
	cin >> call.retailCost;
	cout << "Data added	: "; 
	cin.ignore();
	getline(cin, call.dateAdded);

	cout << "Adding record to file...\n";  

	// prevent new records from over-writing old records.
	dFile.seekp(ios::end); 
	dFile.write(reinterpret_cast<char *>(&call),sizeof(call));  

	cout << "size of record " << sizeof(call) << endl;

	dFile.close();
}

void display(fstream& dFile)
{
	//fstream dFile("Inventory.dat", ios::in);	//this produces an error message.
	//fstream dFile2("Inventory.dat", ios::in | ios::binary);  //infinite loop & compile time error
	Items call;

	int recNum;

	cout << "Enter the item's record number to view: ";
	cin >> recNum;

	dFile.seekg(recNum * sizeof(call), ios::beg);  
	dFile.read(reinterpret_cast<char *>(&call),sizeof(call));  

	cout << "Description	: " << call.desc << endl;  
	cout << "Quantity		: " << call.quantity << endl;  
	cout << "Wholesale cost: " << call.wholeCost << endl;  
	cout << "Retail cost	: " << call.retailCost << endl;  
	cout << "Date			: " << call.dateAdded << endl;  
}


void allContent(fstream& dFile)
{
	Items call;

	//fstream dFile2("inventory.dat", ios::in | ios:: binary);
	// Now read and display ALL the records 
	dFile.read(reinterpret_cast<char *>(&call), sizeof(call));

	while ( ! dFile . eof() ) 
	{ 
		cout << "Description	: " << call.desc << endl;  
		cout << "Quantity		: " << call.quantity << endl;  
		cout << "Wholesale cost: " << call.wholeCost << endl;  
		cout << "Retail cost	: " << call.retailCost << endl;  
		cout << "Date			: " << call.dateAdded << endl;  
		dFile.read(reinterpret_cast<char *>(&call), sizeof (call) ) ; 
	} 

	dFile.close();
}


Is This A Good Question/Topic? 0
  • +

Replies To: Structure record binary file, refuses to display contents.

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3575
  • View blog
  • Posts: 11,117
  • Joined: 05-May 12

Re: Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 07:48 PM

By using the std::string in your Items struct, you are potentially only writing out the bookkeeping information that the std::string uses to actually keep track of strings that it dynamically allocates. You should either change the way you serialize your structure to actually write out the string data, or change your structure so that it uses C-strings with the C-string buffers declared as part of the struct.
Was This Post Helpful? 1
  • +
  • -

#3 jimblumberg  Icon User is online

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,563
  • Joined: 25-December 09

Re: Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 08:02 PM

Quote

By using the std::string in your Items struct, you are potentially only writing out the bookkeeping information that the std::string uses to actually keep track of strings that it dynamically allocates.

Actually write should write out the actual contents of the string.


The problem is that these strings can be of different sizes. And when dealing with the read/write methods you must read the exact number of bytes you wrote, and since the string may be different sizes you will not be able to properly read the file data back in. There are ways to properly serialize read/write operations when using std::string but I suggest you follow Skydiver advice and change the structure to use statically allocated character arrays instead of std::string in your structure. However if binary files are not actually specified I recommend using text files instead.

Jim

This post has been edited by jimblumberg: 24 September 2012 - 08:03 PM

Was This Post Helpful? 3
  • +
  • -

#4 NathanMullenax  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 83
  • View blog
  • Posts: 176
  • Joined: 23-September 12

Re: Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 08:07 PM

Hello. This is by no means a complete answer, but this approach won't really work because sizeof(call) is always going to be 20 bytes, or whatever it might be on your system.

You could, on the other hand, make the two text fields of fixed width. Something like this:

struct Item
{
    char desc[80];
    int quantity, retail, wholesale;
    time_t dateAdded;
}



Then, you would have a fixed record size and your seeking and reading would be straightforward. Hope this helps.
Was This Post Helpful? 0
  • +
  • -

#5 mgrex  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 188
  • Joined: 25-March 10

Re: Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 08:50 PM

View PostSkydiver, on 24 September 2012 - 09:48 PM, said:

By using the std::string in your Items struct, you are potentially only writing out the bookkeeping information that the std::string uses to actually keep track of strings that it dynamically allocates. You should either change the way you serialize your structure to actually write out the string data, or change your structure so that it uses C-strings with the C-string buffers declared as part of the struct.



This would probably be the best option for me, given the possibility of future programming assignments emphasizing the use of strings over chars.

Where could one go, in reading/see examples of implementing this "serialization"? Sorry, but the term serializing a string & structure is totally new is new to me, and could be beyond my course's level.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3575
  • View blog
  • Posts: 11,117
  • Joined: 05-May 12

Re: Structure record binary file, refuses to display contents.

Posted 24 September 2012 - 11:49 PM

"Serialization" is just a fancy way of saying converting data into a format that can be used for transmission or storage. Often the word brings connotations of the data being in an object, class, or data structure, but there is no strict requirement for that.

Given a structure like:
struct Person
{
    string firstName;
    string lastName;
    int age;
}



You have a couple of options on how to store it. One option is to store all the data on a single line:
George, Takei, 75


by doing:
struct person = { "George", "Takei", 75 };
ofstream datafile("myDataFile.txt");
datafile << person.firstName << ", ", << person.lastName << ", " << person.age << endl;



Obviously, that data format encounters issues with names which may contain a comma within it.

Or 3 lines per record which alleviates the comma issue:
George
Takei
75



But these don't have the simplicity of being able to compute where the records are by simple multiplication like you had. -- You'd need to scan through the file using the linefeeds as separators.

If you want the simplicity maybe fixed line lengths maybe an option:
George··············Takei···············75·


(I put in the middle dot's '·' to help visual the space.)

Other ways to to store the data are using JSON:
{
    "Person" : 
    {
        "firstName" : "George",
        "lastName" : "Takei",
        "age" : 75
    }
}


Old style XML using elements:
<Person>
    <firstName>George</firstName>
    <lastName>Takei</lastName>
    <age>75</age>
</Person>


Modern style XML using attributes:
<Person firstName="George" lastName="Takei" age="75" />



Spoiler

This post has been edited by Skydiver: 25 September 2012 - 02:41 AM
Reason for edit:: Fixed spoiler tag.

Was This Post Helpful? 1
  • +
  • -

#7 jimblumberg  Icon User is online

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,563
  • Joined: 25-December 09

Re: Structure record binary file, refuses to display contents.

Posted 25 September 2012 - 02:21 AM

@Skydiver
You're correct about the structure/std::string not being properly written to the file with the write() function. To properly write a std::string to a binary stream you will either need to write the data() or use the c_str() member function.

Here is a example of writing a structure containing a std::string to a binary file:
Spoiler


Normally you would use member functions to write the structure/class to the file.

Also note that since I didn't write a record with a constant size you won't be able to use random access for this file. You will need to store the number of bytes you wrote to the beginning of the record to know how far to seek for the next record. Then you will need to read that "header" and seek to the next header, and continue to the correct record. Otherwise you will need to read in each record until you arrive at the correct location.


Jim

This post has been edited by jimblumberg: 25 September 2012 - 02:32 AM

Was This Post Helpful? 3
  • +
  • -

#8 mgrex  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 188
  • Joined: 25-March 10

Re: Structure record binary file, refuses to display contents.

Posted 26 September 2012 - 12:36 PM

Thanks for the posts, especially Jim's.

I have hit a dead end.

struct Items
{
	string desc;
	int quantity;
	int wholeCost, retailCost;
	string dateAdded;
};


My structure has 2 string variables.

I'm wondering how the 2nd string should be read from the file? This is what I did.
It starts on line 25.
Spoiler


The folk here, through a search for "write structure string to binary file"; used a char buffer to read a structure file that had 2 binary files.
http://stackoverflow...ile-io-question

In the "Add new record" block of my code, I thought about including a file access flag, like append, or seekp, to prevent current records from being over written. Would it be of any use?

I put it at line 24
Spoiler



Unfortunately now, a run-time error occurs, if I try to display a record, (after I just entered a new/first one).

Quote

Unhandled exception at 0x7536b727 in 12_13_Inventory.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0032eba4..



On another note, a potential source for the problem, is the inability for me to properly open/create the text file for input & output.
The program won't let me place the following flags within the case statement of int main() function, stating the following error (from swithc keyword): "transfer of control bypasses initialization of".

Spoiler


I tried putting the following 2, before the do-while statement, but the program wouldn't compile.
	fstream dataFile("inventory.dat", ios::in | ios::binary);
	fstream dataFile("inventory.dat", ios::out | ios::in | ios::binary);


So i did the following: fstream dataFile("inventory.dat", ios::out | ios::in | ios::binary);

The program compiled, but it failed to create text file even after Adding a new record, and then quit the program. There is a run time error when i try to display the record.

Leaving out the ios::in, flag will allow the program create a blank text file immediately at run time, though.
I noticed Jim, did: ofstream datafile("myData.dat", std::ios::binary);,
and then did: ifstream infile("myData.dat", std::ios::binary);

But I'm not sure if i may be permitted to do that for the school course.


Declaring: ifstream d2File("inventory.dat", std::ios::binary);

within, the display function (and updating the reinterpret_cast names, with d2File, instead of dFile), didn't make a difference as well.

Full code
Spoiler

This post has been edited by mgrex: 26 September 2012 - 12:44 PM

Was This Post Helpful? 0
  • +
  • -

#9 jimblumberg  Icon User is online

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,563
  • Joined: 25-December 09

Re: Structure record binary file, refuses to display contents.

Posted 26 September 2012 - 02:34 PM

The problem you are having in the following code is a switch statement is a "block" meaning that when you create something in that block it goes out of scope when you exit the block.
do
{
	options();
	cout << "Your selection: ";
	cin >> option;
	cout << endl;

	switch (option)
	{
	case 1:
		fstream dataFile("inventory.dat", ios::out | ios::binary);
		addNew(dataFile, call);
		dataFile.close();
		break;




So what you would need to do is create the instance before the switch and the open the file in the case statement.

        fstrean dataFile;
	switch (option)
	{
	case 1:
		dataFile.open("inventory.dat", ios::out | ios::binary);
		addNew(dataFile, call);
		dataFile.close();
		break;

Also part of your problem seems to be when you try to create a new file, for this you should add the ios::app flag to the open command. This should create the file if it doesn't exist, leave the existing contents intact if the file does exist. However this mode only allows appending data to the end of the file.

What ever method you use you should always check that the file opened successfully. I also recommend when using fstream that you only open the file once, passing the stream instance to the various functions that require access to the file.

The reason I suggest using ifstream, and ofstream instead of fstream is because the default open modes for the first two are much easier to understand and use. If you don't require read and write access at the same time they are much less complicated.

Also in your final code snippet I got this warning when I compiled your code:

Quote

main.cpp||In function ‘void display(std::fstream&, Items&)’:|
main.cpp|164|warning: ‘recNum’ may be used uninitialized in this function [-Wuninitialized]|



Now also remember that because you are using std::strings you can't use normal random access for this file, and you will not be able to replace a record that is in the middle of the file. This means that your display() function is probably incorrect. And why are you trying to open your file in the display function? You passed in the file stream you should use that.

I strongly recommend that you create functions for your actual read and write calls (similar to the example I posted). These functions should read/write an entire record at a time. You should pass a reference to the file stream and a single record to these functions. The read will return the information in this record and the write will write this record. This way you will have an easy way of iterating through the records to find the correct point in the file.

Jim
Was This Post Helpful? 1
  • +
  • -

#10 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1345
  • View blog
  • Posts: 4,631
  • Joined: 19-February 09

Re: Structure record binary file, refuses to display contents.

Posted 26 September 2012 - 03:33 PM

To check whether a file exists, an old trick is to attempt to open a file for input and check whether it opens.

bool fileExist(char filename[])
{
  fstream file(filename, ios::in | ios::binary);
  bool exist = true;

  if( !file.is_open() ) {
    exist = false;
  }

  file.close();
  return exist;
}


void checkFile(char filename[])
{
  if( !fileExist(filename) ) {
    cout << "Creating file" << endl;
    fstream file(filename, ios::out | ios::binary);
    file.close();
  }
}



In a final program I would probably be concerned that the file exist routine could be wrong because of a strange file error. Therefore I wouldn't write the file without asking the user, or would just tell the user a file (empty or not) is required and exit.


Then you can open for input and output.

  fstream dataFile("inventory.dat", ios::out | ios::in | ios::binary); 




Try the offset seek here, if you are having problems with displaying the data.

101	    dFile.seekp(0, ios::end); 


Was This Post Helpful? 0
  • +
  • -

#11 mgrex  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 188
  • Joined: 25-March 10

Re: Structure record binary file, refuses to display contents.

Posted 27 September 2012 - 08:33 AM

Yeah, I'm using the function "void display(fstream& dFile, Items & call)", to try and display it all at once, for now.

I implemented the bool function, define, recommended.

I confirmed it was implemented correct because, I removed the exclamation point, and the program displayed the message and proceeded to quit without errors.

			if(!fileExists("inventory.dat"))
			{
				cout << "File is not opened.\n";
				system("pause");
				return 0;
			}


It seems the program no longer crashes after selecting 2 (calls display Function) in the main menu, after I have entered a basic record.

Unfortunately it doesn't display the correct information. I've attached an image displaying this.

I noticed in the display function, there is a [0], on lines 13 & 26.


Spoiler


If there were are multiple entries, will I have to use a for/while loop, and change the [0] to [i], to display all the individual records at once?


Full code
Spoiler

Attached image(s)

  • Attached Image

This post has been edited by mgrex: 27 September 2012 - 08:34 AM

Was This Post Helpful? 0
  • +
  • -

#12 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3575
  • View blog
  • Posts: 11,117
  • Joined: 05-May 12

Re: Structure record binary file, refuses to display contents.

Posted 27 September 2012 - 08:47 AM

The code that looks like &call.dateAdded[0] is used to get the address of the beginning of the underlying array where std::string stores the characters. There is no need to increment the index.
Was This Post Helpful? 0
  • +
  • -

#13 jimblumberg  Icon User is online

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,563
  • Joined: 25-December 09

Re: Structure record binary file, refuses to display contents.

Posted 27 September 2012 - 08:48 AM

Quote

Unfortunately it doesn't display the correct information. I've attached an image displaying this.

You will need to post all your current code.

Quote

If there were are multiple entries, will I have to use a for/while loop, and change the [0] to [i], to display all the individual records at once?

No, to display all the records you will need to read each record the index doesn't change. That index is the index of the string not your "record". In the following line dateAdded is a string, call is your instance of your structure. So when you add the ampersand in front of this you are giving read() the address of the string's internal buffer.
dFile.read(&call.dateAdded[0], dateSize);


You really need to think about putting your "read" into it's own function so you can call it from multiple places.

Jim
Was This Post Helpful? 0
  • +
  • -

#14 mgrex  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 188
  • Joined: 25-March 10

Re: Structure record binary file, refuses to display contents.

Posted 27 September 2012 - 09:13 AM

I believe I posted the full code, right before the image.

I was able to get the program to diaplay the record
In lines 32, I had to use the instance Item call, instead of Item show.

Spoiler


Unfortunately another problem persists.
After adding 1 record, and successfully displaying it on screen with the command window, I exit the program.
When I start the program again, and go directly to loading the file, I get a run-time error stating: string subscript out of range.

Edit: On another note. When I reload/restart the program, then press 1 to enter a new record, the display function is able to run, without crashing. But it displays (and only displays), the original records I entered before the program crashed, instead of new one. This indeed shows the program.

#include <iostream> 
#include <fstream> 
#include <string>
using namespace std;

struct Items
{
	string desc;
	int quantity;
	int wholeCost, retailCost;
	string dateAdded;
};

void options();
void addNew(fstream&, Items &);
void display(fstream&, Items &);
void allContent(fstream&);
bool fileExists(string);
//void change();

int main()
{
	Items call;
	int option;

	fstream dataFile;//("inventory.dat", ios::out | ios::binary);
	//fstream dataFile("inventory.dat", ios::in | ios::binary);
	//fstream dataFile("inventory.dat", ios::out | ios::in | ios::binary);	// ::in, won't allow program to create a blank .dat file on its own
	//Items record = {" ", 0, 0, 0, " "};
	//dataFile.write(reinterpret_cast<char *>(&record),sizeof(record)); //writes blank record

	do
	{
		options();
		cout << "Your selection: ";
		cin >> option;
		cout << endl;

		switch (option)
		{
		case 1:
			dataFile.open("inventory.dat", ios::out | ios::binary | ios::app);
			addNew(dataFile, call);
			dataFile.close();
			break;
		case 2:
			dataFile.open("inventory.dat", ios::in | ios::binary);
			if(!fileExists("inventory.dat"))
			{
				cout << "File is not opened.\n";
				system("pause");
				return 0;
			}
			
			display(dataFile, call);
			break;
		case 4:
			allContent(dataFile);
			break;
		case 3:
			//change();
			break;
		}


	} while (option > 0  && option < 5);

	cout << "\nBye-bye.\n";

	dataFile.close();

	system("pause");
	return 0;
}

void options()
{
	cout << "\nPress 1, to add a new record.\n";
	cout << "Press 2, to display current records.\n";
	cout << "Press 3, to change a record.\n";
	cout << "Press 4, to view all contents.\n";
	cout << "Press 0, to quit.\n\n";
}


void addNew(fstream& dFile, Items &call)
{
	//fstream dFile2 ("Inventory.dat", ios::out | ios::binary);  
	//Items call;  



	cout << "Enter Description: "; 
	cin.ignore();				//must be executed atleast once to allow user input later.
	getline(cin, call.desc);	//use this instead of cin >>, so content after spaces can be recognized
	//cin.getline(call.desc);	//
	cout << "Quantity	: ";
	cin >> call.quantity;
	cout << "Wholesale cost	: "; 
	cin >> call.wholeCost;
	cout << "Retail cost	: ";
	cin >> call.retailCost;
	cout << "Data added	: "; 
	cin.ignore();
	getline(cin, call.dateAdded);

	cout << "Adding record to file...\n";  

	dFile.seekp(ios::end); 
	// first obtain size of the structure's string desc member vairable
	size_t sDescSize = call.desc.size();
	dFile.write(reinterpret_cast<char*>(&sDescSize), sizeof(size_t));
	// write actual string (descripton)
	dFile.write(call.desc.c_str(), sDescSize);

	// write out quantity member vairable
	dFile.write(reinterpret_cast<char*>(&call.quantity), sizeof(call.quantity));
	// write out wholeCost and retailCost
	dFile.write(reinterpret_cast<char*>(&call.wholeCost), sizeof(call.wholeCost));
	dFile.write(reinterpret_cast<char*>(&call.retailCost), sizeof(call.retailCost));

	// obtain size of the structure's string date member vairable
	size_t sDateSize = call.dateAdded.size();
	dFile.write(reinterpret_cast<char*>(&sDateSize), sizeof(size_t));
	// write actual string (date added)
	dFile.write(call.dateAdded.c_str(), sDateSize);


	// prevent new records from over-writing old records.
	/*dFile.seekp(ios::end); 
	dFile.write(reinterpret_cast<char *>(&call),sizeof(call));
	//dFile.write(reinterpret_cast<char *>(&call),sizeof(call));  

	cout << "size of record " << sizeof(call) << endl;*/

	dFile.close();	//I've placed this in case 1 within the do-while loop of int main.
}

void display(fstream& dFile, Items & call)
{
	//int recNum;
	//cout << "Enter the item's record number to view: ";
	//cin >> recNum;

	size_t descSize;
	// Read the size of the string
	dFile.read(reinterpret_cast<char*>(&descSize), sizeof(size_t));
	// resize string to the correct size
	call.desc.resize(descSize);
	// read in the string
	dFile.read(&call.desc[0], descSize);
	
	// read the quantity, whole & retail cost.
	dFile.read(reinterpret_cast<char*>(&call.quantity), sizeof(call.quantity));
	dFile.read(reinterpret_cast<char*>(&call.wholeCost), sizeof(call.wholeCost));
	dFile.read(reinterpret_cast<char*>(&call.retailCost), sizeof(call.retailCost));

	size_t dateSize;
	// Read the size of the string
	dFile.read(reinterpret_cast<char*>(&dateSize), sizeof(size_t));
	// resize string to the correct size
	call.desc.resize(dateSize);
	// read in the string
	dFile.read(&call.dateAdded[0], dateSize);


	//dFile.seekg(recNum * sizeof(call), ios::beg);  
	//dFile.read(reinterpret_cast<char *>(&call),sizeof(call));  

	Items show;

	cout << "Description	: " << call.desc << endl;  
	cout << "Quantity		: " << call.quantity << endl;  
	cout << "Wholesale cost: " << call.wholeCost << endl;  
	cout << "Retail cost	: " << call.retailCost << endl;  
	cout << "Date			: " << call.dateAdded << endl;  

	dFile.close();
}


void allContent(fstream& dFile)	//Display all/present contents at once
{
	Items call;

	//fstream dFile2("inventory.dat", ios::in | ios:: binary);
	// Now read and display ALL the records 
	dFile.read(reinterpret_cast<char *>(&call), sizeof(call));

	while ( ! dFile . eof() ) 
	{ 
		cout << "Description	: " << call.desc << endl;  
		cout << "Quantity		: " << call.quantity << endl;  
		cout << "Wholesale cost: " << call.wholeCost << endl;  
		cout << "Retail cost	: " << call.retailCost << endl;  
		cout << "Date			: " << call.dateAdded << endl;  
		dFile.read(reinterpret_cast<char *>(&call), sizeof (call) ) ; 
	} 

	dFile.close();
}

bool fileExists(string filename)
{
		fstream file(filename, ios::in | ios::binary);
		bool exist = true;

		if( !file.is_open()) 
		{
			exist = false;
		}

		file.close();
		return exist;
}

This post has been edited by mgrex: 27 September 2012 - 09:33 AM

Was This Post Helpful? 0
  • +
  • -

#15 jimblumberg  Icon User is online

  • member icon


Reputation: 4074
  • View blog
  • Posts: 12,563
  • Joined: 25-December 09

Re: Structure record binary file, refuses to display contents.

Posted 27 September 2012 - 09:55 AM

You're not going to have anything to display because you have never filled in your structure values in the display function. You are filling in the values of the parameter call but you try to display the values of show. Try printing the values of the call instance.

Also in the following snippet:
	size_t dateSize;
	// Read the size of the string
	dFile.read(reinterpret_cast<char*>(&dateSize), sizeof(size_t));
	// resize string to the correct size
	call.desc.resize(dateSize);  ////// Problem /////////
	// read in the string
	dFile.read(&call.dateAdded[0], dateSize);


You seem to be dealing with dateAdded but you resize() desc, why?

Edit:

Quote

Edit: On another note. When I reload/restart the program, then press 1 to enter a new record, the display function is able to run, without crashing. But it displays (and only displays), the original records I entered before the program crashed, instead of new one


Your display function only prints one record, not all the records. If you want to print out more than one record you will need to loop through the file reading, then displaying the records.

Jim

This post has been edited by jimblumberg: 27 September 2012 - 10:01 AM

Was This Post Helpful? 1
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3