-
Notifications
You must be signed in to change notification settings - Fork 18
C++ practice calculator #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
nZver
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Правки в рамках ёфикации.
| @@ -0,0 +1,167 @@ | |||
| ## Подход к выполнению практики | |||
|
|
|||
| Вычисление алгебраического выражения состоит из трех этапов: токенизация, перевод в постфиксную форму, вычисление выражения в постфиксной форме. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... трёх ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Привет. Ты оставил 10 однотипных комментариев. Вместо этого лучше оставить один и написать "здесь и везде", "и далее" или что-то такое.
Ёфикацию мы уже обсуждали. Сама я этим заниматься не буду. Максимум - мержить реквесты. Два уже замержено)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ок, мне больше нужно было в механизме review разобраться, а тут такой удобный случай подвернулся. :)
| struct Operator | ||
| { | ||
| std::uint8_t priority = 0; | ||
| std::function<double(double, double)> func; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Для расширяемости решения лучше, чтобы func() получала стек значений (std::vector<>&). С таким подходом можно добавлять функции с количеством значений отличных от 1.
Ни разу не настаиваю.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Предлагаю не усложнять понимание кода и оставить как есть.
| std::string value; | ||
| }; | ||
|
|
||
| void save_token(Token & token, std::vector<Token> & tokens) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Функция save_token() выглядит ненужной. Если всё правильно, то токен с TokenType::Invalid может легально встретиться только первым в списке токенов. В остальных случая появление токена такого типа свидетельствует об ошибке. Сейчас save_token() корректно сработает только на первом токене, в остальных случаях просто скрывает ошибку. (Если я не ошибаюсь конечно.)
Предлагаю TokenType::Invalid переименовать в TokenType::Empty. В дальнейшем игнорировать такой токен, если он первый. Во всех остальных случаях сигнализировать об ошибке.
| token = Token{}; | ||
| } | ||
|
|
||
| void start_accumulating_number(char symbol, Token & token, std::vector<Token> & tokens) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Глядя на функции start_accumulating_number(), accumulate_number(), accumulate_operator() и accumulate_parenthesis() напрашивается класс Tokenizer. ИМХО, такой подход правильнее.
Не настаиваю, т.к. всё равно делать эти функции из-за мапы, но уже с ссылкой на Tokenizer. А про лямбды мы не рассказывали. На твоё усмотрение.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Переписала все на токенайзер + свич-кейс.
| token.value = std::string{symbol}; | ||
| } | ||
|
|
||
| void accumulate_number(char symbol, Token & token, std::vector<Token> & tokens) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIR, в C++23 появилась возможность обозначать неиспользуемые переменные префиксом _. Если _ не работает, то убрать либо закомментировать tokens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Да. Переделала.
| token.value = std::string{symbol}; | ||
| } | ||
|
|
||
| struct Transition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не очень хорошо, что можно создать неинициализированный объект типа Transition. Предлагаю сделать конструктор Transition(State state, TransitionAction act), где:
using TransitionAction = std::function<void(char, Token &, std::vector<Token> &)>;Тогда конструктор по умолчанию будет недоступен.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Эта штука больше не нужна. Удалила.
| std::function<void(char, Token &, std::vector<Token> &)> action; | ||
| }; | ||
|
|
||
| using Row = std::map<State, Transition>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Row — неудачное и неговорящее навание. Может лучше TransitionMap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Этой штуки больше нет.
|
|
||
| SymbolType get_symbol_type(char c) | ||
| { | ||
| if (std::isdigit(c)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А разве не так нужно делать:
std::isdigit(static_cast<unsigned char>(c))?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не, все в порядке:
int isdigit( int ch );| const SymbolType symbol_type = get_symbol_type(sybmol); | ||
|
|
||
| if (symbol_type == SymbolType::Other) | ||
| throw std::invalid_argument("Invalid token in expression"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Мне не очень нравится, что определение типа символа (токена по факту) и соответствующая ошибка происходит вне машины состояний. Это должна быть её часть. Допустим у нас было бы более сложное задание, допускались бы шестнадцатиричные значения и функции. В этом случае что означал бы символ A? Это шестнадцатиричные число или начало имени функции (например ABS)? Обрати внимание, что понять тип токена в случае ABS можно только на символе S.
Не хватает шага определения типа токена. Это первый шаг при начале разбора на токены и он же нужен после завершения текущего токена:
def_type => number => def_type => operator => def_type =>parenthesis => def_type => ...
При этом текущий токен может завершаться при встрече неподходящего символа двумя способами:
- переходом на шаг определения типа токена, например:
9.71v(v- невалидный символ, но токен число ничего об этом не знает, аdef_typeзнает); - ошибкой, например:
9.71.(.- валидный символ, но может быть только раз).
При добавлении шага определения типа токена токенам не нужно знать друг о друге, что хорошо. Для текущих вводных шаг определения типа описан функцией get_symbol_type().
P.S. И где классы черт подери! :) Пока какой-то Си-стиль получается ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Переделано на класс Tokenizer.
6b2d054 to
6691191
Compare
No description provided.