Самый эффективный способ анализа заключается в написании собственного синтаксического анализатора (для этой простой грамматики может быть достаточно конечного автомата, использующего вложенные ключи).
Самый простой способ , который я вижу, это использовать 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
Клавиши сортируются в порядке возрастания (поэтому порядок ввода не может быть сохранен):
Клавиши сортируются с использованием функции сравнения Compare.
Если вы хотите отсортировать ключи в порядке убывания, вы можете предоставить пользовательский оператор сравнения (см. этот пример ).
Если вы неНе заботясь о порядке расположения ваших ключей, вместо использования std::map
вы можете использовать std :: unordered_map . unordered_map
реализован в виде хеш-таблицы , тогда как std::map
обычно реализуется в виде красно-черного дерева . Хеш-таблица имеет лучшую сложность доступа .
Если вы хотите сохранить порядок ввода, вы захотите использовать другую структуру данных, например, вектор или список (например: std::vector<std::pair<int, int> >
), но тогда выпридется переписать твой доступ operator[]
.