buggy
buggy

Reputation: 23

How do I retrieve a linked list from a file (in Turbo C++)

I've been working on my school CS Project for a couple of weeks, and I coded a text based program to manage a supermarket/shop in C++. I ran into some trouble when I was trying to store the database and read it from file storage.

Complete source here

I am aware that TurboC++ is an extremely outdated compiler, but it's a part of my prescribed syllabus, so there's no way out of it. (Thankfully, the next batch out will be learning python)

My main concept was to use a self referencial structure as the node for a singly linked list handled by a class and its functions.

struct product  //Self referencial structure to store the product details
{
    unsigned int code;
    char name[100];
    char category[40];
    unsigned int quantity;
    double price;
    product *next;
};
class list  //Class to handle the linked list of products
{
    private:
        product *head, *tail;
    public:
        list()
        {
            head = NULL;    //By default the list will be empty
            tail = NULL;
        }
        void DelList(); 
        void AppProduct(product *, unsigned int);
        void AddProduct(unsigned int);  
        product* FindProduct(unsigned int); 
        double CalcTotal();
        void ListProducts();    
        void ModProduct(product *);
        void SaveToFile();
        void LoadFromFile();
        product* PointToNewProduct(product);
        product* GetProductFromFile(ifstream &);
        product* GetHead()
        {
            return head;
        }
        void Clear();
};

store and cart are globally declared objects of class list storing the separate linked list.

I chose the linked list format primarily for the program, and decided to add saving to file and loading from file only later when I found out file handling was a compulsory part of the project. This is the code I wrote for the same -

void list::SaveToFile()     //self explanatory
{
    ofstream fout("DATABASE.DAT", ios::trunc);
    product * cur = head;
    product temp;
    while( cur != NULL )
    {
        temp = *cur;
        fout.write( (char *)&temp, sizeof(product) );
        cur = cur->next;
    }
    fout.close();
}
product * list::PointToNewProduct(product temp)     //copy the temp product details into a new pointer and return the pointer
{
    product * cur = new product;
    cur->code = temp.code;
    strcpy(cur->name, temp.name);
    strcpy(cur->category, temp.category);
    cur->price = temp.price;
    cur->quantity = temp.quantity;
    cur->next = NULL;
    return cur;
}

product * list::GetProductFromFile(ifstream& fin)       //retrieve a single product from the given file
{
    if( fin.eof() )
        return NULL;
    product temp;
    fin.read( (char *)&temp, sizeof(product) );
    cout<<temp.name;
    return PointToNewProduct(temp);
}
void list::LoadFromFile()       //Function to load struct from file and rebuild the linked list (only returning one item right now)
This is the code I wrote for the same -     //Update: I thought I fixed it, but its up to two items now, still not all
{
    ifstream fin("DATABASE.DAT", ios::in);      //Initialize the stream
    head = GetProductFromFile(fin);     //initialize head pointer
    product * cur = head;       
    product * nextptr;
    do {
        nextptr = GetProductFromFile(fin);      //get the next product in file
        cur = cur->next = nextptr;      //link product with the previous product
        tail = cur;     //make the current pointer the last one
    } while( !fin.eof() );
    tail->next = NULL;
    fin.close();
}

Now my problem is, that while I am able to write the linked list items to file properly, trying to read it results in it retrieving only 2 nodes, regardless of the number of nodes I have written to file.

A debugging session with my teacher led me to believe that this was because I had not been deleting the older linked list when loading one from file, and this problem of unfreed memory carried forward when writing to file. A destructor I had written to free up memory was never called, since my objects were globally declared, leading me to write the DelList(); function and call it before reading from file. This unfortunately did not solve the problem.

void list::DelList()
        {
            product * cur = head, * temp;
            while(cur != NULL)
            {
                temp = cur;
                cur = cur->next;
                delete temp;
            }
            delete cur;
            delete head;
            delete tail;
            head = NULL;
            tail = NULL;
        }

This is the code I wrote for the same - I also added some test code as a switchcase choice where I simply read from file without linking, and it also does not display the desired output.

case 7:
                    clrscr();
                    ifstream fin("DATABASE.DAT", ios::in);  
                    product temp;
                    fin.seekg(0, ios::beg);
                    while( fin.read( (char *)&temp, sizeof(product) ) )
                    {
                        //fin.read( (char *)&temp, sizeof(product) );
                        cout<<temp.name<<'\t'<<temp.category<<'\n';
                    }
                    getch();
                    break;

What's the problem with my code, and how do I fix it?

Upvotes: 1

Views: 229

Answers (1)

buggy
buggy

Reputation: 23

I managed to solve my problem with a workaround, though I still don't know why my original code didn't work, though seemingly the problem is with reading and writing pointers to and from a file.

What I've done to fix the problem is change product to be a class, inherited from the base class prod, with prod containing the same things that the structure used to with the exception of the pointer to the next. Then I wrote a function Delink() to convert each product in the linked list to a prod and write it to file. Then while reading the file, I convert each prod I read into a product and link it back to construct the linked list again. This seems to have fixed my problem.

Upvotes: 1

Related Questions