C++ ';好';按条目维护/更新/访问文件的编程表单
基本问题: 如果我正在编写/修改数据,我是否应该按索引硬编码索引访问文件的元素,即C++ ';好';按条目维护/更新/访问文件的编程表单,c++,c,database,record,C++,C,Database,Record,基本问题: 如果我正在编写/修改数据,我是否应该按索引硬编码索引访问文件的元素,即targetFile.getElement(5);通过硬编码标识符(内部翻译为索引),即target.getElementWithID(“所需元素”),或通过一些中间所需元素=5。。。target.getElement(所需的元素)等 编辑:或使用枚举的东西 背景: 我的程序(c++)将数据存储在许多不同的数据文件中。我还将所有数据文件的列表保存在另一个文件中——'listFile'——该文件还存储了每个文件的一
targetFile.getElement(5)
;通过硬编码标识符(内部翻译为索引),即target.getElementWithID(“所需元素”)
,或通过一些中间所需元素=5。。。target.getElement(所需的元素)
等
编辑:或使用枚举的东西
背景:
我的程序(c++)将数据存储在许多不同的数据文件中。我还将所有数据文件的列表保存在另一个文件中——'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
string desiredID = "NumLines";
int desiredIndex = indexForID(desiredID);
string desiredElement = elementForIndex(desiredIndex);
我完全有可能从这个列表中添加/删除字段,但一般来说,它们将保持静态
现在,我有一个常量字符串数组,它保存每个条目中每个元素的标识,类似于:
filename , contents name , number of lines , some more numbers ...
const string fileKeeper::idKeys[] = { "FileName" , "Contents" , "NumLines" ... };
const int fileKeeper::idKeysNum = 6; // 6 - for example
string desiredID = "NumLines";
int desiredIndex = indexForID(desiredID);
string desiredElement = elementForIndex(desiredIndex);
我正试图以“良好”的程序形式管理这些东西。因此,当我想要检索文件中的行数时(例如),而不是使用只检索“3”元素的方法。。。相反,我会这样做:
filename , contents name , number of lines , some more numbers ...
const string fileKeeper::idKeys[] = { "FileName" , "Contents" , "NumLines" ... };
const int fileKeeper::idKeysNum = 6; // 6 - for example
string desiredID = "NumLines";
int desiredIndex = indexForID(desiredID);
string desiredElement = elementForIndex(desiredIndex);
其中函数indexForID()
遍历idKeys
的条目,直到找到desiredID
,然后返回它对应的索引。而elementForIndex(index)
实际上进入了列表文件,以检索逗号分隔字符串的第个索引元素
问题:
这看起来还是相当丑陋/糟糕的形式。有没有一种我应该这样做的方法?如果没有,通常是以什么方式进行的
谢谢 首先创建一个FileProperty
类,listFile
将是该类对象的列表,您的“键”将是该类的成员变量。我喜欢使用字符串作为键的方式。您可以使用std::map
将字符串映射到数字。然后你就可以做了
std::map<string, int> columns;
columns["FileName"] = 0;
columns["Contents"] = 1;
columns["NumLines"] = 2;
既不使用数据库,也不使用csv。Sqlite是一个轻量级、无服务器的数据库,绑定几乎可以在任何语言中使用。它正是为这种情况而设计的,在这种情况下,您需要存储大量数据,但不希望安装和配置数据库服务器。您可能还希望创建一个结构/类来保存数据,可能需要某种ORM的帮助
如果您使用的是csv,并且希望能够重新排列列顺序,将列名保存为文件的第一个条目,则大多数csv库应该能够使用第一列作为列名。我的解决方案是使用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 ""; }
}
类文件保管器{
公众:
enum ID_KEY={FileName,Contents,“Num_line};
字符串getIDKey(ID\u KEY idk);
私人:
静态映射ID_Key={{FileName,“FileName”},{Contents,“Contents”},{Num_行,“Num行”};
}
字符串FileKeeper::getIDKey(ID\u KEY idk){
if(idk>0&&idk
这样,我可以使用enum轻松地访问索引和迭代键(按照正确的顺序,map
不会这样做),并且仍然可以使用map检索从索引到字符串的映射
方法防止向映射中添加元素,并使实际的映射保持私有状态,防止我使用整数懒洋洋地访问它(即使它在技术上是int索引类型)
无需在代码中的任何位置使用实际的字符串idenitified访问元素,即get__u(“Num行”);---这有点难看,似乎有点失礼。您需要组织的似乎是列表而不是表格数据。也就是说,您希望通过键访问完整的字符串,而不是像数据库中那样访问表中的单独字段。因此,您必须根据数据访问的类型选择最适合的结构。如果需要,它可以是std::list您可以经常插入/删除,或者在大部分时间需要访问特定密钥时,它可以是字符串的std::vector,或者如果您想访问单独的字段,它可以是CodeChords man建议的std::map。最后,按照Karthik T的建议在类中组织它。这与使用枚举(即枚举密钥)有什么不同吗{FileName,Contents,NumLines}
——在这种情况下,它们已经映射到0,1,2
?