Resolver expresiones con pilas

Iniciado por Juan, Noviembre 12, 2013, 08:41:11 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Noviembre 12, 2013, 08:41:11 PM Ultima modificación: Noviembre 13, 2013, 11:18:20 AM por mDrinky
Resuelve expresiones como 1+1+1+1 , 2*5(3+4), (5*2)+(5*3). No resolvera numeros de dos o mas caracteres, aunque modificando un poco el codigo se puede conseguir :)

un saludo!

Código: c
// convierte expresion INFIJA en POSTFIJA y evalua expresiones POSTFIJAS 
// programado por Juan fary (mDrinky) [email protected]
// compilado con MingW y Code::Blocks

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

typedef struct Dato
{
    char caracter;
    struct Dato * Siguiente;
}_Dato;

typedef _Dato * ptrDato;

void push(ptrDato * Pila,char caracter);
char pop(ptrDato * Pila);
int Prioridad(char Op1,char Op2);
char * PostFija(char * Cadena);
int Evaluar(char * Expresion);

int main()
{
    char * cadena = "5*3+8*5";

    char * Expresion = PostFija(cadena);

    printf("POSTFIJA: %s\n",Expresion);

    printf("Resultado de la operacion: %i",Evaluar(Expresion));

    return 0;
}

int Evaluar(char * Expresion)
{
    ptrDato Pila = NULL;
    int num1 = 0,num2 = 0,i = 0, Resultado = 0;

    while (Expresion[i] != '\0')
    {
        if (Expresion[i] != '*' && Expresion[i] != '/' && Expresion[i] != '+' && Expresion[i] != '-')
        {
            push(&Pila,Expresion[i]);
        }else{
            num1 = (pop(&Pila)-0x30);
            num2 = (pop(&Pila)-0x30);

            switch (Expresion[i])
            {
                case '*':
                    Resultado = ((num1*num2));
                    break;

                case '/':
                    Resultado = ((num1/num2));
                    break;

                case '+':
                    Resultado = ((num1+num2));
                    break;

                case '-':
                    Resultado = ((num1-num2));
                    break;
            }
            push (&Pila,(Resultado+0x30));
        }
        i++;
    }
    return Resultado;
}

char * PostFija(char * cadena)
{
    ptrDato Pila = NULL;
    int i = 0,a = 0, Elementos = 0,Longitud = 0;
    char dato;

    Longitud = strlen(cadena);

    char * buffer = (char*) malloc(Longitud);
    memset(buffer,0,Longitud);

    while(cadena[i] != '\0')
    {
        if (cadena[i] == '(')
        {
            push(&Pila,cadena[i]);
            Elementos += 1;
        }else if (cadena[i] == ')'){
            while(1)
            {
                dato = pop(&Pila);
                Elementos -= 1;

                if(dato == '(')
                {
                    break;
                }else{
                    buffer[a] = dato;
                    a += 1;
                }
            }
        }else if(cadena[i] == '*' || cadena[i]  == '/' || cadena[i] == '+' || cadena[i] == '-'){
            RepetirProceso:
            if (Elementos == 0)
            {
                push (&Pila,cadena[i]);
                Elementos += 1;
            }else if(Prioridad(Pila->caracter,cadena[i]) == 1)
            {
                push(&Pila,cadena[i]);
                Elementos += 1;
            }else if (Pila->caracter != '('){
                dato = pop(&Pila);
                Elementos -= 1;

                buffer[a] = dato;
                a += 1;

                goto RepetirProceso;
            }
        }else{
            buffer[a] = cadena[i];
            a += 1;
        }
        i++;
    }

    while(Pila != 0)
    {
        buffer[a] = pop(&Pila);
        a += 1;
    }
    return buffer;
}

int Prioridad(char Op1,char Op2)
{
        int Estado = 1;

        if (Op1 == '*' && Op2 == '-' || Op1 == '*' && Op2 == '+' || Op1 == '/' && Op2 == '-' || Op1 == '/' && Op2 == '+')
        {
            Estado = 0;
        }

        return Estado;
}

char pop(ptrDato * Pila)
{
    ptrDato ViejoDato;
    char _caracter;

    ViejoDato = *Pila;
    _caracter = (*Pila)->caracter;

    *Pila = (*Pila)->Siguiente;

    free(ViejoDato);

    return _caracter;
}
void push(ptrDato * Pila,char caracter)
{
    ptrDato NuevoDato;

    NuevoDato = (ptrDato)malloc(sizeof(_Dato));
    memset(NuevoDato,0,sizeof(_Dato));

    if (NuevoDato != NULL)
    {
        NuevoDato->caracter = caracter;
        NuevoDato->Siguiente = *Pila;

        *Pila = NuevoDato;
    }
}

Muy bueno mDrinky!
Cuando dices que no resuelve numeros con dos caracteres, tambien te refieres a numeros decimales?

Saludos!


HOLA!!!

Quiere decir que su metodo toma a cada caracter como numero completo no como digitos de un numero mas grande...

Osea:
923 seria para su procedimiento 9 ; 2 ; 3

y 9,23 seria para su procedimiento 9 ; , ; 2 ; 3

GRACIAS POR LEER!!!
"Algunos creen que soy un bot, puede que tengan razon"
"Como no se puede igualar a Dios, ya he decidido que hacer, ¡SUPERARLO!"
"La peor de las ignorancias es no saber corregirlas"

*Shadow Scouts Team*                                                No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Cuando dices que no resuelve numeros con dos caracteres, tambien te refieres a numeros decimales?

Seguramente no los aceptará Antrax.

Porque esta usando números enteros (Int), para que aceptará números decimales tendría que usar "float".


Saludos

Tienen razon! ahi lo lei!
Ahora si vale la aclaracion de mDrinky

CitarNo resolvera numeros de dos caracteres, aunque modificando un poco el codigo se peude conseguir


HOLA!!!

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Cuando dices que no resuelve numeros con dos caracteres, tambien te refieres a numeros decimales?

Seguramente no los aceptará Antrax.

Porque esta usando números enteros (Int), para que aceptará números decimales tendría que usar "float".


Saludos

Lamento decir que esa apreciacion es erronea, se puede operar con enteros y para calcular decimales... simplemente se realiza una simulacion de coma flotante donde se multiplica el numero por una potencia de diez grande, luego se realizan las opreaciones y por ultimo se vuelve a dividir...

Ejemplo:
9,7*8,2=> ((9,7*10)*(8.2*10))=>7954 /100 = 79.54
Ahora ustedes me diran, usaste punto en la ultima division...
NO, se hace asi la cuenta:
Int(7954/100)=79 (aca sabemos que la parte entera es 79, eso lo guardamos
79*100 = 7900 ...  7954-7900 = 54 (la parte decimal)

de esta manera ponemos 79 , 54 y no utilizamos decimales ;)

GRACIAS POR LEER!!!
"Algunos creen que soy un bot, puede que tengan razon"
"Como no se puede igualar a Dios, ya he decidido que hacer, ¡SUPERARLO!"
"La peor de las ignorancias es no saber corregirlas"

*Shadow Scouts Team*                                                No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Es lo que dice 7913,  He actualizado el código corrigiendo y minimizando algunas cosillas :P