3

我有一堂课,如下所述:

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;
}

errorH在构造 InputReader 对象时设置。它可以由该类的用户提供,否则,它使用我提供的默认值。errorH唯一的问题是当first被读入时我无法访问。我该如何解决这个问题?

问题限制:不允许使用外部库。不允许使用 C++11/C++OX。

4

3 回答 3

4

你自然有几个选择:

  1. 不要使用>>运算符并创建一个功能相同但接受三个参数的函数 - 输入流、first对象和输入读取器对象。
  2. 定义>>接受firstInputReader作为第二个参数(即一对指针)的元组的运算符。例如: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;
}
于 2012-07-18T20:32:36.083 回答
2

Vlad 提出了一个有趣的想法,但我不喜欢使用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);
    } 
    ...
}
于 2012-07-19T15:49:20.770 回答
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)

于 2012-07-18T21:03:07.143 回答