Как перегрузить оператор вставки >> в for std :: mapC ++? - PullRequest
0 голосов
/ 04 октября 2019

У меня есть класс Poly, который в основном является классом для полиномов. Poly имеет закрытый член типа std::map<int, int> с именем 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;
}

1 Ответ

0 голосов
/ 04 октября 2019

Самый эффективный способ анализа заключается в написании собственного синтаксического анализатора (для этой простой грамматики может быть достаточно конечного автомата, использующего вложенные ключи).

Самый простой способ , который я вижу, это использовать 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[].

...