0

私が作成しているプログラムのこの部分は、ランダム アクセス バイナリ ファイルに保存されているすべてのレコードを出力することになっています。実行するたびに、すべてのレコードが出力され、アクセス違反の例外がスローされます。

void readFile()
{
    ifstream inFile("hardware.txt", ios::in | ios::binary);

    if(!inFile)
    {
        cerr<<"File could not be opened."<<endl;
        exit(1);
    }

    cout<<left<<setw(10)<<"Account"<<setw(16)
            <<"Name"<<setw(11)<<"Quantity"<<left<<setw(10)<<"Price"<<endl;

    Hardware File;

    inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware));

    while(inFile && !inFile.eof())
    {
        if(File.getAccountNumber() != 0)
            outputLine(cout, File);

        inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware));
    }
}

明確にするために、「ハードウェア」は Hardware.h に格納されているクラスです。

ハードウェア.h

#ifndef HARDWARE_H
#define HARDWARE_H

#include <string>
using std::string;

class Hardware
{
public:
Hardware (int = 0, string = "", int = 0, double = 0);

void setAccountNumber(int);
int getAccountNumber() const;

void setName(string);
string getName() const;

void setAmount(int);
int getAmount() const;

void setPrice(double);
double getPrice() const;
private:
int accountNumber;
string name;
int amount;
double price;
};

#endif

ハードウェア.cpp

#include <string>
using std::string;

#include "hardware.h"

Hardware::Hardware(int accountNumberValue, string nameValue, int amountValue, double priceValue)                            

{
setAccountNumber(accountNumberValue);
setName(nameValue);
setAmount(amountValue);
setPrice(priceValue);
}

void Hardware::setAccountNumber(int accountValue)
{
accountNumber = accountValue;
}

int Hardware::getAccountNumber() const
{
return accountNumber;
}

void Hardware::setName(string nameValue)
{
name = nameValue;
}

string Hardware::getName() const
{
return name;
}

void Hardware::setAmount(int amountValue)
{
amount = amountValue;
}

int Hardware::getAmount() const
{
return amount;
}

void Hardware::setPrice(double priceValue)
{
price = priceValue;
}

double Hardware::getPrice() const
{
return price;
}
4

1 に答える 1

1

Joachim が言ったように、そのようなものを読み取ることはできませんstd::string

値型ではありません。内部的には、テキストを含むメモリ領域へのポインタを保持します。ファイルからバイナリのランダムなブロブを読み取った場合、その文字列ポインターはどこかを指している可能性があります。それを逆参照すると(たとえば、「名前」の値を取得または設定することによって)、アクセス違反やセグメンテーション違反などをスローする可能性があります。

次のような新しいメソッドをいくつか追加します (コンパイルや動作は保証されません!):

void Hardware::Serialise(std::ostream& stream) const
{
  stream << accountName << "\n" << accountNumber << "\n" << accountValue << std::endl;
}
void Hardware::Deserialise(std::istream& stream)
{
  char[1024] buffer;
  stream.readsome(buffer, 1024);
  accountName = buffer;
  buffer >> accountNumber >> accountValue;
}

オブジェクトの内部構造を知ることは、オブジェクトを正しく (逆) シリアル化するための重要な鍵となります。障害条件の処理、レコード間の区切り記号、固定サイズのバッファーの代わりに文字列ストリームを使用して名前を読み取る方法は、読者の課題として残されています。

于 2012-06-12T10:40:46.957 に答える