1

基本问题:

如果我正在记录/修改数据,我是否应该通过索引硬编码索引访问文件的元素,即targetFile.getElement(5);通过硬编码的标识符(内部翻译成索引),即target.getElementWithID("Desired Element"),或使用一些中间值DESIRED_ELEMENT = 5; ... target.getElement(DESIRED_ELEMENT)等。

编辑:或者使用enum??


背景:

我的程序 (c++) 将数据存储在许多不同的 'dataFile' 中。我还在另一个文件中保留了所有数据文件的列表——一个“listFile” ——它还存储了每个文件的一些属性(见下文,但即它的名称是什么,它有多少行信息有等)。有一个管理数据文件和列表文件的对象,称之为'fileKeeper'

listFile 的条目类似于:

filename , contents name , number of lines , some more numbers ...

我绝对有可能从此列表中添加/删除字段 --- 但总的来说,它们将保持静态。

现在,我有一个常量字符串数组,它保存每个条目中每个元素的标识,例如:

const string fileKeeper::idKeys[] = { "FileName" , "Contents" , "NumLines" ... };
const int fileKeeper::idKeysNum = 6;   // 6 - for example

我正在尝试以“良好”的程序形式管理这些东西。因此,当我想检索文件中的行数时(例如),而不是使用仅检索“3”元素的方法......相反,我执行以下操作:

string desiredID = "NumLines";
int desiredIndex = indexForID(desiredID);
string desiredElement = elementForIndex(desiredIndex);

函数indexForID()遍历的条目,idKeys直到找到,desiredID然后返回它对应的索引。并且elementForIndex(index)实际上进入listFile以检索以逗号分隔的字符串的第 index 个元素。


问题:

这看起来仍然很丑陋/形式不佳。有没有办法我应该这样做?如果不是,通常有哪些一般方法可以做到这一点?

谢谢!

4

4 回答 4

1

我喜欢使用字符串作为键的方式。您可以使用 将字符串映射到数字std::map<string, int>。然后你可以做

std::map<string, int> columns;
columns["FileName"] = 0;    
columns["Contents"] = 1;
columns["NumLines"] = 2;

然后,您可以参考columns["Contents"],例如,获取列 ID。最好是通过一个函数来完成,如果你拼错了一个键,它会通知你。像这样的一些代码:

std::map<string, int>::iterator it = columns.find(key);
if (it == columns.end()) { // key not in columns
    // report error here
于 2012-12-16T08:54:28.250 回答
1

既不使用数据库,也至少使用 csv。Sqlite 是一个轻量级、无服务器的数据库,并且几乎可以使用任何语言进行绑定。它专为这种需要存储大量数据但又不想安装和配置数据库服务器的场景而设计。您可能还想创建一个结构/类来保存数据,也许在某种 ORM 的帮助下。

如果您使用 csv 并且希望能够重新排列列顺序,将列名保存为文件的第一个条目,大多数 csv 库应该能够使用第一列作为列名。

于 2012-12-16T11:01:12.843 回答
0

首先创建一个FileProperty类,listFile将是该类的对象列表,而您的“键”将是该类的成员变量。

于 2012-12-16T08:31:07.723 回答
0

我的解决方案是使用 std::map 和枚举的组合:

class FileKeeper {
    public:
        enum ID_KEY = { FileName , Contents , "Num_Lines };
        string getIDKey(ID_KEY idk);

    private:
        static map<int,string> ID_Key = { { FileName, "Filename" }, { Contents, "Contents" }, { Num_Lines, "Num Lines" } };

}

string FileKeeper::getIDKey(ID_KEY idk) {
    if( idk > 0 && idk < ID_Key.size() ) { return ID_Key[idk]; }
    else { return ""; }
}

这样,我可以使用枚举轻松访问索引并轻松地遍历键(以正确的顺序 --- 这是map<string,int>不会做的),并且仍然使用映射检索从索引到字符串的映射。使用一种get()方法可以防止向地图添加元素,并保持实际的map私有属性使我无法使用整数懒惰地访问它(即使它在技术上是 int-index 类型)。

我不需要在代码中的任何位置使用已识别的实际字符串访问元素,即 get___("Num Lines"); --- 这有点丑陋,似乎是失礼

于 2012-12-19T22:26:16.727 回答