Sunteți pe pagina 1din 79

Introducción

Expresión Infija. Se le llama expresión infija a aquella expresión común de fórmulas


matemáticas y lógicas, donde se escriben los operadores entre los operandos que se están
evaluando, se considera la acción de los paréntesis (si los hay) dentro de la expresión.
Ejemplo: (A+B)*C .

Expresión postfija Se denomina expresión postfija a aquella que contiene los operandos
se encuentran antes de los operadores, respetando la jerarquía de los mismos, no se
consideran los paréntesis, ya que la expresión postfija respeta la jerarquía de operadores
por sí misma. Ejemplo: AB+C*.

TAD Pila. Es un concepto en donde se acumulan un conjunto de elementos desde un sólo


extremo, a ese extremo le llamamos “Tope”. También le podemos llamar como listas
“LIFO (Last In First Out)”.

Aplicaciones de la Pila. Una de las aplicaciones es la de “Evaluar una expresión infija” la


cual se necesita de un proceso basado en la Pila para poder evaluar cualquier expresión
en notación infija.

• ​Planteamiento del
problema

La problemática con la que nos encontramos esta vez fue la de cómo poder agilizar el
proceso de conversión de expresiones aritméticas en su notación infija a su notación
posfija.

Esta problemática nos ayudará a desarrollar nuestras habilidades de programación


particularmente en el uso de las Pilas, que es una estructura de datos que tiene bastantes
usos en nuestra área y en la vida cotidiana.

1
• ​Diseño y funcionamiento de la solución

La estructura, es vista de manera vertical, se insertan datos en ella, y se colocan encima


uno tras otro, siempre hay un dato que está hasta arriba y podemos sacar datos de esta
pila, siempre que el que saquemos sea el último en ingresar, salvo cuando la pila está
vacía.

F​IGURA ​1. Proceso de una pila en programación.

Para poder retornar un resultado adecuado es necesario:


● ​Convertir una expresión infija (del usuario) a postfija.
● ​Asignar valores a las variables existentes y evaluar.
● ​Que el dato que se retorna al evaluar, acepte decimales, ya que las divisiones de dos
enteros, son racionales en varios casos.
● ​Considerar la jerarquía de operadores aritméticos.

2
*Descripción del funcionamiento de los algoritmos que se apoyan del TAD
pila.

-Validación de paréntesis: ​El propósito de este algoritmo es verificar que todos los
pares “( )” aparezcan congruentemente dentro de la expresión infija, por ejemplo,
(A+B)/(C+D) tiene correctos estos caracteres, sin embargo, (A+B))/(C+D( es incorrecto.

Primeramente, se recorre la expresión y se analiza cada paso por los índices, si el caracter
encontrado es ‘(’, este se mete a la pila. Si el caracter es ‘)’, se saca uno de los caracteres
(que forzosamente es un paréntesis cerrado).

Si al finalizar el recorrido de la cadena, la pila queda con algún elemento dentro, los
paréntesis están mal escritos, hay un lugar donde no cierra un paréntesis.

Si al finalizar el recorrido de la cadena, la pila queda queda vacía, pero la expresión aún
tiene caracteres ‘)’, los paréntesis están mal escritos, hay un lugar donde no abre un
paréntesis.

Ya que el proceso se trata de un validación, es factible devolver un valor lógico de esta


operación, donde el caso verdadero se da cuando los paréntesis sean correctos,

-Convertir expresión a posfija: ​Primeramente, se recorre la expresión y se analiza cada


paso por los índices, si el caracter encontrado es ‘(’, este se mete a la pila.

Si es alguna literal, se va directamente a la expresión


postfija.

Si el caracter es un operador, se mete a la pila, siempre que, sí existe en la pila un


operador que lo preceda, la jerarquía del mismo sea menor a la del que va a insertarse, en
caso contrario, se debe sacar el precedente de la pila y colocarlo como siguiente caracter
de la expresión postfija.

Si el caracter es ‘)’, se va a sacar todo de la pila, hasta donde exista un ‘(’ empilado, y se
colocarán los caracteres en la expresión posrfija, en el orden que fueron saliendo.

3
El proceso debe devolver una cadena con la expresión convertida a
postfijo.

Para realizar este procedimiento, es necesario haber pasado antes por la validación.

-Pedir valores al usuario y evaluar expresión: ​Se recorre la expresión en


notación postfija para darle valor a cada letra mayúscula que nos encontremos en
la expresión.

Creamos un arreglo auxiliar que guardará todas las letras que se encuentren en
nuestra expresión postfija, después de que guardamos todas las letras de la
expresión para mandarla a otra función que nos quitará todas la letras repetidas.

Teniendo el arreglo de todas las letras sin repetirlas haremos otro arreglo que
guardará los valores de cada letra para usar esos dos arreglos como referencia para
recorrer la expresión postfija e ir evaluando con los valores que se le asignó a cada
letra.

• ​Implementación de la solución

Pasos para evaluar una expresión


infija.

Paso 1 (Evaluar paréntesis). Lo primero que se debe realizar es que nuestra expresión sea
válida, revisando que todos los paréntesis tengan su par y no falte uno para abrir o para
cerrar.

Paso 2 (Convertir a postfija). Una vez validados los paréntesis de la expresión podremos
proceder a la conversión de la expresión de infija a postfija. Lo primero que tenemos que
tener en cuenta es la precedencia de la operación que se va obteniendo de la expresión.
Ocuparemos una pila para ir guardando los operadores.

Las reglas para insertar los operadores a la pila son las siguientes:

4
1. Si se tiene en el tope de la pila un operador de igual precedencia que el que se
tiene en la cadena, los operadores se cambian. 2. Si el operador es de mayor procedencia que
el que se tiene en el tope de la pila, se
agrega a la pila. 3. Si el operador es de menor precedencia que el que se tiene en el tope de la
pila, sacas todos los operadores hasta llegar a un paréntesis abierto, se saca el
paréntesis abierto e insertas el operador de la cadena. 4. Si te encuentras un paréntesis
abierto se inserta a la pila. 5. Si te encuentras un paréntesis cerrado sacas los
operadores hasta llegar al
paréntesis
abierto.

Con estas reglas la expresión quedará convertida en postfijo.

Paso 3 (Evaluar la expresión) Para poder evaluar la expresión ya convertida en postfija


tenemos que darle un valor a cada letra que tenemos en ella. Para tener un mayor orden y
entendimiento de nuestro código realizamos una función que nos verifique las letras para
darles un valor, si en algún caso una o más letras se repiten, sólo se le dará a esas letras
un sólo valor y evitamos volver a pedir el valor cada que se encuentre la misma letra que
apreció anteriormente.

Después de asignarle valores a cada letra de la expresión podemos preceder a recorrer la


expresión e ir realizando las operaciones, para ello se necesitará otra pila la cual irá
guardando los valores y cada que se encuentra un operador sacará dos valores y los
operará y después ese valor se insertará en la pila, al final se obtendrá el resultado de toda
la evaluación.

5
• Funcionamiento

6
F​IGURA ​2 y 3. Pantalla de salida al evaluar una expresión posfija.

7
• Posibles mejoras

Posiblemente en la función de darle valores a las letras de la


expresión podríamos hacer un algoritmo un poco más simple y
reducir código y funciones.

• Conclusiones

Las estructuras de datos son una herramienta sumamente útil al trabajar con proyectos
donde la información es demasiada, y es posible con ellas, optimizar tiempos de
operación de los procesos.

Gracias a esta práctica conseguimos ejercitar mucho el concepto del TAD Pila ya que
como cualquier otra estructura de datos, se puede aplicar en muchos problemas y tareas
en la computación porque por su particular forma de manipular la información podrás
notar en qué tipo de problemas se debe atacar usando una Pila.

• Anexo

- TADPilaEst.h

/*

LIBRERIA: Cabecera del TAD PILA ESTÃ​TICA

AUTORES:

Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

8
Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

DESCRIPCIÓN: TAD pila o stack.

Estructura de datos que cumple:

Los elementos se añaden y se remueven por un solo extremo.

Este extremo es llamado “topeâ€​ de la pila.

OBSERVACIONES: Estructura de datos estática, ya que se

asigna una cantidad fija de memoria para dicha estructura,

antes de la ejecución del programa.

*/

//DEFINICIONES DE CONSTANTES

9
#define MAX_ELEMENT 1000

#define TRUE 1

#define FALSE 0

//DEFINICIONES DE TIPOS DE DATO

//Definir un boolean (Se modela con un "char")

typedef unsigned char boolean;

//Definir un elemento (Se modela con una estructura "elemento")

typedef struct elemento

//Variables de la estructura "elemento" (El usuario puede


modificar)

char c;

float valor;

//***

10
//***

//***

}elemento;

//Definir una pila (Se modela con una estructura que unicamente
incluye un puntero a "elemento")

typedef struct pila

elemento arreglo[MAX_ELEMENT]; //La


pila es un arreglo estático de MAX_ELEMET

int tope;
//El tope es un entero (Indice del arreglo de elementos)

}pila;

//DECLARACIÓN DE FUNCIONES DE PILA

//Inicializar pila (Iniciar una pila para su uso)

11
void Initialize(pila *s);

//Empilar (Introducir un elemento a la pila)

void Push(pila *s, elemento e);

//Desempilar (Extraer un elemento de la pila)

elemento Pop (pila *s);

//Vacia (Preguntar si la pila esta vacia)

boolean Empty(pila *s);

//Tope (Obtener el "elemento" del tope de la pila si extraerlo de


la pila)

elemento Top(pila *s);

//Tamaño de la pila (Obtener el número de elementos en la


pila)

int Size(pila *s);

12
//Elimina pila (Borra a todos los elementos y a la pila de
memoria)

void Destroy(pila *s);

- TADPilaEst.c

/*

IMPLEMENTACIÓN DE LA LIBRERIA DEL TAD PILA


ESTÃ​TICA (TADPilaEst.h)

AUTORES:

Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

13
DESCRIPCIÓN: TAD pila o stack.

Estructura de datos que cumple:

Los elementos se añaden y se remueven por un solo extremo.

Este extremo es llamado “topeâ€​ de la pila.

OBSERVACIONES: Estructura de datos estática, ya que se

asigna una cantidad fija de memoria para dicha estructura,

antes de la ejecución del programa.

COMPILACIÓN PARA GENERAR EL CÓDIGO OBJETO:


gcc TADPilaEst.c -c

*/

//LIBRERAS

#include<stdio.h>

#include<stdlib.h>

#include "TADPilaEst.h"

14
//DEFINICIÓN DE FUNCIONES

/*

void Initialize(pila *s);

Descripción: Inicializar pila (Iniciar una pila para su uso)

Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella,

si esto no ha pasado se ocasionara un error.

*/

void Initialize(pila *s)

(*s).tope=-1; //s->tope=-1;

return;

15
/*

void Push(pila *s, elemento e);

Descripción: Empilar (Introducir un elemento a la pila)

Recibe: pila *s (Referencia a la pila "s" a operar), elemento e


(Elemento a introducir en la pila)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

Ademas no se valida el indice del arreglo (tope) esta fuera del


arreglo es decir hay desbordamiento

y se causará en error.

*/

void Push(pila *s, elemento e)

s->tope++;

//Si el tope alcanzo a MAX_ELEMENT, ya no hay más


espacio para elementos en el arreglo

16
if(s->tope==MAX_ELEMENT)

printf("\nERROR: PUSH(*S, E)
DESBORDAMIENTO, NO MÃ​S ESPACIO EN LA PILA");

exit(1);

//Insertar el elemento si no hubo error

s->arreglo[s->tope]=e;

return;

/*

elemento Pop(pila *s);

Descripción: Desempilar (Extraer un elemento de la pila)

Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve: elemento (Elemento e extraido de la pila)

17
Observaciones: El usuario a creado una pila y s tiene la
referencia a ella, s ya ha sido inicializada.

Ademas no se valida si la pila esta vacia (tope == -1) antes de


desempilar (causa error desempilar si esta esta vacÃ​a)

*/

elemento Pop (pila *s)

elemento r;

//Si el tope es -1, se intenta Pop de pila vacia

if(s->tope==-1)

printf("\nERROR POP(*S):
SUBDESBORDAMIENTO, NO HAY ELEMENTOS EN LA
PILA");

exit(1);

//Si no hubo error retornar el elemento indexado por tope

18
r=s->arreglo[s->tope];

s->tope--;

return r;

/*

boolean Empy(pila *s);

Descripción: //Vacia (Preguntar si la pila esta vacia)

Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve: boolean (TRUE o FALSE según sea el caso)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

*/

boolean Empty(pila *s)

boolean r;

if(s->tope==-1)

19
{

r= TRUE;

else

r= FALSE;

return r;

/*

elemento Top(pila *s);

Descripción: Tope (Obtener el "elemento" del tope de la pila si


extraerlo de la pila)

Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve: elemento (Elemento del tope de la pila)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

20
Ademas no se valida si la pila esta vacia antes de consultar al
elemento del tope (causa error si esta esta vacÃ​a).

*/

elemento Top(pila *s)

//Si el tope es -1, se intenta Pop de pila vacia

if(s->tope==-1)

printf("\nERROR TOP(*S):
SUBDESBORDAMIENTO, NO HAY ELEMENTOS EN LA
PILA");

exit(1);

//Si no hubo error retornar el elemento indexado por tope

return s->arreglo[s->tope];

21
/*

int Size(pila *s);

Descripción: Tamaño de la pila (Obtener el número de


elementos en la pila)

Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve: int (Tamaño de la pila -1->Vacia, 1->1 elemento,


2->2 elementos, ...)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

*/

int Size(pila *s)

return s->tope+1;

/*

void Destroy(pila *s);

Descripción: Elimina pila (Borra a todos los elementos en a la


pila de memoria* Memoria estática (No se puede eleminar
realmente)
22
Recibe: pila *s (Referencia a la pila "s" a operar)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella.

*/

void Destroy(pila *s)

//s->tope=-1;

Initialize(s);

return;

- TADPilaDin.h

/*

LIBRERIA: Cabecera del TAD PILA ESTÃ​TICA

AUTORES:

23
Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

DESCRIPCIÓN: TAD pila o stack.

Estructura de datos que cumple:

Los elementos se añaden y se remueven por un solo extremo.

Este extremo es llamado “topeâ€​ de la pila.

OBSERVACIONES: Estructura de datos estática, ya que se

asigna una cantidad fija de memoria para dicha estructura,

antes de la ejecución del programa.

*/

24
//DEFINICIONES DE CONSTANTES

#define TRUE 1

#define FALSE 0

//DEFINICIONES DE TIPOS DE DATO

//Definir un boolean (Se modela con un "char")

typedef unsigned char boolean;

//Definir un elemento (Se modela con una estructura "elemento")

typedef struct elemento

char c;

}elemento;

//Definir un nodo que será utilizado para almacenar una posición

25
de la pila (Nodo), lo que incluira a un elemento y a un apuntador
al siguiente nodo

typedef struct nodo

//Elemento a almacenar en cada nodo de la pila

elemento e;

//Apuntador al elemento de debajo (Requerido por ser una


implementación dinámica -Usuario: No modificar)

struct nodo *abajo;

}nodo;

//Definir una pila (Se modela con una estructura que unicamente
incluye un puntero a "elemento")

typedef struct pila

nodo *tope;

}pila;

//DECLARACIÓN DE FUNCIONES

26
void Initialize(pila *s); //Inicializar pila
(Iniciar una pila para su uso)

void Push(pila *s, elemento e); //Empilar


(Introducir un elemento a la pila)

elemento Pop (pila *s); //Desempilar


(Extraer un elemento de la pila)

boolean Empty(pila *s); //Vacia


(Preguntar si la pila esta vacia)

elemento Top(pila *s); //Tope


(Obtener el "elemento" del tope de la pila si extraerlo de la pila)

int Size(pila *s); //Tamaño de


la pila (Obtener el número de elementos en la pila)

void Destroy(pila *s); //Elimina pila


(Borra a todos los elementos y a la pila de memoria)

- TADPilaDin.c

/*

IMPLEMENTACIÓN DE LA LIBRERIA DEL TAD PILA


DINAMICA (TADPilaDin.h)

AUTORES:

27
Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

DESCRIPCIÓN: TAD pila o stack.

Estructura de datos que cumple:

Los elementos se añaden y se remueven por un solo extremo.

Este extremo es llamado “topeâ€​ de la pila.

OBSERVACIONES: Estructura de datos estática, ya que se

asigna una cantidad fija de memoria para dicha estructura,

antes de la ejecución del programa.

28
COMPILACIÓN PARA GENERAR EL CÓDIGO OBJETO:
gcc TADPilaEst.c -c

*/

//LIBRERAS

#include <stdio.h>

#include <stdlib.h>

#include "TADPilaDin.h"

//DEFINICIÓN DE FUNCIONES

/*

void Initialize(pila *s);

Descripción: Inicializar pila (Iniciar una pila para su uso)

Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella,

29
si esto no ha pasado se ocasionara un error.

*/

void Initialize(pila *s)

s->tope=NULL; //(*s).tope=NULL;

return;

/*

void Push(pila *s, elemento e);

Descripción: Empilar (Introducir un elemento a la pila)

Recibe: int *s (Referencia a la pila "s" a operar), elemento e


(Elemento a introducir en la pila)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

Ademas no se valida si el malloc() pudo o no apartar memoria, se


idealiza que siempre funciona bien

30
y no se acaba la memoria

*/

void Push(pila *s, elemento e)

nodo *aux;

aux=malloc(sizeof(nodo));

//Si no hay más memoria dinámica por alguna razón

if(aux==NULL)

printf("\nERROR-Push(&s,e): Desbordamiento de
la pila, no hay más memoria disponible");

exit(1);

//Si se creo el nuevo nodo insertar al elemento

(*aux).e=e; //aux->e=e;

31
aux->abajo=s->tope;

s->tope=aux;

return;

/*

void Pop(pila *s);

Descripción: Desempilar (Extraer un elemento de la pila)

Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve: elemento (Elemento e extraido de la pila)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

Ademas no se valida si la pila esta vacia antes de desempilar


(causa error desempilar si esta esta vacía),

tampoco se valida si free() pudo o no liberar la memoria, se


idealiza que siempre funciona bien

*/

32
elemento Pop (pila *s)

elemento r;

nodo *aux;

//Si el tope es NULL, se intenta Pop de pila vacia

if(s->tope==NULL)

printf("\nERROR-e=Pop(&s): Subdesbordamiento
de la pila, no hay elementos en la pila");

exit(1);

r=s->tope->e;

aux=s->tope;

s->tope=s->tope->abajo;

free(aux);

33
return r;

/*

boolean Empty(pila *s);

Descripción: //Vacia (Preguntar si la pila esta vacia)

Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve: boolean (TRUE o FALSE según sea el caso)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

*/

boolean Empty(pila *s)

boolean r;

if(s->tope==NULL)

r=TRUE;

34
}

else

r=FALSE;

return r;

/*

elemento Top(pila *s);

Descripción: Tope (Obtener el "elemento" del tope de la pila si


extraerlo de la pila)

Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve: elemento (Elemento del tope de la pila)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

Ademas no se valida si la pila esta vacia antes de consultar al


elemnto del tope (causa error si esta esta vacía).

35
*/

elemento Top(pila *s)

//Si el tope es NULL, se intenta Top de pla vacia

if(s->tope==NULL)

printf("\nERROR-e=Top(&s):
Subdesbordamiento de la pila, no hay elementos en la pila");

exit(1);

return s->tope->e;

/*

int Size(pila *s);

Descripción: Tamaño de la pila (Obtener el número de elementos


en la pila)

36
Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve: int (Tamaño de la pila 0->Vacia, 1->1 elemento, 2->2


elementos, ...)

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

*/

int Size(pila *s)

nodo *aux;

int tam_pila=0;

aux=s->tope;

if(aux!=NULL)

tam_pila++;

while(aux->abajo!=NULL)

tam_pila++;

aux=aux->abajo;

37
}

return tam_pila;

/*

void Destroy(pila *s);

Descripción: Elimina pila (Borra a todos los elementos en a la


pila de memoria)

Recibe: int *s (Referencia a la pila "s" a operar)

Devuelve:

Observaciones: El usuario a creado una pila y s tiene la


referencia a ella, s ya ha sido inicializada.

*/

void Destroy(pila *s)

nodo *aux;

if(s->tope!=NULL)

38
{

while(s->tope!=NULL)

aux=s->tope->abajo;

free(s->tope);

s->tope=aux;

return;

- Biblioteca.h

/*

//NUEVO PUSH

LIBRERIA: Cabecera de la Biblioteca de funciones específicas


para la Practica

39
AUTORES:

Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

DESCRIPCIÓN: Herramientas usadas en el programa.

Lista de funciones:

Cada una de las funciones que aquí se declaran, cumplen un


objetivo

especifico en la implemetnacion, para poder llevar a cabo


operaciones

separadas de manera correcta.

OBSERVACIONES: Esta libreria utiliza a TADPila Est o Din, y


es la presente,

40
que se importa en el archivo principal.

*/

#include "TADPilaEst.h"

#define TAM 100

#define TAM_CADENA_LITERALES 55

#define LIM_INFERIOR 65

#define LIM_SUPERIOR 90

//Muestra el menu para que el usuario interactua con el programa

void Menu();

/*

Validacion de parentesis:

Recibe una cadena y devuelve TRUE si los parentesis

son correctos, y FALSE si no lo son.

41
*/

boolean Validar_Parentesis(char *cad);

/*

Correcion de la expresion ingresada:

Recibe la cadena que acaba de entrar el usuario,

no devuelve valor, pero modifica la cadena a una nueva que sea


entrada.

*/

void Corregir_Expresion(char *cad); //simon, tú eres el que


hace el push, yo sólo edito XD

//ve comentando el codigo y


arreglandolo, ahorita que acabe el algoritmo, corregimos el error

/*

Convertir la Expresion de infija a posfija:

Recibe...

-la direccion de cadena que se quiere convertir.

-la variable que verifica si esta validada la expresion dada.

42
-la direccion de la cadena donde se escribira la conversion de
infija a posfija.

Devuelve...

-Nada.

*/

boolean Pasar_Posfijo(char *cad, boolean v, char *cad_posfija);

/*

Recibe la cadena postfija y devuelve el valor de

la evaluación.

Primero pide los valores de las literales por medio de


Obtener_Valores.

*/

//float Evaluar_Expresion(char *cad_posfija);

/*

Recibe los dos valores desempilados a operador,

y su respectivo operador, para devolver su valor

43
y regresarlo a la pila posteriorente en Evaluar_Expresion.

*/

void Obtener_Valores();

void No_Repite(char* cadena,int tam,char* resultado);

/*

Elimina el contenido de todos los arreglos usados a lo largo del


programa,

para poder analizar una nueva expresiónd e manera correcta.

*/

//void Vaciar_Arreglos(char *cad, char *cad_posfija, char


*literalesDeExpresion, int *valoresDeLiterales, char
*auxiliarAntiRepeticion);

void Evaluar_Expresion(char *cad_posfija, float*


valoresDeLiterales);

44
- Biblioteca.c

/*

//NUEVO PUSH

IMPLEMENTACION: Implemetación de la Biblioteca de


funciones especificas

AUTORES:

Ayona Lopez Eugenio Milton

BenÃ​tez Morales Manuel Emilio

Tellez Perez Juan Manuel

Febrero 2019

VERSIÓN: 1.0

DESCRIPCIÓN: Herramientas usadas en el programa.

Lista de funciones:

45
Cada una de las funciones que aquí se declaran, cumplen un
objetivo

especifico en la implemetnacion, para poder llevar a cabo


operaciones

separadas de manera correcta.

OBSERVACIONES: Esta libreria utiliza a TADPila Est o Din, y


es la presente,

que se importa en el archivo principal.

COMPILACIÓN PARA GENERAR EL CÓDIGO OBJETO:


gcc Biblioteca.c -c

*/

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include<math.h>

#include "Biblioteca.h"

46
void Menu()

printf("\n1.Corregir expresion");

printf("\n2.Validar Parentesis.");

printf("\n3.Pasar a Posfija.");

printf("\n4.Evaluar expresion");

printf("\n5.Salir\n");

return;

/*

Recibe una expresion y devuelve un boolean

47
Efecto: La cadena que ingresamos puede o no estar correcta,
comprueba eso y

regresa TRUE si lo esta de lo contrario FALSE

*/

boolean Validar_Parentesis(char *cad)

boolean validado;

int i=0; //controla el paso por la cadena

int tamCadena=0; // Guarda el tamañano de la cadena

pila pila_parentesis; //Guarda los parentesis ya que solo nos


importan, por el momento

elemento elm; // Guarda el tipo de dato deseado

Initialize(&pila_parentesis);

tamCadena= strlen(cad);

48
for(i=0; i<=tamCadena; i++) //recorre la cadena

if(cad[i]=='(')//Ingresa en la Pila si es (

elm.c='(';

Push(&pila_parentesis, elm);

else

if(cad[i]==')') // Si detecta un parentesis cerrado no lo


guarda, hace pop y saca al de la ultima posicion

if(Empty(&pila_parentesis)) //si esta vacia cumple y salta


todo los pasos hasta

validado=FALSE;//¿Para que guardas si al momento de


combrobrobar que esta vacia lo cambias a TRUE?

goto regresar; //puesto para poder salir del if, y tome el valor
TRUE al seguri a la condicion final

49
}

else

Pop(&pila_parentesis);

regresar: // correccion @Eugenio

if(Empty(&pila_parentesis))

validado=TRUE;

else

validado=FALSE;

//regresar: ¿porque la pusiste aqui?//jajajaa bambi XD MIRA

50
AQUI ERA EL ERROR, donde??

return validado;

/* Recibe una cadena

Efecto: Ingresa los primeros datos al comenzar el programa y


puede corregir

la cadena con la condicion que mande Validar_Parentesis()

Excepciones: Rango de ingreso: "A-Z" Y "()"

*/

void Corregir_Expresion(char *cad)

51
int i;

//Vaciar_Arreglos(&cad[0], &cad_posfija[0],
&literalesDeExpresion[0], &valoresDeLiterales,
&auxiliarAntiRepeticion[0]);

printf("\n\nEscriba la nueva expresion:\n");

scanf("%s", cad);

for(i=0;i<strlen(cad);++i){

if(cad[i]>=97 && cad[i]<=122)

printf("Has ingresado un caracter fuera del rango A-Z\n");

Corregir_Expresion(cad);

52
//printf("%s\n", cad);

return;

/*

Recibe la cadena ingresada, la condicion si es correcta o no,

y la cadena postfija- Referencia

Efecto: Si recibe un TRUE continua con la expresion y la


pasa a postfija

Excepciones: Al recibir un FALSE puede que no haya


validado al

principio

*/

boolean Pasar_Posfijo(char *cad, boolean v, char *cad_posfija)

53
pila pila_posfija; // Guarda cadena

elemento e; //Caracter actual

elemento aux_e; //

int i=0;

int aux=-1;

Initialize(&pila_posfija);

printf("\n");

if(!v) {

printf("\nParece que no has validado tu expresion...");

printf("Expresion postfija: " );

else

while(cad[i] != '\0')//Mientras no encuentre caracter nulo

e.c = cad[i];

54
switch(e.c){ //Caracter actual

/*

Si el primer operador detectado es + ó -

*/

case '-':

case '+':

if(Empty(&pila_posfija)) //si la pila esta


vacia ingresa el caracter actual de la cadena

Push(&pila_posfija,e);

else if(Top(&pila_posfija).c == '+' || Top(&pila_posfija).c


== '-')

/* Si tienen el caracter actual tiene la misma precedencia


que el tope de la pila

Saca el tope de la pila e ingresa el caracter actual

*/

55
++aux;

cad_posfija[aux] = Pop(&pila_posfija).c;

Push(&pila_posfija,e);

else if(Top(&pila_posfija).c == '*' || Top(&pila_posfija).c


== '/' || Top(&pila_posfija).c == '^')

/*Si el tope de la pila tiene mayor precedencia que el


caracter actual

*/

while(!Empty(&pila_posfija))//Mientras la pila no este


vacia saca elemetos de la pila

aux_e = Pop(&pila_posfija); // saca de la pila y


guarda el tope

if(aux_e.c != '(') //si el ultimo elemento no es igual


"(" guarda en la cadena_posfija

{
56
++aux;

cad_posfija[aux] = aux_e.c;

} else

break;

Push(&pila_posfija,e); /*ya que se han sacado los


elementos debajo del signo de mayor precedncia (pila vacia)

se coloca
el caracter actual de la cadena en la pila*/

else if(Top(&pila_posfija).c == '('){ // si la cadena actual


comienza con "(" guarda directamente

Push(&pila_posfija,e);

break;

57
/*

Si el primer operador detectado es * ó /

*/

case '*':

case '/':

if(Empty(&pila_posfija))

Push(&pila_posfija,e);

else if(Top(&pila_posfija).c == '*' ||


Top(&pila_posfija).c == '/') // caso misma precedencia

++aux;

cad_posfija[aux] = Pop(&pila_posfija).c;

Push(&pila_posfija,e);

58
else if(Top(&pila_posfija).c == '+' || Top(&pila_posfija).c
== '-') //caso precedencia mayor al caracter actual

Push(&pila_posfija,e);

else if(Top(&pila_posfija).c == '^') //caso de precedencia


menor al caracter actual

while(!Empty(&pila_posfija))

aux_e = Pop(&pila_posfija);

if(aux_e.c != '('){

++aux;

cad_posfija[aux] = aux_e.c;

}else

break;

Push(&pila_posfija,e);

59
}

else if(Top(&pila_posfija).c == '(')

Push(&pila_posfija,e);

break;

case '^':

Push(&pila_posfija,e);

break;

case ')'://caso cuando detecta que termino un parentesis

while(Empty(&pila_posfija)==FALSE) //Mientras la
pila no este vacia saca elemetos de la pila NO ES TRUE !NO
FUNCIONA

aux_e = Pop(&pila_posfija);// saca de la pila y guarda el

60
tope

if(aux_e.c != '('){ //si el ultimo elemento no es


igual "(" guarda en la cadena_posfija

++aux;

cad_posfija[aux] = aux_e.c;

}else

break;

break;

case '(': // Si detecta un parentesis "(" añade


directamente a la pila

Push(&pila_posfija,e);

break;

default: // A todos los demas caracteres los


encapsula y activan el default

++aux;

61
cad_posfija[aux] = e.c;

break;

i++;

while(!Empty(&pila_posfija))

aux_e = Pop(&pila_posfija);

if(aux_e.c != '('){

++aux;

cad_posfija[aux] = aux_e.c;

printf("Expresion postfija: %s",cad_posfija);

62
}

Destroy(&pila_posfija);

return TRUE;

void Obtener_Valores(char* cad,float* valoresDeLiterales, char*


auxiliarAntiRepeticion)

//controla el paso por la cadena

int i_aux=0; // controla la posicion de la variable

int o_aux=0; //

int j,k,l,m;

/*

63
Los siguientes 3 arreglos guardan las letras, sus valores, y sus
no repeticiones respectivamente,

la congruencia es que el valor en la posicion n de


valoresDeLiterales

corresponde a la letra en la misma posición en


literalesDeExpresion,

mientras que auxiliarAntiRepeticion guarda sólo una copia de


cada literal.

*/

//SE DEBE PONER 90 DEBIDO A QUE NUESTRO RANGO


SON LAS MAYUSCULAS

char literalesDeExpresion[90]="";

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

//Obtener las literales de la expresion

for(j=0; j<strlen(cad); j++)

if(cad[j]>=65 && cad[j]<=90)

{
64
literalesDeExpresion[i_aux]=cad[j];

++i_aux;

No_Repite(literalesDeExpresion,i_aux,auxiliarAntiRepeticion);

//pedir al ususario el valor de dichas literales

//COMO EL ARREGLO GUAR DIRECTAMENTE EN LA


POSICION QUE OCUPA EL CARACTER DEL CODIGO
ASCII DEBEMOS LIMITAR A NUESTRO ARREGLO
HASTA EL RANGO QUE QUEREMOS

for(k=0; k<strlen(auxiliarAntiRepeticion); k++)

printf("Valor de %2c: ", auxiliarAntiRepeticion[k]);

scanf("%f", &valoresDeLiterales[auxiliarAntiRepeticion[k]]);

printf("\n");

65
//estos for solo prueban que los valores sean congruentes

for(l=0; l<strlen(literalesDeExpresion); l++)

printf("%2c, ", literalesDeExpresion[l]);

printf("\n");

for(m=0; m<strlen(literalesDeExpresion); m++)

printf("%.1f, ", valoresDeLiterales[literalesDeExpresion[m]]);

printf("\n\n");

return;

66
//funcion que evita la repeticion

void No_Repite(char* cadena,int tam,char* resultado){

int j=0,k=0,inicio,i;

for(i=0;i<tam;++i){

if(i==0){

resultado[j]=cadena[i];

}else{

for(inicio=0;inicio<=j;++inicio){

if((cadena[i]!=resultado[inicio])){

++k;

67
}else {

k=0;

break;

if(k==j+1){

++j;

resultado[j]=cadena[i];

k=0;

68
void Evaluar_Expresion(char* cad_posfija, float*
valoresDeLiterales)

pila resultado;

elemento numero_conv;

elemento valorNP;

char float_cad[2]="";

char cadena_num[strlen(cad_posfija)+10];

int control_cn=0;

int i;

float n1;

float n2;

Initialize(&resultado);

printf("Pasos:\n");

for(i=0;i<strlen(cad_posfija);i++)

69
switch(cad_posfija[i]){

case '+':

n1= Pop(&resultado).valor;

n2= Pop(&resultado).valor;

printf("%.2f + %.2f\n",n2,n1);

valorNP.valor= n1+n2;

Push(&resultado,valorNP);

break;

case '-':

n1= Pop(&resultado).valor;

n2= Pop(&resultado).valor;

printf("%.2f - %.2f\n",n2,n1);

valorNP.valor= n2-n1;

Push(&resultado,valorNP);

70
break;

case '/':

n1= Pop(&resultado).valor;

n2= Pop(&resultado).valor;

printf("%.2f / %.2f\n",n2,n1);

valorNP.valor= n2/n1;

Push(&resultado,valorNP);

break;

case '*':

n1= Pop(&resultado).valor;

n2= Pop(&resultado).valor;

printf("%.2f * %.2f\n",n2,n1);

valorNP.valor= n1*n2;

71
Push(&resultado,valorNP);

break;

case '^':

n1= Pop(&resultado).valor;

n2= Pop(&resultado).valor;

printf("%.2f ^ %.2f\n",n2,n1);

valorNP.valor= pow(n2,n1);

Push(&resultado,valorNP);

break;

default:

numero_conv.valor=valoresDeLiterales[cad_posfija[i]];

Push(&resultado,numero_conv);

break;

72
}

printf("\nResultado de la expresion
%.2f\n",Top(&resultado).valor);

- main.c

/*

Forma de ejecución: gcc main.c TADPila(Est)(Din).c


Biblioteca.c -o archivo_ejecutable

*/

//EUGENIO CAMBIOS

#include <stdio.h>

#include "Biblioteca.h"

#include <stdlib.h>

#include <math.h>

73
//main

int main()

int j;

int opc; //opcion del menu

char cad[TAM]; // guarda la expresion

char cad_posfija[TAM]=""; // guarda la expresion postfija

boolean v=FALSE,posv=FALSE;

float valoresDeLiterales[90];

char auxiliarAntiRepeticion[90]="";

printf("BIENVENIDO...\nPráctica sobre el TAD Pila.\nEl


programa recibe una expresión en literales, y los valores de las
mismas,\nfinalmente se obtiene el valor de la evaluación.\n");

Corregir_Expresion(cad);

Menu();

do

74
printf("\nExpresion: %s",cad);

printf("\nSelecciona opcion\n");

scanf("%d", &opc);

if(opc>0 && opc<5) //LIMITA EL INGRESO

switch(opc)

case 1:

system("cls");

Menu();

Corregir_Expresion(cad);

break;

case 2:

v = Validar_Parentesis(cad);

if(v){

system("cls");

Menu();

75
printf("\nParentesis validos, continua...\n");

else

system("cls");

Menu();

printf("\nParentesis invalidos, corrigelo...\n");

Corregir_Expresion(cad);

break;

case 3:

//system("cls");

Menu();

for(j=0;j<TAM;++j)//ESTO CAUSABA

76
EL ERROR DE LIMPIEZA DE LA CADENA POSTFIJA

cad_posfija[j]=0;

posv= Pasar_Posfijo(cad, v, cad_posfija);

break;

case 4:

if(v){

if(posv){

for(j=0;j<90;++j)//ESTO
CAUSABA EL ERROR DE LIMPIEZA DE REPETICION DE
ELEMENTOS

auxiliarAntiRepeticion[j]=0;

Obtener_Valores(cad,valoresDeLiterales,auxiliarAntiRepeticion)
;

printf("Cadena Postfija: %s\n",cad_posfija);

Evaluar_Expresion(cad_posfija,valoresDeLiterales);

77
}

else

printf("No ha pasado por la postfija");

}else{

system("cls");

printf("\nParece que no has


validado tu expresion...");

Menu();

break;

}else

printf("Ingrese del 1-5\n");

} while (opc<5);

return 0;

78
}

• Bibliografía (En formato IEEE)


[1] E. Martinez, "Web personal de Edgardo Adrián Franco Martínez", Eafranco.com, 2019.
[Online]. Available: http://www.eafranco.com/?p=docencia/estructurasdedatos/index.htm.
[Accessed: 12- Mar- 2019].

79

S-ar putea să vă placă și