我有一个类Poly
,它基本上是用于多项式的类。 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;
}
答案 0 :(得分:0)
进行解析的最有效的方法是编写自己的解析器(使用嵌套开关的状态机足以满足这种简单的语法要求)。
我看到的最简单的方式是使用regex。
这是您的处理方法:
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
类的朋友,才能允许他们访问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
键以升序排序(因此输入顺序无法保留):
使用比较功能“比较”对键进行排序。
如果要按降序对键进行排序,则可以提供自定义比较运算符(请参见this example)。
如果您不关心密钥的顺序,则可以使用std::unordered_map而不是使用std::map
。 unordered_map
被实现为hash table,而std::map
通常被实现为red-black tree。哈希表has better access complexity。
如果您要保留输入顺序,则将要使用其他数据结构,例如矢量或列表(例如:std::vector<std::pair<int, int> >
),但随后您将不得不重写访问权限operator[]
。