бобёр

Калькулятор

Мы с вами будем делать КАЛЬКУЛЯТОР! В том числе парсер выражения.

Обратная польская запись

На вики описано хорошо.

Ваша программа должна уметь вычислять выражения в обратной польской записи и поддерживать:

  • бинарные операции + - * /
  • целые числа, в том числе отрицательные.

Пример использования:

int main() {
  int res = calc("4 1 + 5 *");
  assert(res == (4+1)*5);
}

Программируемый польский калькулятор

Усложним программу: добавим поддержку создания своих операторов произвольной арности, добавим поддержку float типов.

Проектируйте калькулятор, как библиотеку, чтобы пользователь мог дописать свой оператор и встроить в наш калькулятор, не меняя код самой библиотеки.

Главные нововведения:

  • парсинг float чисел
  • создание операций произвольной арности, например, sum должна просуммировать вообще всё что в стеке лежит.

Нельзя использовать std::atoi-like функций. Сами встройте парсер числа.

int main() {
  ModuleOp mod_op;
  Calculator calc;
  calc.register("%", &mod_op);
  SumOp sum_op;
  calc.register("sum", &sum_op);

  {
  auto s = "6 8 + 3 %";
  auto tokens = Tokenize(s);
  float res = calc.eval(tokens);
  assert(res == (6+8) % 3);
  }

  {
    auto tokens = Tokenize("1 2 3 4 5 6 sum");
    float res = calc.eval(tokens);
    assert(res == 1 + 2 + 3 + 4 + 5 + 6);
  }
}

Нормальный калькулятор

Сделайте так, чтобы ваша библиотека поддерживала парсинг записей в инфиксной нотации: примение алгоритм сортировочной станции.

int main() {
  ModuleOp mod_op;
  Calculator calc;
  calc.register("%", &mod_op);
  SumOp sum_op;
  calc.register("sum", &sum_op);

  string s = "(1 + 4) / 5 + 9 % 2";
  auto infix_tokens = Tokenize(s);

  auto polish_tokens = ShuntingYard(infix_tokens);

  float res = calc.eval(polish_tokens);
}

Подсказки

Применяйте ООП.

Можете посмотреть мой старый стрим на твитче про Польский калькулятор.