Pratap Biswakarma
Pratap Biswakarma

Reputation: 117

what is my program not reading from file after i close it and then run it again for reading from the file?

I have written a program that stores date and time in a custom data type and then stores it in a binary file. Everything works perfectly if I compile and run the program in DevC++ 5.11 (shortcut F11). My program is able to store data in the file and then read it as long as I don't close the program. However, if I close the program and then open the file again for reading, it only shows the first day that I entered and doesn't show the rest of it. Please tell me what I need to do to fix this.

Here is my DevC++ 5.11 code

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

char s=' ';

struct date{
    int day;
    string month;
    int year;
};

struct time{
    int hr;
    int min;
};

class entry{
    private:
        int sno;
        date d;
        time t;

    public:

        void initsno(){
            sno=0;
        }

        void getdate(){
            cout << "\nEnter the date : ";
            cout << "\nDay : ";
            cin >> d.day;
            cout << "Month : ";
            cin >> d.month;
            cout << "Yeay :";
            cin >> d.year;      
        }

        void gettime(){
            cout << "\n\nEnter time : ";
            cout << "\nHours :";
            cin >> t.hr;
            cout << "Minutes :";
            cin >> t.min;
        }   

        void showdate(){
            cout << "\n\nDate is : ";
            cout << d.day << s << d.month << s << d.year << endl << endl;
        }

        void showtime(){
            cout << "\n\nTime is :";
            cout << t.hr << ":" << t.min << endl << endl;
        }           
};

int main(){

    //declaring variables
    char c='y', l;
    string filename;
    entry e, e2;
    ofstream filew;
    ifstream filer; 

    cout << "******Time sheet calculator******" << endl << endl;

    //getting file name begins
    cout << "Enter the name of file you want to create : ";
    cin >> filename;
    cout << "\nThe file name is : " << filename << endl;
    //getting file name over

    e.initsno();    //initializing the entry serial number

    //creating and opening file
    filew.open(filename.c_str(), ios::binary | ios::out | ios::app);
    //file association operation successful

    if (!filew)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue write operation\n";

    //getting date
    e.getdate();

    cout << "\nDo you want to write to file? :";
    cin >> l;

    if (l == 'y')
    {
        //Entering time
        while (c == 'y')
        {
            e.gettime();
            filew.write((char*)&e, sizeof(e));
            cout << "\nFile write operation successful.\n";
            cout << "\nDo you wish to continue? :";
            cin >> c;
        }
    }
    else
        cout << "\nContinue reading...\n";

    //closing file
    filew.close();

    cout << "\nReading file...\n";

    //opening file for reading
    filer.open(filename.c_str(), ios::binary | ios::in);

    if (!filer)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue read operation\n";

    while (filer.read((char*)&e2, sizeof(e2)))
    {
        cout << "\nDisplaying file data...\n";
        e2.showdate();
        e2.showtime();
    }

    cout << "\n\nFile IO successful...";

    filer.close();

    return 0;
}

Upvotes: 0

Views: 116

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596041

Your date struct contains a string member. You can't write()/read() a string as-is, since the character data is (usually1) stored elsewhere in memory.

1: not taking Short String Optimization into account, in which case small amounts of character data are actually stored directly in the string object.

Use a fixed char[] array instead of a string, eg:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct date{
    int day;
    char month[10];
    int year;
};

struct time{
    int hr;
    int min;
};

class entry{
    private:
        int sno;
        date d;
        time t;

    public:

        void initsno(){
            sno=0;
        }

        void getdate(){
            cout << "\nEnter the date : ";
            cout << "\nDay : ";
            cin >> d.day;
            cout << "Month : ";
            cin.get(d.month, sizeof(d.month));
            cout << "Year :";
            cin >> d.year;      
        }

        void gettime(){
            cout << "\n\nEnter time : ";
            cout << "\nHours :";
            cin >> t.hr;
            cout << "Minutes :";
            cin >> t.min;
        }   

        void showdate(){
            cout << "\n\nDate is : ";
            cout << d.day << s << d.month << s << d.year << endl << endl;
        }

        void showtime(){
            cout << "\n\nTime is :";
            cout << t.hr << ":" << t.min << endl << endl;
        }           
};

int main(){

    //declaring variables
    char c;
    string filename;
    entry e, e2;
    ofstream filew;
    ifstream filer; 

    cout << "******Time sheet calculator******" << endl << endl;

    //getting file name begins
    cout << "Enter the name of file you want to create : ";
    cin >> filename;
    cout << "\nThe file name is : " << filename << endl;
    //getting file name over

    e.initsno();    //initializing the entry serial number

    //creating and opening file
    filew.open(filename.c_str(), ios::binary | ios::app);
    //file association operation successful

    if (!filew)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue write operation\n";

    //getting date
    e.getdate();

    cout << "\nDo you want to write to file? :";
    cin >> c;

    if (c == 'y')
    {
        //Entering time
        do
        {
            e.gettime();
            filew.write((char*)&e, sizeof(e));
            cout << "\nFile write operation successful.\n";
            cout << "\nDo you wish to continue? :";
            cin >> c;
        }
        while (c == 'y');
    }
    else
        cout << "\nContinue reading...\n";

    //closing file
    filew.close();

    cout << "\nReading file...\n";

    //opening file for reading
    filer.open(filename.c_str(), ios::binary);

    if (!filer)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue read operation\n";

    while (filer.read((char*)&e2, sizeof(e2)))
    {
        cout << "\nDisplaying file data...\n";
        e2.showdate();
        e2.showtime();
    }

    cout << "\n\nFile IO successful...";

    filer.close();

    return 0;
}

Otherwise, you need to serialize the string (ie, save its size() value followed by its actual character data), eg:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct date{
    int day;
    string month;
    int year;

    void read(istream &is) {
        is.read(reinterpret_cast<char*>(&day), sizeof(day));
        size_t size;
        if (is.read(reinterpret_cast<char*>(&size), sizeof(size)))
        {
            month.resize(size);
            is.read(&month[0], size);
        }
        is.read(reinterpret_cast<char*>(&year), sizeof(year));
    }

    void write(ostream &os) const {
        os.write(reinterpret_cast<const char*>(&day), sizeof(day));
        size_t size = month.size();
        os.write(reinterpret_cast<const char*>(&size), sizeof(size));
        os.write(month.c_str(), size);
        os.write(reinterpret_cast<const char*>(&year), sizeof(year));
    }
};

istream& operator>>(istream &is, date &d)
{
    d.read(is);
    return is;
}

ostream& operator<<(ostream &os, const date &d)
{
    d.write(os);
    return os;
}

struct time{
    int hr;
    int min;

    void read(istream &is)
    {
        is.read(reinterpret_cast<char*>(&hr), sizeof(hr));
        is.read(reinterpret_cast<char*>(&min), sizeof(min));
    }

    void write(ostream &os) const
    {
        os.write(reinterpret_cast<const char*>(&hr), sizeof(hr));
        os.write(reinterpret_cast<const char*>(&min), sizeof(min));
    }
};

istream& operator>>(istream &is, time &t)
{
    t.read(is);
    return is;
}

ostream& operator<<(ostream &os, const time &t)
{
    t.write(os);
    return os;
}

class entry{
    private:
        int sno;
        date d;
        time t;

    public:

        void initsno(){
            sno=0;
        }

        void getdate(){
            cout << "\nEnter the date : ";
            cout << "\nDay : ";
            cin >> d.day;
            cout << "Month : ";
            cin >> d.month;
            cout << "Yeay :";
            cin >> d.year;      
        }

        void gettime(){
            cout << "\n\nEnter time : ";
            cout << "\nHours :";
            cin >> t.hr;
            cout << "Minutes :";
            cin >> t.min;
        }   

        void showdate(){
            cout << "\n\nDate is : ";
            cout << d.day << s << d.month << s << d.year << endl << endl;
        }

        void showtime(){
            cout << "\n\nTime is :";
            cout << t.hr << ":" << t.min << endl << endl;
        }

        void read(istream &is) {
            is.read(reinterpret_cast<char*>(&sno), sizeof(sno));
            d.read(is);
            t.read(is);
        }

        void write(ostream &os) const {
            os.write(reinterpret_cast<const char*>(&sno), sizeof(sno));
            d.write(os);
            t.write(os);
        }
};

istream& operator>>(istream &is, entry &e)
{
    e.read(is);
    return is;
}

ostream& operator<<(ostream &os, const entry &e)
{
    e.write(os);
    return os;
}

int main(){

    //declaring variables
    char c;
    string filename;
    entry e, e2;
    ofstream filew;
    ifstream filer; 

    cout << "******Time sheet calculator******" << endl << endl;

    //getting file name begins
    cout << "Enter the name of file you want to create : ";
    cin >> filename;
    cout << "\nThe file name is : " << filename << endl;
    //getting file name over

    e.initsno();    //initializing the entry serial number

    //creating and opening file
    filew.open(filename.c_str(), ios::binary | ios::app);
    //file association operation successful

    if (!filew)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue write operation\n";

    //getting date
    e.getdate();

    cout << "\nDo you want to write to file? :";
    cin >> c;

    if (c == 'y')
    {
        //Entering time
        do
        {
            e.gettime();
            filew << e;
            cout << "\nFile write operation successful.\n";
            cout << "\nDo you wish to continue? :";
            cin >> c;
        }
        while (c == 'y');
    }
    else
        cout << "\nContinue reading...\n";

    //closing file
    filew.close();

    cout << "\nReading file...\n";

    //opening file for reading
    filer.open(filename.c_str(), ios::binary);

    if (!filer)
        cout << "\nCan't open file" << endl;
    else
        cout << "continue read operation\n";

    while (filer >> e2)
    {
        cout << "\nDisplaying file data...\n";
        e2.showdate();
        e2.showtime();
    }

    cout << "\n\nFile IO successful...";

    filer.close();

    return 0;
}

Upvotes: 1

Related Questions