c++ - 如何从函数中读取文件中的数据
问题描述
我想让我的代码更高效,特别是从文本文件中读取数据。这是它现在的样子的快照:
values V(name);
V.population = read_value(find_line_number(name, find_in_map(pop, mapping)));
V.net_growth = read_value(find_line_number(name, find_in_map(ngr, mapping)));
... // and so on
基本上,该read_value
函数创建一个ifstream
对象,打开文件,读取一行数据,然后关闭文件连接。这种情况发生很多次。我想要做的是打开文件一次,将需要的每一行读入结构,然后关闭文件连接。
这是带有参数的创建values
结构函数:
static values create_struct(std::string name, std::map<std::string, int> mapping) {
values V(name);
V.population = read_value(find_line_number(name, find_in_map(pop, mapping)), file);
V.net_growth = read_value(find_line_number(name, find_in_map(ngr, mapping)), file);
// more values here
return V;
}
调用的函数create_struct
如下所示:
void initialize_data(string name) {
// read the appropriate data from file into a struct
value_container = Utility::create_struct(name, this->mapping);
}
我正在考虑在函数中定义 ifstream 对象initialize_data
。鉴于我的程序所显示的内容,这是创建文件对象、打开连接、读取值然后关闭连接的最佳位置吗?另外,我是否需要将 ifstream 对象传递到create_values
结构中,如果需要,按值、引用或指针传递?
解决方案
简短的回答是首先创建您的 ifstream 对象并将其作为参考传递给您的解析器。请记住在您离开函数之前或开始阅读时将流返回到开头。
RAII 要做的事情是创建一个包装器对象,当它超出范围时会自动执行此操作。
class ifStreamRef{
ifStreamRef(std::ifstream& _in) : mStream(_in){}
~ifStreamRef(){mStream.seekg(0);}
std::ifstream& mStream;
}
然后在输入将读取 fstream 的方法时创建一个包装器实例。
void read_value(std::ifstream& input, ...){
ifStreamRef autoRewind(input);
}
或者,由于 Ctor 可以进行转换...
void read_value(ifStreamRef streamRef, ...) {
streamRef.mStream.getLine(...);
}
std::ifstream 本身遵循 RAII,因此当您的流超出范围时,它将为您关闭()流。
长答案是您应该阅读依赖注入。不要在可以共享的对象/函数内部创建依赖项。有很多关于依赖注入和依赖倒置的视频和文档。
基本上,构造您的对象所依赖的对象并将它们作为参数传递。
注入现在依赖于您传入的对象的接口。因此,如果您将 ifStreamRef 类更改为充当接口:
class ifStreamRef{
ifStreamRef(std::ifstream& _in) : mStream(_in){}
~ifStreamRef(){mStream.seekg(0);}
std::string getLine(){
// todo : mStream.getLine() + return "" on error;
}
bool eof() { return mStream.eof(); }
std::ifstream& mStream;
}
然后稍后您可以更改将引用vector<string>&
而不是ifstream
...的内部实现
class ifStreamRef{
ifStreamRef(std::vector<string>& _in) : mStream(_in), mCursor(0){}
~ifStreamRef(){}
std::string getLine(){
// todo : mStream[mCursor++] + return "" on error;
}
bool eof() { return mCursor >= mStream.size(); }
std::vector<string>& mStream;
size_t mCursor;
}
我把一些事情简单化了。
推荐阅读
- mysql - 我可以在一个实例上为每个架构设置多个从属主机吗?
- python - 如何根据日期范围从字典列表中过滤出子字典
- r - 找不到功能,但是包肯定是安装加载的
- r - 减去并找到值或体积的差异
- html - iframe 后面的下拉菜单?
- j - 从时间设置RNG种子
- asp.net-core - 使用 Azure DevOps 将 Asp.Net Core 应用程序部署到 Azure 时未找到包
- python-3.x - 在 Window 7 上运行“从 skimage 导入数据”代码时发现“ModuleNotFoundError”
- dc.js - 为什么在折线图的上方和下方都呈现黑色区域?
- c - Xcode 中的 Git 忽略