Reputation: 83
I wrote this code:
#include <fstream>
#include <iostream>
using namespace std;
struct Man
{
int ID;
char Name[20];
};
void Add();
void Update();
void Print();
int main()
{
int n;
cout << "1-add, 2-update, 3-print, 5-exit" << endl;
cin >> n;
while (n != 5)
{
switch (n)
{
case 1: Add(); break;
case 2: Update(); break;
case 3: Print(); break;
}
cout << "1-add, 2-update, 3-print, 5-exit" << endl;
cin >> n;
}
return 0;
}
void Add()
{
fstream file;
file.open("Data.dat", ios::in | ios::out | ios::binary);
if (file.is_open())
{
int id;
Man man;
bool didFound = false;
cout << "ID : ";
cin >> id;
file.read((char*)&man, sizeof(Man));
while (!file.eof() && !didFound)
{
if (man.ID == id)
{
cout << "Already exist" << endl;
didFound = true;
}
file.read((char*)&man, sizeof(Man));
}
if (!didFound)
{
man.ID = id;
cout << "Name: ";
cin >> man.Name;
file.clear();
file.seekp(0, ios::end);
file.write((char*)&man, sizeof(Man));
}
}
}
void Update()
{
fstream file;
file.open("Data.dat", ios::in | ios::out | ios::binary);
if (file.is_open())
{
int id;
Man man;
bool didFound = false;
cout << "ID : ";
cin >> id;
file.read((char*)&man, sizeof(Man));
while (!file.eof() && !didFound)
{
if (man.ID == id)
{
cout << "Name: ";
cin >> man.Name;
file.seekp((int)file.tellg() - sizeof(Man), ios::beg);
file.write((char*)&man, sizeof(Man));
didFound = true;
}
file.read((char*)&man, sizeof(Man));
}
file.close();
if (!didFound)
{
cout << "Cant update none existing man" << endl;
}
}
}
void Print()
{
fstream file;
file.open("Data.dat", ios::in | ios::binary);
if (file.is_open())
{
int id;
Man man;
bool didFound = false;
cout << "ID\tName" << endl;
file.read((char*)&man, sizeof(Man));
while (!file.eof())
{
cout << man.ID << '\t' << man.Name << endl;
file.read((char*)&man, sizeof(Man));
}
file.close();
}
}
But I have a problem in Update function: When I update the last Man in the file, when it reach file.read the file writes the value of the last Man(in the file before the writting) to the end of the file (after the updated man)
I added this after file.write and it seems to solve it:
file.seekg(file.tellp(), ios::beg);
Can somebody explain why?
(yes it can be solved with else)
Upvotes: 4
Views: 1829
Reputation: 137940
Somewhat arbitrarily, you are required to perform seek
in between read
and write
. It's not spelled out in the Standard, but the C++ Standard mentions that C++ fstream
has the same properties as C stdio
streams with respect to the validity of stream operations, and the C standard mentions that a positioning command is required between reading and writing (or vice versa).
Some platforms relax the requirement. GCC after about version 4.5 or 4.6, I personally modified basic_filebuf
to eliminate the byzantine rule.
By the way, file.seekg( 0, ios::cur )
is safer.
Upvotes: 4