you cannot write a linked list to a file directly. You are saving the pointers, which are invalid after the program ends, and not the data pointed to.
there are 2 primary ways to handle this. Method one is to put the linked list into something like a vector and change the pointers to the indices into the vector, then just write the vector out.
method 2 is to iterate the list and write the DATA to the file, and rebuild the list from scratch by reading each record from the file and inserting it into your list object one by one.
in method 2, you can waste space to save effort and time: write each node to the binary file one by one, but when you read it, you must IGNORE the pointers entirely and rebuild as I said, even though you saved them. Basically, saving the pointers on each node wastes the space the pointer variables consume, but it allows a simple write() statement. If you want to avoid wasting the space, you have to write() it field by field, leaving the pointers out.
In method 1, you will want to add a boolean 'deleted' or 'empty' to node so that you can reuse deleted vector locations and skip unused locations when processing it.
if NODE itself is a template, you must assume that NODE may also contain the pointer problem and cannot be safely written out with write() directly. EG if NODE is a next pointer and a vector<int> or string as the data parts, write() has the same problem again: you can't write the pointer, you have to write the data (vectors, strings, and stl containers in general use pointers for the data portions under the hood). If NODE is a simple type like int or double etc, you can use write() on it directly.
basically, write() on something that is full of pointers writes the pointer's value to the file, not the data under the pointer, and this issue crops up a lot with the STL, so you need to understand this concept and how to deal with it. Also, write() dumps a block of bytes to the file. The blocks must be in sequential memory, like an array. You can't dump a linked list or tree: the nodes are not adjacent to each other in memory (classic pointers approach) unless you forced them to be that way (method 1 above!).
As seeplus said, you're looking for "serialization". In general it's quite complicated and we tend to use a pre-written library to accomplish it. Using the boost serialization library, the "list_of_lists" code might look something like the following.
Thank you guys all. I will search more on the serialization topic
@dutch: That is quite a code. Doing it with jonnin's method 2, can I write something like the following to traverse and write the key and data of the list to my file?
1 2 3 4 5 6 7 8 9 10 11 12 13 14
if (head == NULL) {
cout << "No nodes in the list ";
}
else {
ofstream outfile;
outfile.open("data.txt", ios::app);
node* temp = head;
while (temp != NULL) {
outfile << "[" << temp->key << " | " << temp->data << "]" << endl;
temp = temp->next;
}
outfile.close();
}
Just to let you know, I only intend to write to a file and not to be able to read from that.
If you write the list that way, then how will you read it? You need some sort of sentinel to signal the end of the list. When you have that, you don't need a special case for an empty list.
yes, you can do that.
To the above post, you should track the # of items in your list (++ when you insert, -- when you delete is sufficient) and you can write that, making the file something like:
5
[0|100]
[1|101]
[2|102]
[3|103]
[4|104]
which is fine. You tossed out your write() which is also fine if a text file does what you need. Its at least better to do text files at first, to get it working, then if you want to revisit binary files you can.
all I see is you gave it one node. If you tried to load from a file or put more nodes in, you forgot to give us that code part. I would expect this to do what you said, and operate on the one and only node.
Hello Jonnin. Yes I gave it one node and this is that it confuses me somehow. I gave one node with the intention to pass it as an argument to the method and the method to recursively go from the head node to the end of the list and sum the data in the nodes. However it seems that there is something I am missing in this logic. How can I pass the first node and the method to go on with summing all the next nodes of the list?
class singlylinkedlist1 {
public:
node* head;
singlylinkedlist1();
singlylinkedlist1(node* n);
node* nodeExists(string k);
void appendnode(node* n);
void prependnode(node* n);
void insertnodeafter(string k, node* n);
void deletenode(string k);
void updatenode(string k, int d);
void printlist();
void savetofile1();
}
int main(int argc, char* argv)
{
system("title ..........");
system("color 17");
int option;
static singlylinkedlist1 s;
do {
int choose;
string key1, k1;
int data1;
do {
cout << "\nSelect an operation:" << endl;
cout << "0. Return to initial menu" << endl;
cout << "1. Append node " << endl;
cout << "2. Prepend node" << endl;
cout << "3. Insert node" << endl;
cout << "4. Delete node" << endl;
cout << "5. Update node" << endl;
cout << "6. Print" << endl;
cout << "7. Clscr" << endl;
cout << "8. sum nodes" << endl;
cin >> choose;
node* n1 = new node();
switch (choose) {
case 0:
break;
case 1:
cin >> key1;
cin >> data1;
n1->key = key1;
n1->data = data1;
s.appendnode(n1);
break;
case 2:
cin >> key1;
cin >> data1;
n1->key = key1;
n1->data = data1;
s.prependnode(n1);
break;
case 3:
cin >> k1;
cin >> key1;
cin >> data1;
n1->key = key1;
n1->data = data1;
s.insertnodeafter(k1, n1);
break;
case 4:
cin >> k1;
s.deletenode(k1);
break;
case 5:
cin >> key1;
cin >> data1;
s.updatenode(key1, data1);
break;
case 6:
s.printlist();
break;
case 7:
system("cls");
break;
case 8:
//Here is where I want to apply the node summing
break;
default:
cout << "Wrong number! Enter number 1-8!" << endl;
break;
}
} while (choose != 0);
return 0;
}
@keskiverto: I have set a menu so as to build the list by adding, deleting or updating nodes. When I build the list then with the above summation code, how could pass as argument the head node and the method will recursively sum all of the lists nodes, in the menu's case 8?