0

I am learning c++ and have a trouble in file handling. I am writing a code as a homework where i have to write objects into a file and then read those objects as array from the file at once. Here is my code:

#include <iostream>
#include <fstream>

using namespace std;

class Records{
    char* name;
    int roll;
public:
    Records()
    {
        name = new char[20];
    }
    void setData()
    {
        cout<<"Enter name: "<<endl;
        cin>>name;
        cout<<"Enter roll"<<endl;
        cin>>roll;
    }
    char* getname()
    {
        return name;
    }
    int getRoll()
    {
        return roll;
    }
    void operator = (Records& no)
    {
        name = no.name;
        roll = no.roll;
    }
};

int main()
{
    int i =0 ;
    Records rec;
    rec.setData();
    Records::increase();
    ofstream fout;
    fout.open("file.txt", ios::app);
    fout.write((char*)&rec, sizeof(rec));
    fout.close();

    Records* results = new Records[20];
    Records rec1;
    ifstream fin;
    fin.open("file.txt", ios::in);
    while(!fin.eof())
    {
        fin.read((char*)&rec1, sizeof(rec1));
        results[i] = rec1;
        i++;
    }
    fin.close();
    cout<<results[0].getRoll();
    return 0;
}

So basically, I made a Records class and store its object in a file. That works fine but I faced problem while taking data from file. It is not showing anything or sometimes showing garbage value. Anyone have better idea please hep me. Thanks in advance!

3
  • 1
    Do you have to use raw pointers? Why not use std::string? Your class is very unsafe as-is because of the char* name - and it leaks memory because you don't delete[] the pointer. Read rule of 3/5/0. Also read: Why is iostream::eof() inside a loop condition (i.e. while (!stream.eof())) considered wrong? Commented Nov 26, 2020 at 16:08
  • 2
    You can't store pointers in a file and use them later. You need some kind of serialization. Commented Nov 26, 2020 at 16:12
  • 1
    what you are doing is rather low level, you don't have to go that low. Using the ofstreams operator<< is much simpler if you just want to write a string and a number per line into a text file Commented Nov 26, 2020 at 16:14

2 Answers 2

1

First, you have to open file in binary mode for read and write.

 std::ofstream fou("out_filename",std::ofstream::binary);
 std::ifstream fin("in_filename", std::ifstream::binary);

Secondly, you assign operator=() is problematical. It assigns two records using the same address. Therefore in the reading process, all 20 elements in result[i] were all sharing the address of rec1::name. You have to correct the operator=() by copying contents of name.

This is not good.

void operator = (Records& no)
{
    name = no.name;
    roll = no.roll;
}

Rewrite as follows:

Edit: since your objects are all initially assigned with its memory. The new allocation is not necessary.

Records& Records::operator=(const Records& no)
{
   // this->name = new char [20]; 
    std::copy_n(no.name, 20, this->name); // include <algorithm>
    roll = no.roll;
    return *this; // return current object for another =.
}

Finally, add a destructor

Records::~Records() {
delete [] this->name; }

Good luck!

Sign up to request clarification or add additional context in comments.

Comments

0

After fixed some other errors, I post this final version for you reference. Note that this project cannot use dynamic allocation for the field "name". Using dynamic allocation, the 20-byte of "name" is not counted as the size of class Records, and the pointer itself is not transferable. It causes read/write error in the field "name".

#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;

class Records{
    char name[20];
    int roll;
public:
    Records()
    {
      //  name = new char[20];
    }
    void setData()
    {
        cout<<"Enter name: "<<endl;
        cin>>name;
        cout<<"Enter roll"<<endl;
        cin>>roll;
    }
    const char* getname() const
    {
        return name;
    }
    int getRoll() const
    {
        return roll;
    }
    Records& operator = (const Records& no)
    {
        std::copy_n(no.name, 20, this->name);
        roll = no.roll;
        return *this;
    }
};
int main()
{
    int i =0, c ;
    std::string a;
    Records rec;
    ofstream fout;
    fout.open("file.txt", std::ofstream::binary);
    c = 0;
    while (1)
    {
       std::cout << "Input record [" << c << "] ? (y/n) ";
       std::cin >> a;
       if (a[0]=='y' || a[0]=='Y')
        {
          rec.setData();
          fout.write((char*)&rec, sizeof(rec));
          ++c;
        }
        else break;
    }
    fout.close();
// output 
    Records* results = new Records[20];
    Records rec1;
    ifstream fin;
    fin.open("file.txt", std::ifstream::binary);
    while(!fin.eof())
    {
       fin.read((char*)&rec1, sizeof(rec1));
       results[i] = rec1;
       i++;
    }
   fin.close();
   // eidt to print all records
   for (int j=0; j<(i-1); j++)
    {  std::cout << "record # = " << j << std::endl;
       std::cout << "   name = " << results[j].name;
       std::cout << "   roll = " << results[j].roll << std::endl;
    }

   return 0;
}

A test run

$ ./a.exe
Input record [0] ? (y/n) y
Enter name:
aaaa
Enter roll
1234
Input record [1] ? (y/n) y
Enter name:
bbbb
Enter roll
2345
Input record [2] ? (y/n) y
Enter name:
cccc
Enter roll
3456
Input record [3] ? (y/n) n
1234

9 Comments

Thank you sir! But i have another question, how to display all the records at once as we don't how big our array is?
@SachinBhusal During the process of reading, the variable i is the number of records fetched. But due to the while(end of file condition), there is one extra record with data duplicate of the last one. Please look up my edited part for a demo.
@SachinBhusal Yes. After a run, you can go to the directory and change the file.txt to another name, e.g. filesave.txt. Then rewrite your program, remark the first part (input section), and directly go to the second part: open filesave.txt and read from it.
When i read from file then it is showing in a binary form like it was saved in a file. I mean it is not showing in proper "english" readable text. Why?
@SachinBhusal Sure. You had saved it in binary form, and have to open it also in binary form. You cannot open this kind of file in notepag, or read it as a text file. >>> You may open the file.txt append mode, which allow you to continue write new records into the end of the file.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.