0

假设您有一个包含以下内容的文件:

  • 文件包含:a) 第一个空记录号,b) 每条记录的大小,以及 c) 文件可以容纳的最大记录数。
  • 记录包含:a) 指示记录是空闲还是占用的字节,b) 固定数量的字段。

当我想读取随机记录时,我使用这个函数:

int FixedLengthRecordFile :: read (int numRec, FixedLengthFieldsRecord & rec) 

问题是,为了让这个函数工作,我必须FixedLengthFieldsRecord事先创建一个,这意味着指定这个记录所具有的字段数......这不是我想要的。我希望文件处理程序足够“智能”以识别记录有多少个字段,并FixedLengthFieldsRecord在读取它时动态创建一个。

我怎样才能做到这一点?该函数必须返回一个,int因为我将它用作退出代码(错误/成功)。

4

2 回答 2

2

潜在地,您可以定义 FixedLengthFieldsRecord 类,以便该类本身强制执行正确的记录长度,但允许每个记录中的任意数量的字段。实现此目的的一种可能的好方法是让 CONSTRUCTOR 从文件中读取下一条记录。

该类(减去一些必要的错误检查,您可以添加)可以以与以下类似的方式编写(该类假定您在创建此类的对象之前阅读了文件的第一行):

using namespace std;
class FixedLengthFieldsRecord
{

    public:

        FixedLengthFieldsRecord(int const recordLength, istream & s); // Set the length of the record in the constructor
        bool IsEmpty() const;
        int FieldCount() const; // variable number of fields allowed; but LENGTH of record is enforced (see below)

        bool IsValidRecord(); // Does the record contain the correct number of bytes?
        string GetField(int const index) const; // This could throw an exception if the record is not valid

    protected:
        // Could have sophisticated functions here to replace fields, remove fields, reorder fields, etc.

    // This section contains the actual implementation.
    private:
        vector<string> fields; // The vector contains a VARIABLE number of fields
        bool is_empty;
        bool is_valid;
        int const record_length; // This contains the LENGTH of the record; it is set in the constructor and cannot be changed

    // The following variable and function store (and access) ALL the records
    static vector<FixedLengthFieldsRecord> records;
    static read(int numRec, FixedLengthFieldsRecord & rec);

}

FixedLengthFieldsRecord::FixedLengthFieldsRecord(int const recordLength_, istream & s)
    : record_length(recordLength)
{
    // pseudocode provided here
    // this functionality could be factored into other functions that are called by the constructor

    is_valid = true;

    is_empty = ReadFirstByte(s); // ReadFirstByte (not shown) reads first byte of current line and returns true if it indicates an empty record

    if (!is_empty)
    {
        string field;
        int currentRecordLength = 0;
        while (ReadNextField(s, field)) // ReadNextField() returns true if another field was read from the line (i.e., not end-of-line
        {
            currentRecordLength+= field.length();
        }
        if (currentRecordLength != record_length)
        {
            is_valid = false;
        }
        if (currentRecordLength > record_length)
        {
            break;
        }
        if (is_valid)
        {
            fields.push_back(field);
        }
    }
    if (is_valid)
    {
        records.push_back(*this); // not efficient, nor thread safe - deep copy occurs here
    }
}

bool FixedLengthFieldsRecord::IsEmpty()
{
    return is_empty();
}

bool FixedLengthFieldsRecord::IsValidRecord()
{
    return is_valid;
}

string FixedLengthFieldsRecord::GetField(int const index)
{
    if (!is_valid)
    {
        // throw an exception, or return an empty string
    }
    if (index < 0 || index >= fields.size())
    {
        // throw an exception, or return an empty string
    }
    return fields[index];
}

FixedLengthFieldsRecord::read(int numRec, FixedLengthFieldsRecord & rec)
{
    if (numRec < 0 || numRec >= records.size())
    {
        // throw an exception, or just return
    }
    rec = records[numRec];
}
于 2013-04-03T04:19:01.813 回答
0

FixedLengthRecordFile应该打开文件(或者更好的是,在构造函数中取一个)std::istream,读取标题,然后FixedLengthRecordFile::read(...)成员函数可以使用std::istream::seekgstd::istream::read获取数据。

现在,到你的实际问题。为什么你希望FixedLengthRecordFile::read函数返回一段int时间,它通过引用获取记录?签名不会像

FixedLengthFieldsRecord FixedLengthRecordFile::read(size_t numRec, int& foo);

更容易?

如果您坚持您的原始签名,请让FixedLengthFieldsRecord默认构造函数将对象初始化为无效状态(例如,添加一个bool isValid设置为 的标志false),并添加一个setData(size_t length, const char* data)成员函数,然后该函数可以调用该成员FixedLengthRecordFile::read函数。

于 2013-04-03T06:07:48.907 回答