我有一个如下所述的课程:
class InputReader
{
public:
typedef void (*handler)(std::string, int);
static void errorHandler(std::string error, int severity); //Supplies a default error handler
static void warningHandler(std::string error, int severity); //Supplies a default warning handler
handler errorH;
handler warningH;
InputReader(std::string pwd = "", handler eHandler = errorHandler, handler wHandler = warningHandler);
bool readFile(std::string filename);
std::vector<first> mesh;
//other irrelevant objects that need to be read into
};
first
是一个结构:
struct first
{
std::string filename;
double scale;
};
在Mooing Duck的帮助下,我有:
std::istream& operator>>(std::istream& file, first& obj)
{
std::string symbol;
while(file >> symbol)
{
if (symbol[0] == '#')
{
std::getline(file, symbol);
}
else if (symbol == FIRSTTAGEND)
{
break;
}
else if (symbol == FILEPATH)
{
if (!(file >> '=' >> obj.filename))
std::cerr << symbol << " is incorrectly formatted"; //This needs to use errorH
}
else if (symbol == SCALE)
{
if (! (file >> '=' >> obj.scale) )
std::cerr << symbol << " is incorrectly formatted"; //This needs to use errorH
}
else
{ //not a member: failure
std::cerr << symbol << " is not a member of first";
file.setstate(file.rdstate() | std::ios::badbit);
break;
}
}
return file;
}
std::istream& operator>>(std::istream& file, InputReader& obj)
{
std::string symbol;
while(file >> symbol)
{
if (symbol[0] == '#')
{
std::getline(file, symbol);
}
else if (symbol == FIRSTTAGBEG)
{
first t;
if (file >> t)
obj.mesh.push_back(t);
}
else
{
obj.errorH(symbol + " is not a member of the input reader.", 1);
file.setstate(file.rdstate() | std::ios::badbit);
}
}
return file;
}
bool InputReader::readFile(std::string filename)
{
std::ifstream infile;
infile.open(filename.c_str());
infile >> *this;
return true;
}
在构造InputReader对象时设置 errorH
。它可以由类的用户提供,否则,它使用我提供的默认值。唯一的问题是,当errorH
被读入时,我无法访问first
。我该如何解决这个问题?
问题限制:不允许使用外部库。不允许使用C ++ 11 / C ++ OX。
答案 0 :(得分:4)
你自然没有多少选择:
>>
运算符并创建一个执行相同但接受三个参数的函数 - 输入流,first
对象和输入阅读器对象。>>
和first
元组作为第二个参数(即一对指针)的运算符InputReader
。例如:std::istream& operator>>(std::istream& file, std::pair<first *, InputReader *> & obj)
。只要你有很好的想象力,你就可以无限期地扩展这个列表。
希望它有所帮助。
的更新:强> 的
这是一个简单的例子:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
struct first {
std::string filename;
double scale;
};
class InputReader {
public:
typedef void (*handler)(const std::string &, int);
InputReader(const std::string & pwd = std::string(),
handler eHandler = errorHandler,
handler wHandler = warningHandler);
bool readFile(const std::string & filename);
static void errorHandler(const std::string & error, int severity);
static void warningHandler(const std::string & error, int severity);
handler errorH;
handler warningH;
first firstobj;
std::vector<first> mesh;
};
std::istream & operator >> (std::istream & file,
std::pair<first, InputReader *> & obj)
{
std::string symbol;
while (file >> symbol) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "FIRSTTAGEND") {
break;
} else if (symbol == "FILEPATH") {
if (!(file >> obj.first.filename))
obj.second->errorHandler(symbol + " is incorrectly formatted",
1);
} else if (symbol == "SCALE") {
if (!(file >> obj.first.scale))
obj.second->errorHandler(symbol + " is incorrectly formatted",
1);
} else { //not a member: failure
std::cerr << symbol << " is not a member of first";
file.setstate(file.rdstate() | std::ios::badbit);
break;
}
}
return file;
}
std::istream & operator>>(std::istream & file, InputReader & obj)
{
std::string symbol;
while (file >> symbol) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "FIRSTTAGBEG") {
std::pair<first, InputReader *> t(first(), &obj);
if (file >> t)
obj.mesh.push_back(t.first);
} else {
obj.errorH(symbol + " is not a member of the input reader.", 1);
file.setstate(file.rdstate() | std::ios::badbit);
}
}
return file;
}
bool InputReader::readFile(const std::string & filename)
{
std::ifstream infile;
infile.open(filename.c_str());
infile >> *this;
return true;
}
答案 1 :(得分:2)
std::pair<first, InputReader *>
,因为那不是我想要阅读的类型。我会稍微改变你目前的设计。将流读取函数移动到单独的函数,该函数接受流引用,以及您需要的任何其他变量,并让流操作符调用该成员。当您希望操作员可以访问可选的附加参数时,通常会使用此想法
std::istream& loadObjectFromFile(std::istream& file,
first& obj,
handler errorH=InputReader::errorHandler,
handler warningH=InputReader::warningHandler); //new
std::istream& operator>>(std::istream& file, first& obj)
{return loadObjectFromFile(file, obj);}
然后实现阅读器功能,是直接复制粘贴,除了现在你还有错误处理程序
std::istream& loadObjectFromFile(std::istream& file, first& obj
handler errorH, handler warningH) {
...
else if (symbol == FILEPATH)
{
if (!(file >> '=' >> obj.filename))
errorH(symbol + " is incorrectly formatted.", 1); //new
}
else if (symbol == SCALE)
{
if (! (file >> '=' >> obj.scale) )
errorH(symbol + " is incorrectly formatted.", 1); //new
}
else
{ //not a member: failure
errorH(symbol + " is not a member of first.", 1); //new
file.setstate(file.rdstate() | std::ios::badbit);
break;
}
}
return file;
}
然后,InputReader的相应更改是istream函数
std::istream& operator>>(std::istream& file, InputReader& obj)
{
...
else if (symbol == FIRSTTAGBEG)
{
first t;
if (loadObjectFromFile(file, obj))
mesh.push_back(t);
}
...
}
答案 2 :(得分:1)
将std::istream& operator>>(std::istream& file, first& obj)
替换为std::istream &InputReader::readObj(std::istream &file, first &obj)
。
另外,为了保持一致性,请将std::istream& operator>>(std::istream& file, InputReader& obj)
替换为std::istream &InputReader::readFileStream(std::istream& file)
。
然后在readFileStream
中,你可以写if (readObj(file, t))
,在readObj
你可以写
errorH("oops", -1)
。