Usuários online

segunda-feira, 24 de junho de 2013

Algoritmos e Estruturas de Dados - Técnico em Informática para Internet - Aula 24/06/2013

Analisador de Expressões Descendente
 
 


Um analisador de expressões é um excelente código para estudarmos diversas funções que trabalham com string e chamadas de função em C/C++. O código abaixo é de um analisador simples, capaz de trabalhar com os seguintes operadores aritméticos:


  • + adição -- por exemplo, 2+4
  • - subtração -- por exemplo, 2-4
  • * multiplicação -- por exemplo, 2*4
  • / divisão -- por exemplo, 2/4
  • ^ exponenciação -- por exemplo, 2^4
  • % módulo (resto da divisão) -- por exemplo, 2%4
  • ( e ) parênteses -- por exemplo, 2+(4-3)

Divirta-se primeiro com o código, que roda perfeito no Dev-C++ e depois tente entender como funciona um Analisador de Expressões Descendente. Em outra oportunidade, melhoraremos o código e acrescentaremos novas funcionalidades, como a possibilidade de usar variáveis e acréscimos de funções como logaritmos, senos, cossenos etc.

Bom estudo!

#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>

#define DELIMITADOR 1
#define VARIAVEL 2
#define NUMERO 3

char *prog;
char token[80];
char tok_type;
           
void eval_exp(double *answer);
void eval_exp2(double *answer);
void eval_exp3(double *answer);
void eval_exp4(double *answer);
void eval_exp5(double *answer);
void eval_exp6(double *answer);
void atom(double *answer);
void get_token(void);
void putback(void);
void unary(char o, double *r);
void serror(int error);
int isdelim(char c);

void eval_exp(double *answer)
{
   get_token();
   if(!token)
   {
      serror(2);
      return;
   }
   eval_exp2(answer);
}

void eval_exp2(double *answer)
{
   register char op;
   double temp;

   eval_exp3(answer);
   while ( (op = *token) == '+' || op == '-')
   {
      get_token();
      eval_exp3(&temp);
      switch(op) {
         case '-':
            *answer = *answer - temp;
            break;
         case '+' :
            *answer = *answer + temp;
            break;
      }
   }
}

void eval_exp3(double *answer)
{
   register char op;
   double temp;

   eval_exp4(answer);

   while ((op=*token) == '%' || op == '/' || op =='*')
   {
      get_token();
      eval_exp4(&temp);
      switch (op) {
         case '*':
            *answer = *answer * temp;
            break;
         case '/':
            *answer = *answer / temp;
            break;

         case '%':
            *answer = (int)*answer % (int)temp;
            break;
      }
   }
}

void eval_exp4(double *answer)
{
   double temp, ex;
   register int t;

   eval_exp5(answer);
   if (*token=='^') {
      get_token();
      eval_exp4(&temp);
      ex = *answer;
      if (temp==0.0) {
         *answer = 1.0;
         return;
      }
      for (t=(int)temp-1;t>0;--t) *answer = (*answer) * (double)ex;
   }
}

void eval_exp5(double *answer)
{
   register char op;
   op = 0;
   if ((tok_type == DELIMITADOR) && *token=='+' || *token=='-') {
      op = *token;
      get_token();
   }
   eval_exp6(answer);
   if (op=='-') *answer = -(*answer);
}

void eval_exp6(double *answer)
{
   if ((*token=='(')) {
      get_token();
      eval_exp2(answer);
      if (*token != ')')
         serror(1);
      get_token();
   }
   else
      atom(answer);
}
void atom(double *answer)
{
   if (tok_type == NUMERO) {
      *answer = atof(token);
      get_token();
      return;
   }
   serror(0);
}

void putback()
{
 char *t;
 t = token;
 for (;*t;t++) prog--;
}

void serror(int error)
{
   static char *e[] = {"erro de sintaxe",
                       "falta parenteses",
                       "nenhuma expressao presente"
                      };
   printf("%s\n", e[error]);
}

void get_token(void)
{
   register char *temp;
   tok_type = 0;
   temp = token;
   *temp = '\0';
   if (!*prog) return;
   while (isspace(*prog)) ++prog;
   if (strchr("+-*/%^=()", *prog)) {
      tok_type = DELIMITADOR;
      *temp++ = *prog++;
   }
   else if (isdigit(*prog)) {
        while (!isdelim(*prog)) *temp++ = *prog++;
        tok_type = NUMERO;
   }
   *temp = '\0';
}

int isdelim(char c)
{

   if (strchr(" +-*/%^=()", c) || c==9 || c=='\r' || c==0) {
      return 1;
   }
   return 0;
}

main(void)
{
   double answer;
   char *p;

   p = (char *) calloc(100, sizeof(p));
   prog = (char *) calloc(100, sizeof(prog));
 
   if (!p) {
      printf("falha na execucao\n");
      exit(1);
   }

   printf("Entre com uma expressao usando: +, -, *, /, %, ^, ( ou ). Por exemplo: 2+3-4*5/2^10 e tecle ENTER\n\n");
   do {
      printf("> ");
      scanf("%s", prog);
      if (!*prog) break;
      eval_exp(&answer);
      printf(">> %.15f\n\n", answer);
   } while (!*p);
}

Nenhum comentário:

Postar um comentário

Observação: somente um membro deste blog pode postar um comentário.

LinkWithin

Related Posts Plugin for WordPress, Blogger...

NOSSO OBJETIVO

OBJETIVO

Este blog será usado para divulgação de minhas ideias, notícias sobre tecnologia, disponibilização de links para download de materiais diversos (incluindo materiais didáticos -- que poderão ser usados em minhas aulas e/ou cursos). Gostaria de DEIXAR BEM CLARO que quaisquer materiais disponibilizados através deste blog são, tão somente, para acompanhamento de aulas e/ou cursos, e não constituem de modo algum, aulas na modalidade "ensino à distância" (EAD). Alunos têm total acesso aos materiais disponíveis, mas somente como tutoriais passo a passo. Apostilas disponibilizadas através deste blog não são materiais obrigatórios em disciplinas cursadas ou cursos ministrados.

RESPONSABILIDADE

O autor deste blog não é responsável pelo mau uso, intencional ou não, de qualquer código de programa disponibilizado aqui. Os códigos de programas disponíveis neste blog para download é e serão sempre, e tão somente, para uso didático durante o aprendizado. Seja bem-vindo.