Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Парсер математических формул 
:(
    Опции темы
Toyamatokanava
  Дата 12.5.2014, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.10.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: нет



Из книги Шилдта взял пример парсера. Формулу ввожу с клавиатуры в edit.  Числа хорошо анализирует, а вот с переменными беда. Не могу понять почему  smile . Подскажите пожалуйста.




Код

#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
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0683 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.