miércoles, 21 de septiembre de 2011

Cálculo de una expresión aritmética

calculo-de-una-expresion-aritmética
El algoritmo permite calcular el resultado de una expresión aritmética ingresada por teclado

#include <iostream>
#include <string>
#include <sstream>
#include <tgmath.h>

using namespace std;

//PRIMERA PARTE: PILA DE OPERANDOS

int xSize;
int xCab;
bool xFull;
bool xHas;
struct structXHeap
{
 double dat;
} *xHeap;

void xInit(int size)
{
    xSize = size;
    xCab = -1;
    xFull = false;
    xHas = false;
    xHeap = new structXHeap[xSize];
}

bool xPush(double xdat)
{
 if(xFull)
  return false;
 else
 {
  xCab++;
  xHeap[xCab].dat = xdat;

  xHas = true;

  if(xCab == xSize-1)
   xFull = true;

  return true;
 }
}

double xTop()
{
 if(xHas)
  return xHeap[xCab].dat;
 else
  return -1;
}

double xPop()
{
 if(xHas)
 {
  double dat_out = xTop();
  xCab--;
  
  xFull = false;

  if(xCab<0)
   xHas = false;
   

  return dat_out;
 }
 else
  return -1;
}

int xLength()
{
 return xCab+1;
}

double *getXHeap()
{
 double *xHeapGeted = new double[xCab+1];

 int j=xCab;

 for(int i=0;i<=xCab;i++)
 {
  xHeapGeted[j] = xHeap[i].dat;
  j--;
 }

 return xHeapGeted;
}

//SEGUNDA PARTE: PILA DE OPERADORES

int ySize;
int yCab;
bool yFull;
bool yHas;
struct structYHeap
{
 char dato;
 int prioridad;
} *yHeap;

void yInit(int size)
{
    ySize = size;
    yCab = -1;
    yFull = false;
    yHas = false;
    yHeap = new structYHeap[ySize];
}

bool yPush(char yDat)
{
 if(yFull)
  return false;
 else
 {
  yCab++;
  yHeap[yCab].dato = yDat;
  
  yHas = true;
  
  if(yCab == ySize-1)
   yFull = true;

  return true;
 }
}

char yTop()
{
 if(yHas)
  return yHeap[yCab].dato;
 else
  return '\0';
}

char yPop()
{
 if(yHas)
 {
  char dato_out = yTop();
  yCab--;
  
  yFull = false;

  if(yCab<0)
   yHas = false;  

  return dato_out;
 }
 else
  return '\0';
}

int yLength()
{
 return yCab+1;
}

char *getYHeap()
{
 char *yHeapGeted = new char[yCab+1];

 int j=yCab;

 for(int i=0;i<=yCab;i++)
 {
  yHeapGeted[j] = yHeap[i].dato;
  j--;
 }

 return yHeapGeted;
}

//TERCERA PARTE: LÓGICA DE USOS

int calculatePriority(char xOperator)
{
    switch (xOperator)//Tabla de prioridades de los operadores
    {
        case '(':
            return 0;
        case ')':
            return 0;
        case '+':
            return 1;
        case '-':
            return 1;
        case '/':
            return 2;
        case '*':
            return 2;
        case '^':
            return 3;
        default:
            return 0;
    }

}

bool analyzeInfix(string infix)
{
 int open=0;
 int closer=0;

 for(unsigned int i=0; i<infix.size() ;i++)
 {
  if(infix[i]=='(')
   open++;
  if(infix[i]==')')
   closer++;
 }

 if(open==closer)
  return true;
 else
  return false;
}
                                                                                                                                                                                                                                                                                                        
string convertToPostfix(string infix)
{
 string postfix="";
 yInit(100);

 for(unsigned int i=0;i<infix.size();i++)
 {
  char xdato=infix[i];

  int ascii=int(xdato);//Extrae el código ASCII de un caracter

  if(ascii>47 && ascii<58)//Si el codigo ASCII esta entre estos valores, entonces es un número natural
   postfix+=xdato;
  else//Si no es un número natural entre en este "else"
  { 
   if(xdato=='(')//Si es un paréntesis izquierdo simplemente se colocará en la pila
    yPush(xdato);//Se agrega a la pila de operadores
   else
   {
    if(xdato==')')//Si es un paréntesis derecho debe sacar todos los operadores almacenados hasta que se encuentre un paréntesis izquierdo
    {
     while(yTop()!='(')//Extrae los operadores hasta que se encuentre un paréntesis izquierdo
      postfix+=yPop();

     yPop();//Este último paréntesis izquierdo no fue eliminado de la pila, pero acá se elimina

    }
    else//Si no es paréntesis entonces es un operador
    {     
     if(!yHas)//Verifica si la pila de operadores está vacía
      yPush(xdato);//De ser así solo colocamos el operador en la pila
     else
     {
      if(calculatePriority(xdato)<=calculatePriority(yTop()))//Compara la prioridad del operador entrante con el que está en la cabecera de la pila
      {
       char operador=yPop();//Si es menor debemos sacar el que está en la cabecera
       yPush(xdato);//Y colocar el entrante en la cabecera
       postfix+=operador;//y el que salio lo colocamos en postfix
      }
      else
       yPush(xdato);//Si el operador entrante fuese de mayor prioridad que el de la cabecera, simplemente se coloca en la pila
     }
    }
   }
   
  }

 }
 
 while(yHas)
  postfix+=yPop();

 return postfix;
}


string invertExpression(string infix)
{
 string infixInvertida="";

 for(unsigned int i=0;i<infix.size();i++)
 {
  char caracter = infix[i];

  if(caracter==')')
   caracter = '(';
  else
  {
   if(caracter=='(')
    caracter = ')';
  }

  infixInvertida=caracter+infixInvertida;

 }

 return infixInvertida;
}

double postfixResult(string postfix)
{
    xInit(100);
 for(unsigned int i=0;i<postfix.size();i++)
 {
  char xdato=postfix[i];

  int ascii=int(xdato);//Extrae el código ASCII de un caracter

  if(ascii>47 && ascii<58)//Si el codigo ASCII esta entre estos valores, entonces es un número natural
   xPush(xdato-'0');
  else
  {
   double num1=xPop();
   double num2=xPop();

   switch(xdato)//Tabla de operaciones
   {
   case '+':
    xPush(num2+num1);break;
   case '-':
    xPush(num2-num1);break;
   case '/':
    xPush(num2/num1);break;
   case '*':
    xPush(num2*num1);break;
   case '^':
    xPush(pow(num2,num1));break;
   }
  }
 }

 return xPop();
}

//MAIN
int main()
{
    string infix;
    cout << "Ingrese una expresión aritmética: ";
    cin >> infix;
    
    if(analyzeInfix(infix))
    {
        string postfix = convertToPostfix(infix);
        cout << to_string(postfixResult(postfix));
    }
    else
    {
      cout << "Falta cerrar o abrir algunos paréntesis ()";
    }
}

Copiar, pegar y ejecutar este script en http://cpp.sh/

No hay comentarios:

Publicar un comentario