#include<stdio.h>
#include<math.h>
#include<ctype.h>

#define EXPR_LEN	50	/* Longitud de la Expresion */

struct pila_char{
	unsigned char pila[EXPR_LEN];
	int tope;
};

struct pila_float{
	float pila[50];
	int tope;
};

void iniciar_pila_char(struct pila_char *a)
{
	a->pila[0] = 0;
	a->tope = -1;
}

void iniciar_pila_float(struct pila_float *a)
{
	a->tope = -1;
}

void meter_pila_char(struct pila_char *a, unsigned char b)
{
	a->tope++;
	a->pila[a->tope] = b;
}

void meter_pila_float(struct pila_float *a, float b)
{
	a->tope++;
	a->pila[a->tope] = b;
}

unsigned sacar_pila_char(struct pila_char *a)
{
	unsigned char simbolo = a->pila[a->tope];

	a->tope--;

	return simbolo;
}

float sacar_pila_float(struct pila_float *a)
{
	float simbolo = a->pila[a->tope];

	a->tope--;

	return simbolo;
}

int pila_vacia_char(struct pila_char *a)
{
	if(a->tope == -1)
		return 1;

	return 0;
}

int asignar_prioridad(unsigned char a)
{
	if((toupper(a) == 'S') || (toupper(a) == 'C'))
		return 1;
	if((a == '*') || (a == '/'))
		return 2;
	if((a == '+') || (a == '-'))
		return 3;		
}

void posfija(char *a, char *b)
{
	struct pila_char pila;
	unsigned char simbolo;
	int prioridad_entrada, prioridad_pila;

	iniciar_pila_char(&pila);

	while(*a != '\0')
		switch(*a){
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				*b = *a;
				a++;
				b++;
				break;
			case '(':
				meter_pila_char(&pila, '(');
				a++;
				break;
			case ')':
				while((simbolo = sacar_pila_char(&pila)) != '('){
					*b = simbolo;
					b++;
				}
				a++;
				break;
			case '+':
			case '-':
			case '*':
			case '/':
			case 's':
			case 'S':
			case 'c':
			case 'C':
				if(pila_vacia_char(&pila)){
					meter_pila_char(&pila, *a);
					a++;
					break;
				}

				simbolo = sacar_pila_char(&pila);

				if(simbolo == '('){
					meter_pila_char(&pila, simbolo);
					meter_pila_char(&pila, *a);
					a++;
					break;
				}

				prioridad_entrada = asignar_prioridad(*a);
				prioridad_pila = asignar_prioridad(simbolo);

				if(prioridad_entrada >= prioridad_pila){
					*b = simbolo;
					b++;
				}
				else{
					meter_pila_char(&pila, simbolo);
					meter_pila_char(&pila, *a);
					a++;
				}
				break;
			default:
				printf("Token no valido\n");
		}

	while(!pila_vacia_char(&pila)){
		*b = sacar_pila_char(&pila);
		b++;
	}

	*b = '\0';
}

float evaluacion(char *a)
{
	float operando_izquierdo, operando_derecho, operando_unico, resultado;
	struct pila_float pila;

	iniciar_pila_float(&pila);

	while(*a != '\0'){
		if(isdigit(*a))
			meter_pila_float(&pila, *a-'0'); /* convierte el caracter a número */

		if(*a == '+' || *a == '-' || *a == '*' || *a == '/'){
			operando_derecho = sacar_pila_float(&pila);
			operando_izquierdo = sacar_pila_float(&pila);
			switch(*a){
				case '+':
					resultado = operando_izquierdo + operando_derecho;
					break;
				case '-':
					resultado = operando_izquierdo - operando_derecho;
					break;
				case '*':
					resultado = operando_izquierdo * operando_derecho;
					break;
				case '/':
					resultado = operando_izquierdo / operando_derecho;
					break;
			}
			meter_pila_float(&pila, resultado);
		}
		if(toupper(*a) == 'S' || toupper(*a) == 'C'){
			operando_unico = sacar_pila_float(&pila);
			switch(*a){
				case 's':
				case 'S':
					resultado = sin(3.14159 * operando_unico / 180);
					break;
				case 'c':
				case 'C':
					resultado = cos(3.14159 * operando_unico / 180);
			}
			meter_pila_float(&pila, resultado);
		}
		a++;
	}

	return sacar_pila_float(&pila);
}

int main()
{
	unsigned char entrada[EXPR_LEN], salida[EXPR_LEN];

	printf("Expresion: ");	gets(entrada);
	posfija(entrada, salida);
	printf("Posfija: %s\n", salida);
	printf("Resultado: %.2f\n", evaluacion(salida));

	return 0;
}
