Сложение, вычитание и скобки

Усложним предыдущий пример. Пусть теперь помимо чисел и знаков "плюс" и "минус", в выражении допустимо использование круглых скобок любой вложенности.

Во-первых, для корректной работы программы в этом случае потребуется модифицировать функцию get_next_lexem(), чтобы она "научилась" распознавать лексемы типа LT_OPEN и LT_CLOSE

Во-вторых, потребуется изменить функцию evaluate_expression(). При этом будем воспользуемся следующим наблюдением: часть выражения, заключенная в скобки, тоже является выражением, поэтому можно использовать функцию evaluate_expression() рекурсивно.

На рисунке разными цветами показаны области, для вычисления которых будут использоваться отдельные вызовы функции evaluate_expression().

Отдельные выражения

Изменения коснутся функций calc_plus() и calc_plus().

void calc_plus() { // в эту функцию мы попадем, если текущая лексема - это LT_PLUS get_next_lexem(); // возьмем следующую лексему // если следующая за плюсом лексема является числом, то ничего не изменилось: if (current_lexem_type == LT_NUMBER) { current_result = current_result + current_lexem_value; } else { // но в этом примере слагаемое может быть не только числом, // но и целым выражением в скобках. // предположим, что исходное выражение корректно current_result = current_result + evaluate_expression(); // вычислили выражение до закрывающейся скобки get_next_lexem(); // за выражением будет следовать закрывающаяся скобка, ее нужно пропустить } }

Функция calc_minus() изменяется аналогично.

Также должна немного измениться основная логика функции evaluate_expression()

while ((current_lexem_type != LT_END) && (current_lexem_type != LT_CLOSE)) { if (current_lexem_type == LT_PLUS) { calc_plus(); } else { calc_minus(); } get_next_lexem(); }

Теперь эту функцию могут вызвать для разбора основного выражения (признаком конца которого является LT_END, или для разбора выражения в скобках, признаком конца которого является LT_CLOSE.

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

int current_result = 0; get_next_lexem(); if (current_lexem_type == LT_NUMBER) { // в случае, если первая лексема выражения - это число, ничего не меняется current_result = current_lexem_value; get_next_lexem(); } else { // в противном случае сделаем рекурсивный вызов // который вычислит для нас выражение в скобках current_result = evaluate_expression(); get_next_lexem(); // как и ранее, вызов get_next_lexem(); нужен чтобы пропустить // закрывающуюся скобку }
Последнее изменение: Суббота, 15 Август 2020, 02:35