-1

I saved some data into the file and when I read all the data at the end of the program right after calling the destructor function I got an access violation error. The data is read successfully but the exception keeps throwing

This is my class:

    class DoList
{
public:

    DoList(const std::string& , const std::string& , const std::string& ,const int& , const int&, const int&, const int&);
    DoList();
    ~DoList();

    bool Input_Task();
    bool Remove_Task();
    void Read_Data();

private:
    int m_Year;
    int m_Month;
    int m_Day;
    int m_ID;

    std::string m_TaskName;
    std::string m_Description;
    std::string m_Status;

};

This is my class.cpp

The function where I input task:


bool DoList::Input_Task() /*Works fine*/
{

    DoList Data;


        std::cout << "Enter Your Task ID: ";
        std::cin >> Data.m_ID;

        std::cin.ignore();

        std::cout << "Enter Your Task Name: ";
        std::getline(std::cin, Data.m_TaskName);

        std::cout << "Enter Description: ";
        std::getline(std::cin, Data.m_Description);

        time_t now = time(NULL);
        tm now_tm = {};
        localtime_s(&now_tm, &now);

        Data.m_Year = 1900 + now_tm.tm_year;
        Data.m_Month = 1 + now_tm.tm_mon;
        Data.m_Day = now_tm.tm_mday;

        std::ofstream file("Tasks_Data.dat", std::ios::app);

        if (!file.is_open())
        {
            std::cout << "file cannot be opened";
            return false;
        }

        file.write((char*)(&Data), sizeof(DoList));

        file.close();
        return true;
}

the function where I read data

    void DoList::Read_Data()
{
    DoList Read;
    std::ifstream file("Tasks_Data.dat");

    if (!file.is_open())
    {
        std::cout << "file cannot be opened";
    }
    
        
        while (file.read((char*)(&Read), sizeof(DoList)))
        std::cout << "Task ID: " << Read.m_ID << ", Task Name: " << Read.m_TaskName << ", Description: " << Read.m_Description << ", Status: " << Read.m_Status << ", Date: " << Read.m_Year << "/"
        << Read.m_Month << "/" << Read.m_Day << std::endl;


    file.close();
}

enter image description here

enter image description here

Sgt Mahdi
  • 29
  • 6
  • 4
    You cannot read classes containing `std::string` using `istream::read`. It is bound to fail. Only *trivially copyable* objects can be read using `istream::read`. – john Aug 30 '23 at 09:05
  • First you should ask how can you write them. Then you read them back in the same way. – john Aug 30 '23 at 09:06
  • The data is printed in the console successfully but the exception throws. If there was a problem in writing data shouldn't it give me unreadable data? – Sgt Mahdi Aug 30 '23 at 09:11
  • `std::string` is generally implemented using short string optimization. It's a feature of such implementations that **short strings** do seem to read and write successfully. But in general `std::string` cannot be read and written using `read` and `write`. Try a longer string (say 30 characters) and see if you can see that in the console. – john Aug 30 '23 at 09:16
  • 3
    The basic problem is that `std::string` contains pointers and it's not meaningful to write a pointer value out to a file and then read that pointer back again. Whatever that pointer value was when you wrote it, it is very unlikely that it is a valid pointer when you read it back again. – john Aug 30 '23 at 09:19
  • @john When I write and read in this way the file will be created but nothing prints on the console – Sgt Mahdi Aug 30 '23 at 09:25
  • 3
    Well as I said, this technique is flawed, you must look for an alternative. What that alternative is depends on what your requirements are. For example do you require binary I/O, or is text I/O OK? – john Aug 30 '23 at 09:50
  • 1
    IYou cannot read and write C++ objects from files, this way. Are you aware that a `sizeof` of a `std::string` is always the same, small value, whether the string is empty or contains the entire contents of Wikipedia? How do you expect to use `sizeof` when reading and writing objects that contain these strings? Do you always expect to read and write the same twenty, or so, bytes, that a typical `std::string` implementation uses, and somehow get all of Wikipedia covered, this way? – Sam Varshavchik Aug 30 '23 at 10:55

1 Answers1

0

The way of writing the string into the file After I got the data from the keyboard I put the data inside the file straightly except Date, I made it string by the to_String()to make it easier to read


bool DoList::Input_Task(){

    std::ofstream file("Tasks_Data.dat", std::ios::app, std::ios::binary);

    if (!file.is_open())
    {
        std::cout << "file cannot be opened";
        return false;
    }

    Task Write;

    std::cout << "Enter Your Task ID: ";
    std::cin >> Write.ID;

    std::cin.ignore();

    std::cout << "Enter Your Task Name: ";
    std::getline(std::cin, Write.TaskName);

    std::cout << "Enter Description: ";
    std::getline(std::cin, Write.Description);

    time_t now = time(NULL);
    tm now_tm = {};
    localtime_s(&now_tm, &now);

    int Year;
    int Month;
    int Day;

    Year = 1900 + now_tm.tm_year;
    Month = 1 + now_tm.tm_mon;
    Day = now_tm.tm_mday;

    Write.Date = std::to_string(Year) + "/" + std::to_string(Month) + "/" + std::to_string(Day);

    file << Write.ID << "\n";
    file << Write.TaskName << "\n";
    file << Write.Description << "\n";
    file << Write.Status << "\n";
    file << Write.Date << "\n";

    file.close();
    return true;}

To Read the file, I insert everything into a string, then I read the string by while loop, to convert my ID (which is the first data we read from the file) to integer I use std::stoi then I started reading everything from file by getline().

void DoList::Read_Data(){

DoList obj;
Task Read;
std::ifstream file("Tasks_Data.dat", std::ios::in, std::ios::binary);


if (!file.is_open())
{
    std::cout << "file cannot be opened";
}
    
std::string line;

while (std::getline(file, line))
{
    Read.ID = std::stoi(line);
    std::getline(file, Read.TaskName);
    std::getline(file, Read.Description);
    std::getline(file, Read.Status);
    std::getline(file, Read.Date);

    std::cout << "Task ID: " << Read.ID;
    std::cout << ", Task Name: " << Read.TaskName;
    std::cout << ", Description: " << Read.Description;
    std::cout << ", Status: " << Read.Status;
    std::cout << ", Date: " << Read.Date << std::endl;
}

file.close();}

The Result: enter image description here

Sgt Mahdi
  • 29
  • 6