Click here to Skip to main content
15,904,652 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have this error when I read/write binanry file with data are structs (it has string members)

this is my code:

C++
//read data from file to linked list
int ReadFile(char* fname, Node* &head)
{
	Node* cur;
	BOOK a;
	ifstream iFile;
	iFile.open(fname, ios::binary);

	if(iFile.good() == 0)
		return 0;

	while( iFile.read((char*)&a, sizeof(a)) )
	{
		if (head==NULL)
		{
			head = new Node;
			head->data = a;
			head->pNext = NULL;
			cur = head;
		}
		else
		{
			cur->pNext = new Node;
			cur = cur->pNext;
			cur->data = a;
			cur->pNext = NULL;
		}
	}
	iFile.close();
	return 1;
}

//write data from LL to file
int WriteFile(char* fname, Node* head)
{
	Node* cur = head;
	ofstream oFile;
	oFile.open(fname, ios::binary);

	if(oFile.good() == 0)
		return 0;
	while(cur != NULL)
	{
		WriteNode(oFile, cur->data);
		cur = cur->pNext;
	}
	oFile.close();
	return 1;
}

//write one node
void WriteNode(ofstream& out, BOOK a)
{
	out.write((char*)&a, sizeof(a));
}


when I have created data.bin file which save the info. I call ReadFile function in main() function to read data. I got the error.

http://diendan.congdongcviet.com/attachment.php?attachmentid=8807&d=1331693026[^]

this is my struct:

C++
struct BOOK
{
    string isbn;        
    string bookname;    
    string genre;       
    string author;      
    string publisher;   
    int year;           
    int amount;         
};

struct Node
{
    BOOK data;
    Node* pNext;
};


So how to solve this problem?
thank you!!
p/s: how to insert an image?
Posted
Updated 23-Apr-12 0:40am
v3

1. Casting a Book * to a char * is a very, very bad thing. Don't. So is passing a Book by value to function WriteNode. Lots of copy constructors running there.
2. You don't have to insert an image: if you press CTRL-C when you have a message box open, the text in the message box gets copied to the clipboard.

Best wishes,
Pablo.
 
Share this answer
 
v2
Comments
5fox 23-Apr-12 9:10am    
can you explain clearly? I don't understand much, the syntax of write is char*
Pablo Aliskevicius 23-Apr-12 9:47am    
The "Book" object is built (among others) of std::string members.
std::string may hold pointers to whatever, wherever (out of the Book instance), so when you save the Book, you're saving pointers.
Pointers are variables that hold an address in the computer's memory.
When you reload those pointers, you receive the same address again. But the contents of that memory may be now something else (if available).
See also solution #2.

Hope this helps,
Pablo.
5fox 23-Apr-12 10:03am    
thank you!
You should properly serialize[^] your struct. See, for instance: "Serialization of STL class"[^].
 
Share this answer
 
Comments
Aescleal 23-Apr-12 10:14am    
Anyone that points a beginning programmer at boost deserves a 5.
CPallini 23-Apr-12 10:57am    
Thank you.
Usman Hunjra 23-Apr-12 13:35pm    
I give 5 ..
Wheel, meet your new inventor. Fire, meet your new discoverer.

I know you've probably had this annoying little problem foisted on you by a lecturer that thinks you have to learn how to program C++ from first principles. However you're using strings so why not go the whole hog and use a list from the standard library?

Once you've defined your books then creating a list is pretty simple:

std::list<book> my_books;

There you go, all the farting about with nodes disposed of [1]. Next up is how you read your books from a file and write them to it. Reading and writing is just copying so why not use the copy algorithm from the standard library?

To write them:

C++
std::copy( my_books.begin(),
           my_books.end(),
           std::ostream_iterator<book>( file_stream ) );


To read them:

C++
std::copy( std::istream_iterator<book>( file_stream ),
           std::istream_iterator<book>(),
           std::back_inserter( my_books ) );


Now there's a snake in the grass here... Yep, you have to write some code. What you have to do is implement insertion and extraction operators (<< and >>) for your structure, Book. Then you all that code will work like a dream. Or a nightmare :-). And you'll have the bonus of being able to read and write Books from the console with no code changes.

One final thing - if you can get a better C++ teacher go and get one. Implementing your own lists is so last century and anyone that's making you write your own is a sadist.

Cheers,

Ash

[1] You can now make the joke:

Coder: "My code has no nodes"

Reviewer: "How does it smell?"

Coder: "Terrible!"

If you're not a native English speaker and miss the joke, don't worry, it ain't that funny unless you've heard the original and even then it's a bit poor.
 
Share this answer
 
v2
Comments
5fox 23-Apr-12 11:15am    
according to you, use list in list STL is better
Aescleal 23-Apr-12 12:01pm    
Infinitely better as you don't have to write it and it's probably as efficient as any doubly linked list you can come up with. I don't mean that as an insult BTW, I couldn't come up with a non-intrusive list that did any better than std::list.
[FULLY EDITED]
really sorry for the wrong input given first.
See the below link
http://support.microsoft.com/kb/813810[^]
it seems STL string has issue while executing it in multiprocessor system. I executed your code in both single processor CPU and multiprocessor. In single processor i got it executed correct without any issue(only some logical issue with the code). So in multiprocessor i used char* instead of STL string and it is working fine
C++
//read data from file to linked list
struct BOOK
{
    char isbn[20];        
    char bookname[20];    
    char genre[20];       
    char author[20];      
    char publisher[20];   
    int year;           
    int amount;
	BOOK()
	{
	}
	~BOOK()
	{
	}
	void operator = ( BOOK b)
	{
		strcpy_s( this->author, b.author );
		strcpy_s( this->bookname, b.bookname );
		strcpy_s( this->genre, b.genre );
		strcpy_s( this->isbn, b.isbn );
		strcpy_s( this->publisher, b.publisher );
	}
};
 
struct Node
{
    BOOK data;
    Node* pNext;
};
int ReadFile(char* fname, Node*& head)
{
	Node* prev;
	Node* cur;
	BOOK a;
	ifstream iFile;
	iFile.open(fname, ios::binary);
 
	if(iFile.good() == 0)
		return 0;
 
	while( iFile.read((char*)&a, sizeof(BOOK)) )
	{
		if (head==NULL)
		{
			head = new Node;
			head->data = a;
			head->pNext = NULL;
			prev = head;
		}
		else
		{
			cur = new Node;
			cur->data = a;
			cur->pNext = NULL;
			prev->pNext = cur;
			prev = cur;
		}
	}
	iFile.close();
	return 1;
}

//write one node
void WriteNode(ofstream& out, BOOK a)
{
	out.write((char*)&a, sizeof(a));
}

//write data from LL to file
int WriteFile(char* fname, Node* head)
{
	Node* cur = head;
	ofstream oFile;
	oFile.open(fname, ios::binary );
 
	if(oFile.good() == 0)
		return 0;
	while(cur != NULL)
	{
		WriteNode(oFile, cur->data);
		cur = cur->pNext;
	}
	oFile.close();
	return 1;
}

int main()
{
	Node* pNode = new Node;
	pNode->data.amount = 201;
	strcpy_s( pNode->data.author, "Name1" );
	strcpy_s( pNode->data.bookname, "c++" );
	strcpy_s( pNode->data.genre, "YYY" );
	strcpy_s( pNode->data.isbn, "Yes" );
	strcpy_s( pNode->data.publisher, "abcd" );
	pNode->data.year = 1999;

	Node* pNode1 = new Node;
	pNode1->data.amount = 201;
	strcpy_s( pNode1->data.author , "Name2" );
	strcpy_s( pNode1->data.bookname , "java" );
	strcpy_s( pNode1->data.genre , "XXX" );
	strcpy_s( pNode1->data.isbn , "No" );
	strcpy_s( pNode1->data.publisher , "defg" );
	pNode1->data.year = 1999;
	pNode1->pNext = 0;
	
	pNode->pNext = pNode1;
	WriteFile( "D:\\Test\\Test", pNode );

	Node* pNode2 = 0;
	ReadFile( "D:\\Test\\Test", pNode2 );
	while( pNode2 != 0 )
	{
		cout<< "AUTHOR is " << pNode2->data.author << endl;
		pNode2 = pNode2->pNext;
	}
        // handle memory free stuffs

	getchar();
	return 0;
}
 
Share this answer
 
v3
Comments
5fox 23-Apr-12 9:15am    
it still is. but the error is "an unhandled win32 exception occurred in filename.exe [1336].
if i have greater than 2 books, i think your readfile function can't add it to the list. This is my opinion, what do you think?
5fox 23-Apr-12 11:04am    
readfile function in #3 is not mine, so i can't understand it clearly!
Philippe Mori 23-Apr-12 19:07pm    
This code is not better than the original. In fact, it is worst as there is a memory leak, it doesn't fix the original problem and the comment is completly wrong.
Aescleal 24-Apr-12 5:31am    
VC++ hasn't had that string synchronisation problem since about 2002. If you're still using VC++ 6.0 then you should really change your compiler, you're being a mug to yourself.

Look up gcc or VC++2010 express edition for a pair of fair better compilers that actually implement most of the C++98 and C++03 standards.
Resmi Anna 24-Apr-12 6:09am    
i got the crash in vs 2010 with multiprocessor...it is working fine in VS 6.0 with single processor...the issue is with STL string only

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900