Из книги Шилдта взял пример парсера. Формулу ввожу с клавиатуры в edit. Числа хорошо анализирует, а вот с переменными беда. Не могу понять почему  . Подскажите пожалуйста. Код | #define DELIMITER 1 #define VARIABLE 2 #define NUMBER 3
char *exp_ptr; /* указатель на анализируемое выражение */ char token[80]; char tok_type;
double vars[26] = { /* 26 пользовательских переменных, A-Z */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double eval_exp(char *exp); void eval_exp1(double &result), eval_exp2(double &result); void eval_exp3(double &result), eval_exp4(double &result); void eval_exp5(double &result), eval_exp6(double &result); void atom(double &result); void get_token(void), putback(void); void serror(int error); double find_var(char *s); int isdelim(char c);
/* Точка входа анализатора. */ double eval_exp(char *exp) { double result; exp_ptr=exp; get_token(); if(!*token) { serror(2); return 0.0; } eval_exp1(result); if(*token) serror(0); /* последня лексема должна быть нулем */ return result; }
/* Обработка присваивания. */ void eval_exp1(double &result) { int slot; char ttok_type; char temp_token[80];
if(tok_type == VARIABLE) { /* сохранить старую лексему */ strcpy_s(temp_token, token); ttok_type = tok_type; /* вычислить индекс переменной */ slot = toupper(*token) - 'A';
get_token(); if(*token != '=') { putback(); /* вернуть текущую лексему */ /* восстановить старую лексему - это не присваивание */ strcpy_s(token, temp_token); tok_type = ttok_type; } else { get_token(); /* получить следующую часть выражения */ eval_exp2(result); vars[slot] =result; return; } } eval_exp2(result); }
/* Сложение или вычитание двух слагаемых. */ void eval_exp2(double &result) { register char op; double temp;
eval_exp3(result); while((op = *token) == '+' || op == '-') { get_token(); eval_exp3(temp); switch(op) { case '-': result = result - temp; break; case '+': result = result + temp; break; } } }
/* Умножение или деление двух множителей. */ void eval_exp3(double &result) { register char op; double temp;
eval_exp4(result); while((op = *token) == '*' || op == '/' || op == '%') { get_token(); eval_exp4(temp); switch(op) { case '*': result = result * temp; break; case '/': if(temp == 0.0) { serror(3); /* деление на ноль */ result = 0.0; } else result = result / temp; break; case '%': result = (int) result % (int) temp; break; } } }
/* Возведение в степень */ void eval_exp4(double &result) { double temp, ex; register int t;
eval_exp5(result); if(*token == '^') { get_token(); eval_exp4(temp); ex = result; if(temp==0.0) { result = 1.0; return; } // for(t=temp-1; t>0; --t) result = (result) * (double)ex; } }
/* Вычисление унарного + и -. */ void eval_exp5(double &result) { register char op;
op = 0; if((tok_type == DELIMITER) && *token=='+' || *token == '-') { op = *token; get_token(); } eval_exp6(result); if(op == '-') result = -(result); }
/* Обработка выражения в скобках. */ void eval_exp6(double &result) { if((*token == '(')) { get_token(); eval_exp2(result); if(*token != ')') serror(1); get_token(); } else atom(result); }
/* Получение значения числа или переменной. */ void atom(double &result) { switch(tok_type) { case VARIABLE: result = find_var(token); get_token(); return; case NUMBER: result = atof(token); get_token(); return; default: serror(0); } }
/* Возврат лексемы во входной поток. */ void putback(void) { char *t;
t = token; for(; *t; t++) exp_ptr--; }
/* Отображение сообщения о синтаксической ошибке. */ void serror(int error) { static char *e[]= { "Синтаксическая ошибка", "Несбалансированные скобки", "Нет выражения", "Деление на нуль" }; printf("%s\n", e[error]); }
/* Получение очередной лексемы. */ void get_token(void) { register char *temp;
tok_type = 0; temp = token; *temp = '\0';
if(!*exp_ptr) return; /* конец выражения */
while(isspace(*exp_ptr)) ++exp_ptr; /* пропустить пробелы, символы табуляции и пустой строки */
if(strchr("+-*/%^=()", *exp_ptr)){ tok_type = DELIMITER; /* перейти к следующему символу */ *temp++ = *exp_ptr++; } else if(isalpha(*exp_ptr)) { while(!isdelim(*exp_ptr)) *temp++ = *exp_ptr++; tok_type = VARIABLE; } else if(isdigit(*exp_ptr)) { while(!isdelim(*exp_ptr)) *temp++ = *exp_ptr++; tok_type = NUMBER; }
*temp = '\0'; }
/* Возвращение значения ИСТИНА, если с является разделителем. */ int isdelim(char c) { if(strchr(" +-/*%^=()", c) || c==9 || c=='\r' || c==0) return 1; return 0; }
/* Получение значения переменной. */ double find_var(char *s) { if(!isalpha(*s)){ serror(1); return 0.0; } return vars[toupper(*token)-'A']; }
|
Это сообщение отредактировал(а) Toyamatokanava - 12.5.2014, 18:07
|