我写了这段代码:
#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();
}
}
但我在Update函数中遇到问题: 当我更新文件中的最后一个Man时,当它到达file.read时,文件会将最后一个Man的值(在写入之前的文件中)写入文件的末尾(在更新后的man之后)
我在file.write之后添加了它,它似乎解决了它:
file.seekg(file.tellp(), ios::beg);
有人可以解释原因吗?
(是的,可以用其他方法解决)
答案 0 :(得分:4)
有些随意,您需要在seek
和read
之间执行write
。它没有在标准中详细说明,但C ++标准提到C ++ fstream
具有与C stdio
流相同的属性,与流操作的有效性有关,C标准提到了定位命令在阅读和写作之间需要(反之亦然)。
有些平台放宽了要求。 GCC在4.5或4.6之后,我亲自修改basic_filebuf
以消除拜占庭规则。
顺便说一下,file.seekg( 0, ios::cur )
更安全。