Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практикум по программированию на языке программирования Си..pdf
Скачиваний:
20
Добавлен:
05.02.2023
Размер:
1.39 Mб
Скачать

114

return 1; //вернуть значение совпадения

}

9.3.4 Реализация метода рекурсивного спуска

Рекурсивный разбор арифметического выражения начинается с рабо­ ты функции ExpressAdd, которая осуществляется разбор и вычисление ад­ дитивных составляющих арифметического выражения.

TranSin — функция разбора и вычисления синуса; ExpressFunc — разбор первичного (см. алгоритм РазборD() );

ExpressMult — разбор и вычисление выражений с умножением и деле­

нием;

ExpressAdd — разбор и вычисление выражений со сложением и вычи­ танием;

AssignOp — вычисление и разбор выражения и присвоение результат переменной.

Текст функции разбора и вычисления синуса

void TranSin(void) { // вычисление синуса

double f;

 

if(match("(")) {

//есть ли скобка ?

ExpressAdd();

//вычислить выражение аргумента синуса

f=Pull();

//взять значение из стека

Push(sin(f));

//положить в стек значения синуса

match(")");

//ждать закрывающуюся скобку

}

else Error("Ошибка в функции sin");

}

void ExpressFunc(void) {// вычисление первичного выражения int num;

char name[30]; double f;

int max=29;

if(match("(")){ //вычисление выражения в скобках ExpressAdd(); //разобрать и вычисллить выражение в скобках if(match(")")==0) Error("Пропущена )");

}

else { //вычисление функций

//вычислить значение первого операнда
//если знак плюс

115

if(match("sin")) TranSin(); else { //это переменная?

if(GetName(name,max)==1) { //взятие значения переменной

num=AddNameVar(name);

//найти переменную в таблице

Push(TablVar[num].init);

//положить табличное значение в стек

}

 

else { //взять значение константы f=getfloat(name,max);

Push(f);

//положить значение константы в стек

}

 

}

 

}

 

}

 

void ExpressMult(void) { //вычисление выражения для умножения и деления

double f1, f2;

 

ExpressFunc();

//вычислить первичное

while(1) {

 

if(match("*")) {

//если знак умножения

ExpressFunc();

//вычислить второе первичное

f1=Pull(); f2=Pull(); //взять из стека множители

Push(f1*f2);

//положить в стек произведение

}

 

else

 

if(match("/")){

//если знак деления

ExpressFunc();

//вычислить второе первичное

f1=Pull();

//взять делитель

f2=Pull();

//взять делимое

if(f1==0.) Error("Деление на 0");

else Push(f2/f1); //положить частное в стек

}

else break;

}

}

void ExpressAdd(void) { // вычисление выражения для сложения и вычита­ ния

double f1, f2; ExpressMult(); while(1) { if(match("+")){

 

116

ExpressMult();

//вычислить значение для второго операнда

f1=Pull(); f2=Pull(); //взять значения слагаемых из стека

Push(f1+f2);

//положить сумму в стек

}

 

else

 

if(match("­")) {

//если это минус

ExpressMult();

//взять значение второго операнда

f1=Pull(); f2=Pull(); //взять значения из стека

Push(f2­f1);

//положить разность в стек

}

 

else break;

 

}

 

}

 

void AssignOp(void) {// выполнение операции присваивания char name[10];

int max=9; int num;

if(GetName(name,max)==1) { //взять имя переменной num=AddNameVar(name); //записать имя в таблицу

}

 

else {

 

ExpressAdd();

//иначе вычислить выражение

printf("%f\n",Pull());

return;

 

}

 

if(match("=")) {

//имеется операция присваивания

ExpressAdd();

//вычислить выражение

TablVar[num].init=Pull(); //записать значение в таблицу

}

printf("%f\n",TablVar[num].init);

}

PrintTablVar() {// вывод таблицы символов со значениями int i;

for(i=0; i<TopVar; i++) {

printf("%2d %10s %f\n",i,TablVar[i].Name,TablVar[i].init);

}

}

void main() {