EVALUA_EXPR.c



/* EVALUACION DE EXPRESIONES

	J. Rafael RodrIguez Ochoa
//
// CaracterIsticas:
//	Dada una expresiOn, (como: "(sin(30)*2+3*4/(2-1) +7)" ) se
//	almacena en una cadena y se evalua con la tEcnica de recursividad
//	derecha evaluandose conforme se avanza de izquierda a derecha.
//
// Manera de ejecutarse:
//              Al correr el programa pedirA el siguiente dato:
//		1.- "\n=> "
//		2.- Teclee la expresiOn terminando con enter
//		3.- a lo que el programa contestarA con el valor numErico
//		    equivalente
//
// El programa se probO con la siguiente expresiOn
//
//	sin(30) * cos(40 - 10)
//-------------------------------------------------------------------------
*/


#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <alloc.h>

char *lectura(void);		       //OK
void evalua(char *, int *);            //OK
void entero(char *);                   //OK
int termino(char *);                   //OK
void funcion(char *, int *);	       //OK
void parentesis(char *, int *);        //OK

struct vars			// Variables definidas.
{
   char var;
   int val;
   struct vars *sig;
   struct vars *ant;
};
struct vars *pri_v = NULL;	// Apuntador a la primera variable

void main ()
{
   char *car;
   int ok = 1, res;
   while (ok)
   {
      car = lectura();
      if (strlen(car) == 0) return;
      //printf("\ncadena= %s",car);
      evalua(car, &res);
      if(res >= 0) printf("\n%d",res);
   }
   printf("salio\n");
   getch();
}

void evalua(char *cadena, int *res)
{
   int ent1,ent2;
   char c;
   c = cadena[0];
   ent1 = termino(cadena);
   if (c == '(') parentesis(cadena, &ent1);
   *res = ent1;
   while ( (c=cadena[0]) == '+' || c == '-' || c == '/' || c == '*')
   {
      ++cadena;
      if  (cadena[0] == '(') parentesis(cadena, &ent2);
      else ent2 = termino(cadena);
      if (c == '+') *res = *res + ent2;
      if (c == '-') *res = *res - ent2;
      if (c == '*') *res = *res * ent2;
      if (c == '/') *res = *res / ent2;
   }
}

void parentesis(char *cad, int *res)
{
   int c = cad[0], ent2;
   *res = termino(++cad);
   while ( (c = cad[0]) != ')')
   {
      ent2 = termino(++cad);
      if (c == '+') *res = *res + ent2;
      if (c == '-') *res = *res - ent2;
      if (c == '*') *res = *res * ent2;
      if (c == '/') *res = *res / ent2;
   }
   ++cad;
}


void entero(char *cadena, int *res)
{
   int c=cadena[0];
   *res = c -'0';
   cadena++;
   while( (c = cadena[0]) >= '0' && c <= '9')
      *res = *res*10 + (c - '0');
}

char *lectura(void)
{
	 char *car;
	 printf("\n=> ");
	 gets(car);
	 return car;
}
void funcion(char *cadena, int *res)
{
   int c=cadena[0],ent1;
   ++cadena; ++cadena; ++cadena;
   parentesis(cadena, &ent1);
   if (c == 's') *res = sin(ent1);
   if (c == 'c') *res = cos(ent1);
}

void lista(char *cad, int *res)
{
   struct vars *y,*nuevo;
   y = pri_v;
   while(y)
   {
      if(y->var == cad[0])
      {
	*res = y->val;
	++cad;
	return;
      }
      y = y->sig;
   }
   if (cad[1] == '=')
   {
      nuevo = (vars *)malloc(sizeof(struct vars));
      if (!nuevo) {printf("No hay memoria suficiente..."); return;}
      nuevo->var = cad[0];
      ++cad; ++cad;				// elimina 'letra' y '='
      *res = nuevo->val = termino(cad);
      nuevo->ant = NULL;			// se aNIade al  principio
      nuevo->sig = pri_v;                 	// de la lista.
      pri_v->ant = nuevo;
      pri_v = nuevo;
   }
   else *res = 0;
}

int termino(char *cad)				// "*" O "/"
{
   int res,c=cad[0];
   if (c >= '0' && c <= '9') entero(cad, &res);	// Es entero.
   if (c == 's' || c == 'c') funcion(cad, &res);	// Es funciOn.
   if ( (c == 'a' || c == 'b') ||			// Es variable.
	(c >= 'd' && c <= 'r') ||
	(c >= 't' && c <= 'z')
      ) lista(cad, &res);				// Si existe se toma su valor
							// si no, se aNIade a la lista.
   return res;
}