-1

The following is my function in C++ for modifying records of bank a/c holders (A/C no and Name) in a file.

class AccountHolder
{
    int accno; //Account No
    char name[50]; //AC Holder name
public:
    void getRecord_KB()
    {
        cout<<"\nEnter account no:";
        cin>>accno;
        cout<<"Enter name of the new account holder:";
        cin>>name;
    }

    void showRecord_VDU()
    {
        cout<<"\nAccount no:"<<accno;
        cout<<"\nA/C Holder's Name:"<<name;
    }

    int retAccno()
    {
        return accno;
    }
};
void writeRecord_File() //Initial and subsequent writings are done through this function
{
    ofstream outFile;
    outFile.open("C:/PN/account.dat", ios::binary | ios::app);

    AccountHolder ah;
    ah.getRecord_KB();

    outFile.write(reinterpret_cast<char*>(&ah), sizeof(ah));

    outFile.close();
}
void modify_record(int n) 
{
    fstream file;
    file.open("C:/PN/account.dat",ios::in | ios::out);
    AccountHolder ah;

    file.clear();
    file.seekp(0,ios::beg);
    int object_start = file.tellp();

    while(file.read(reinterpret_cast<char*>(&ah), sizeof(ah)))
    {
        if(ah.retAccno()==n)
        {
            cout<<"\nEnter the new details of a/c holder:";
            ah.getRecord_KB();
            file.seekp(object_start);// <-- go back to position where object start.
            file.write(reinterpret_cast<char*>(&ah), sizeof(ah)); 
        }
        object_start = file.tellp(); // <-- again save position where object start.
    }
    file.close();
}

The function modify_record(int) when called, asks for the a/c no and modifies the record with new inputs. But it also does an unwanted modification of the a/c no of the next record and the program is terminating. What am I doing wrong? I googled this type of cases and found the following two codes:

int pos = -1 * sizeof(ah);
file.seekp(pos, ios::cur);

and

long pos = file.tellp();
file.seekp (pos-sizeof(ah));

But the same problem is occurring when implemented. The rest of the program is working properly. Any suggestion? Thanks in advance.

PS Nayak
  • 409
  • 8
  • 20
  • `cin>>name` - buffer overflow. `"C://PN"` should be `"C:/PN"`. – melpomene Nov 07 '17 at 09:02
  • `file.open("C:/PN/account.dat",ios::in | ios::out);` doesn't open the file in binary mode. – Retired Ninja Nov 08 '17 at 03:27
  • Yes, but I have resolved it. Please have a look in my comment below. – PS Nayak Nov 08 '17 at 03:39
  • Your code is incomplete; in particular, it seems to be missing a `main()` function and at least one `#include`. Please [edit] your code so it's a [mcve] of your problem, then we can try to reproduce and solve it. You should also read [ask]. – Toby Speight Nov 23 '17 at 11:02

1 Answers1

1

I think the answer to your question indeed lies with the cursor position.

You finish reading an object file. And straight away try to write back. You have to change the position of the cursor back to the place you started reading.

You should save the position where you start reading an object. And return to it when you want to write it back after you edit it.

Like this:

long object_start = file.tellp();  // <-- save position where object start.
while(file.read((char*)&ah, sizeof(ah)))
{
    if(ah.retAccno() == n)
    {
        cout<<"\nEnter the new details of a/c holder:";
        ah.getRecord_KB();
        file.seekp(object_start)// <-- go back to position where object start.
        file.write((char*)&ah, sizeof(ah)); 
    }
    object_start = file.tellp(); // <-- again save position where object start.
}

Because its a file stream. tellp(),tellg(),seekp() & seekg() are all referring to the same position pointer. But its good thing to know them both, look them up :).

Lastly, this kind of object to file writing in this case is possible only because of the static size of your class. It wont work if it had any dynamically allocated memory objects. Have a look at this for more information: Is it possible to serialize and deserialize a class in C++?

Please notice as well that (char*) casting is c style, a more appropriate C++ way would be to use reinterpret_cast<char*>(&ah); you can look here for more information: When to use reinterpret_cast?

Cheers.

  • The problem persists after implementing the code you mentioned. Before the while loop, I modified the code like this: file.clear(); file.seekp(0,ios::beg); int object_start = file.tellp(); – PS Nayak Nov 07 '17 at 16:57
  • Can you add the code that initially creates the file? The one you later try to modify. – NoamStolero Nov 07 '17 at 18:46
  • 1
    Dear Master Sprinller, I got it right. I googled and got to know that pressing the Return key is also considered as a character that is getting appended. This was touching the initial data of the next object. So I reduced the size of writing by 1 like this: `file.write(reinterpret_cast(&ah), sizeof(ah));` to `file.write(reinterpret_cast(&ah), sizeof(ah)-1);` Now the program is working without any issue. Thank you for your time. – PS Nayak Nov 08 '17 at 03:30