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やや恣意的に、 との間で実行する必要がreadありwriteます。標準では詳しく説明されていませんが、C++ 標準では、ストリーム操作の有効性に関して C++fstreamは C ストリームと同じプロパティを持っているとstdio言及されており、C 標準では、読み取りと書き込みの間で位置決めコマンドが必要である (またはその逆) と言及されています。 )。

一部のプラットフォームでは要件が緩和されています。バージョン 4.5 または 4.6 以降の GCC ではbasic_filebuf、ビザンチン ルールを排除するために個人的に修正を加えました。

ちなみに、file.seekg( 0, ios::cur )より安全です。

于 2013-05-21T20:18:37.197 に答える