i have this problem to write and read data, here's what im trying to make :
Write a program that uses a structure to store the following inventory data in a file:
-Item Description
-Quantity on Hand
-Wholesale Cost
-Retail Cost
-Date Added to Inventory

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.

and this is the code i made =

#include <iostream>
#include <fstream>
#include <cctype>

using namespace std;

struct Info
{
    string desc;
    int quantity;
    double saleCost;
    double retCost;
    string added;
};

void getData(Info&);
void displayData(Info);
void changeData(Info&, fstream&);

int main()
{
    Info data;
    fstream file("asd.txt", ios::in | ios::out | ios::app | ios::binary);
    char ch;
    long recNum;
    long byte;


    do
    {
        cout<<"do you want to : \n";
        cout<<"1. add new record\n";
        cout<<"2. display record\n";
        cout<<"3. change record\n";
        cout<<"pick 1, 2, or 3\n";
        cin.get(ch);

        switch(ch)
        {
            case '1' :  getData(data);
                        file.write(reinterpret_cast<char*>(&data), sizeof(data));
                        file.close();
                        break;

            case '2' :  cout<<"which record u want to see = ";
                        cin>>recNum;
                        recNum--;
                        file.seekg(recNum * sizeof(data), ios::beg);
                        file.read(reinterpret_cast<char*>(&data), sizeof(data));
                        displayData(data);
                        break;

            case '3' :  cout<<"which record u want to change = ";
                        cin>>recNum;
                        recNum -=1;
                        file.seekp(recNum * sizeof(data), ios::beg);
                        changeData(data, file);
                        break;

        }
        cout<<"\ndo u want to do anything else (Y/N)? ";
        cin.get(ch);
}while(toupper(ch)!= 'N');
}

void getData(Info &asd)
{
    cin.ignore();
    cout<<"enter description = ";
    getline(cin, asd.desc);
    cout<<"\nenter quantity = ";
    cin>>asd.quantity;
    cout<<"enter wholesale cost = ";
    cin>>asd.saleCost;
    cout<<"enter retail cost = ";
    cin>>asd.retCost;

    asd.added = "u had added " + asd.desc;
    cout<<endl;
}

void displayData(Info d)
{
    cout<<"item desciption = "<<d.desc<<endl;
    cout<<"item quantity = "<<d.quantity<<endl;
    cout<<"item wholesale cost = "<<d.saleCost<<endl;
    cout<<"item retail cost = "<<d.retCost<<endl;
    cout<<"last thing u did on this record = "<<d.added<<endl;
    d.added = "u had displayed "+ d.desc;
}

void changeData(Info &DATA, fstream &FILE)
{
    cin.ignore();
    cout<<"enter description = ";
    getline(cin, DATA.desc);
    cout<<"\nenter quantity = ";
    cin>>DATA.quantity;
    cout<<"enter wholesale cost = ";
    cin>>DATA.saleCost;
    cout<<"enter retail cost = ";
    cin>>DATA.retCost;

    DATA.added = "u had edited " + DATA.desc;
    cout<<endl;

    FILE.write(reinterpret_cast<char*>(&DATA), sizeof(DATA));
}

erm the problems with it are :
A. if i add record example
item description = A
quantity = 5
whole sale cost = 20.5
retail cost = 10.5

then when i pick to add new record again, example
item description = B
quantity = 10
wholesale cost = 30.5
retail cost = 20.0

after that i try to view the record, but if i pick record 1, it just display the :
item description = B
quantity = 10
wholesale cost = 30.5
retail cost = 20.0

so its like the item"B" replace the item "A" which means i cant see the item's A record

B. when i let the program just to add record, then i close the program and then open the program again just to view the record, it shows unknown data like some random number and strings etc in the screen.

anyone can help?

note : sorry ofr the bad english

Edited 4 Years Ago by Sendy Hipo

edited :
i just found the problem is because im using string class object inside a struct and i tried to change struct into a pointer to char by using reinterprect_cast
also i forgot to use ios::app

if anyone have tips, please pm me or post here ;D

Here's an example of serializing non-POD types:

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <ctime>

using namespace std;

struct Info
{
    string description;
    int quantity;
    double wholesale_cost;
    double retail_cost;
    string date_added;

    Info() {}

    Info(string const& s) { deserialize(s); }

    string serialize() const
    {
        ostringstream oss;

        oss << description << '|' << quantity << '|' << wholesale_cost << '|' << retail_cost << '|' << date_added;

        return oss.str();
    }

    void deserialize(string const& s)
    {
        istringstream iss(s);

        // No error checking for brevity
        getline(iss, description, '|');
        iss >> quantity; iss.get();
        iss >> wholesale_cost; iss.get();
        iss >> retail_cost; iss.get();
        getline(iss, date_added);
    }
};

bool user_menu(string& option)
{
    cout << "1. Add Inventory\n2. View Inventory\n3. Load Inventory\n4. Save Inventory\n5. Quit\n> ";

    return getline(cin, option) && option.front() >= '1' && option.front() <= '4';
}

string now()
{
    // No error checking for brevity
    time_t t = time(0);
    tm* info = gmtime(&t);
    char buf[1024];

    strftime(buf, sizeof buf, "%Y-%m-%d", info);

    return string(buf);
}

int main()
{
    vector<Info> inventory;
    string option;

    while (user_menu(option))
    {
        switch (option.front())
        {
        case '1':
            {
                Info item;

                cout << "Description: "; getline(cin, item.description);
                cout << "Quantity: "; cin >> item.quantity;
                cout << "Wholesale Cost: "; cin >> item.wholesale_cost;
                cout << "Retail Cost: "; cin >> item.retail_cost;

                cin.get(); // Trim the newline

                item.date_added = now();

                inventory.push_back(item);

                break;
            }
        case '2':
            for (vector<Info>::size_type i = 0; i < inventory.size(); ++i)
            {
                cout << inventory[i].serialize() << '\n';
            }

            break;
        case '3':
            {
                ifstream in("test.txt");
                string line;

                if (in)
                {
                    while (getline(in, line))
                    {
                        // No error checking for brevity
                        inventory.push_back(Info(line));
                    }
                }

                break;
            }
        case '4':
            {
                ofstream out("test.txt");

                if (out)
                {
                    for (vector<Info>::size_type i = 0; i < inventory.size(); ++i)
                    {
                        out << inventory[i].serialize() << '\n';
                    }
                }

                break;
            }
        }
    }
}

Take careful note of how I'm not using read(), write(), or seekg() to process the file. read() and write() are simply broken because your objects use std::string to store data, and std::string handles its data dynamically rather than statically. This means you can't just xcopy bytes into the object and expect it to work.

Likewise, seekg() cannot be used easily when the length of the records are not fixed. You use the size of the object, which is guaranteed to be wrong due to the separate storage of std::string described previously.

The solution for correctness and maximum portability is to use a text file rather than a binary file, and manually serialize your objects (or use a library that does it for you, but manual is simple enough IMO).

I also didn't keep trying to read and write the file, instead choosing to process the items in memory using a vector, then either saving or loading them in bulk. This is much more efficient, especially if you're going to do any kind of non-linear processing on the items (such as finding and modifying one of them).

okay thx, even though i dont understand some of the codes due to lack of knowledges and also im still a beginner, but i get the main idea of serializing the struct.
thx alot :D

This question has already been answered. Start a new discussion instead.