我正在编写一个命令行实用程序,用于文本处理。 我需要一个帮助函数(或两个函数),其功能如下:
这适用于
最终,在进行了许多调整和在StackOverflow上搜索后,这是我能想到的最好解决方法:
- 如果文件名为“-”,则返回标准输入/输出;
- 否则,创建并打开一个文件,检查错误,并返回它。
FILE *open_for_read(const char *filename)
{
if (strcmp(filename, "-") == 0)
{
return stdin;
}
else
{
auto fp = fopen(filename, "r");
if (fp == NULL)
{
throw runtime_error(filename);
}
return fp;
}
}
它能够正常工作,并且稍后(如果不忘记的话)fclose(stdin)
也是安全的,但是这样一来我将失去对流方法的访问,例如std::getline
。
因此,我想到了用智能指针与流进行现代化的C++处理。起初,我尝试使用
unique_ptr<istream> open_for_read(const string& filename);
这适用于
ifstream
,但不适用于cin
,因为您无法删除cin
。 因此,我必须为cin
提供自定义删除程序(什么也不做)。 但是突然间,编译失败了,因为显然,当提供自定义删除程序时,unique_ptr
变成了不同的类型。最终,在进行了许多调整和在StackOverflow上搜索后,这是我能想到的最好解决方法:
unique_ptr<istream, void (*)(istream *)> open_for_read(const string &filename)
{
if (filename == "-")
{
return {static_cast<istream *>(&cin), [](istream *) {}};
}
else
{
unique_ptr<istream, void (*)(istream *)> pifs{new ifstream(filename), [](istream *is)
{
delete static_cast<ifstream *>(is);
}};
if (!pifs->good())
{
throw runtime_error(filename);
}
return pifs;
}
}
它是类型安全和内存安全的(至少我是这么认为;如果我错了,请纠正我),但这看起来有点丑陋且模板化,最重要的是,只是让它编译起来就令人头痛。
我是不是做错了什么并且错过了什么?肯定有更好的方法。
delete static_cast<ifstream *>(is);
可以简写为delete is;
- 因为istream
的析构函数是虚函数,所以它会做正确的事情。 - Ted Lyngmo