4

我写了这段代码:

#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();
    }
}

但是我在更新函数中有一个问题:当我更新文件中的最后一个 Man 时,当它到达 file.read 时,文件将最后一个 Man 的值(在写入之前的文件中)写入文件末尾(之后更新的人)

我在 file.write 之后添加了这个,它似乎解决了它:

file.seekg(file.tellp(), ios::beg);

有人可以解释为什么吗?

(是的,可以用其他方法解决)

4

1 回答 1

4

有点武断,你需要在和seek之间执行。标准中没有详细说明,但 C++ 标准提到 C++在流操作的有效性方面与 C 流具有相同的属性,并且 C 标准提到在读取和写入之间需要一个定位命令(反之亦然)。readwritefstreamstdio

一些平台放宽了要求。GCC 大约在 4.5 或 4.6 版本之后,我亲自修改basic_filebuf以消除拜占庭规则。

顺便说一句,file.seekg( 0, ios::cur )更安全。

于 2013-05-21T20:18:37.197 回答