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

errorHInputReaderオブジェクトの構築時に設定されます。クラスのユーザーが提供できます。それ以外の場合は、私が提供するデフォルトのものを使用します。唯一の問題は、読み込まれているerrorHときにアクセスできないことです。firstどうすればこれを解決できますか?

問題の制約:外部ライブラリは許可されていません。C ++ 11 / C++OXは許可されていません。

4

3 に答える 3

4

当然、いくつかのオプションがあります。

  1. 演算子を使用せず、同じことを行うが、入力ストリーム、オブジェクト、および入力リーダーオブジェクト>>の3つの引数を受け入れる関数を作成します。first
  2. およびのタプルを2番目の引数(つまり、ポインターのペア)として>>受け入れる演算子を定義します。例:。firstInputReaderstd::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 に答える