繁体   English   中英

如何为 std::map 重载插入运算符 &gt;&gt; in<const int, int> C++?</const>

[英]How to overload insertion operator >> in for std::map<const int, int> C++?

我有一个 class Poly ,它基本上是多项式的 class。 Poly有一个std::map<int, int>类型的私有成员,称为values_ 我设法使左移运算符<<重载,以便能够打印我的多项式。 例如,如果 values_ 有{(2,4), (1,0), (-1,-1)} ,其中第first是指数, second是乘数,输出到 ostream 的字符串应为4x2+0x1-1x-1

现在我试图找到一种方法来重载插入运算符>>以便如果用户输入4x2+0x1-1x-1多项式应存储为{(2,4), (1,0), (-1,-1)}

处理 std::istringstream 以将输入转换为多项式的步骤是什么?

class Poly {
public:
    typedef std::map<int, int> Values;
    typedef Values::const_reverse_iterator const_iterator;
    typedef Values::reverse_iterator iterator;

    const_iterator begin() const { return values_.rbegin(); }
    const_iterator end() const { return values_.rend(); }
    iterator begin() { return values_.rbegin(); }
    iterator end() { return values_.rend(); }
}



    int operator[](int exp) const;
    int& operator[](int exp) { return values_[exp]; }

private:
    Values values_;
};

std::istream& operator>>(std::istream& is, Poly& p);

std::ostream& operator<<(std::ostream& os, const Poly& p);

int Poly::operator[](int exp) const {
    Values::const_iterator it = values_.find(exp);
    return it == values_.end() ? 0 : it->second;
}

进行解析的最有效方法是编写自己的解析器(使用嵌套开关的 state 机器对于这种简单的语法就足够了)。

我看到的最简单的方法是使用regex

以下是关于它的 go 方法:

std::istream& operator>>(std::istream& is, Poly& p) {

   std::regex rx("([+-]?[[:digit:]]+)x([+-]?[[:digit:]]+)");

   std::string line;
   int coef, exponent;

   std::getline(is, line);

   for (std::smatch m; std::regex_search(line, m, rx); line = m.suffix()) {
      coef = std::atoi(m[1].str().c_str());
      exponent = std::atoi(m[2].str().c_str());
      p.values_.insert(p.values_.end(), { exponent, coef });
   }

   return is;
}

std::ostream& operator<<(std::ostream& os, const Poly& p) {

   auto it = p.values_.begin();
   auto end = p.values_.end();
   while (it != end) {
      os << it->first << "x" << it->second;
      it++;
      if (it != end) {
         if (it->first >= 0)
            os << "+";
      }
   }

   return os;
}

请注意,您需要将这些操作员添加为Poly class 的朋友,以便允许他们访问Poly成员。

class Poly
{
public:
   typedef std::map<int, int> Values;
   typedef Values::const_reverse_iterator const_iterator;
   typedef Values::reverse_iterator iterator;

   const_iterator begin() const { return values_.rbegin(); }
   const_iterator end() const { return values_.rend(); }
   iterator begin() { return values_.rbegin(); }
   iterator end() { return values_.rend(); }

   int operator[](int exp) const;
   int& operator[](int exp) { return values_[exp]; }

   private:
      Values values_;

      friend std::istream& operator>>(std::istream& is, Poly& p);
      friend std::ostream& operator<<(std::ostream& os, const Poly& p);
};

一个测试:

int main(int argc, char * argv[]) {

   Poly poly;

   std::stringstream str("4x2+0x1-1x-1");
   str >> poly;
   std::cout << std::endl << poly << std::endl;

   return 0;
}

结果是:

-1x-1+0x1+4x2

键按升序排序(因此无法保留输入顺序):

使用比较 function 比较对键进行排序。

如果您想让您的键按降序排序,您可以提供自定义比较运算符(请参阅此示例)。

如果您不关心密钥的顺序,而不是使用std::map ,您可能想要使用std::unordered_map unordered_map实现为hash 表,而std::map通常实现为红黑树 Hash 表具有更好的访问复杂度

如果您想保留输入顺序,您将需要使用其他数据结构,例如向量或列表(例如: std::vector<std::pair<int, int> > ),但是您将不得不重写您的访问operator[]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM