Я отвечу для случая работы с простым форматом ввода:
12345 + 6789
1) вы не модифицируете входную строку, поэтому, если имеем дело со стандартом от c++17, то лучше в функцию принимать явно
string_view
или
const string_view&
, если ниже, то принимать надо
const string&
.
2) если уж принимаем что-то строкоподобное, то смело пользуемся функцией-членом
::find
, которая есть и в строке и в вью. С её помощью можно найти сразу позицию арифметического символа. Для простого случая, даже не нужен обход от найденной позиции к началу строки и к концу строки для проверок
std::isspace
, является ли символ пробелом, поскольку мы можем сразу слать в atoi для левого числа например
string_view::substr(0, opPos - 1)
. И, получится, только один if/switch, который будет сопоставлять символ операции, например, с указателем на функцию.
...
int plus(int left, int right) { return left + right; }
using CalculatorFunction = int (*)(int, int);
...
CalculatorFunction operation;
...
switch (opChar):
case '+': operation = plus;
...
3) настоятельно рекомендую после этого реализовать нормальный простой калькулятор, а потом третьим заходом добавить поддержку скобок, hex oct бинарную и с мантиссой нотации записи чисел, операцию степени и корня.
Нормальный - имеется ввиду, что в калькулятор входит строка, которая является корректным арифметическим выражением. В этом случае нужно ещё иметь дело с разделителями. По-хорошему, решение состоит из нескольких этапов:
- на первом логическом этапе функция парсит выражение и сохраняет в контексте или возвращает контейнер с токенами, (или прерывает весь процесс из-за плохой строки). В вашем варианте, задача однопоточная, поэтому можно воспользоваться функцией
strtok, чтобы удобно извлечь строковое значение токена по входной строке от разделителя до разделителя.
- как вариант, токены могут быть структурами с членом string_view на строковые представления и членом на тип токена (число, операция).
- на втором логическом этапе мы считываем последовательность токенов и делаем какое-то действие:
- считали число - ожидаем за ним токен операции
- если оказался не токен операции - бросаем исключение о некорректном арифметическом выражении, иначе - подготавливаем аргументы и кормим функцию
evaluate<T>( Token::kOperation op, T arg1, T arg2)
, для случая, если операции нужно два аргумента, то первый уже считан, а второй будет в последовательности токенов за операцией. Результат evalaute записываем в переменную результата, которая, кстати говоря, типа double.
- продолжаем движение по последовательности токенов до конца, контейнером может быть std::list, когда добрались до конца, возвращаем результат.