You are on page 1of 20

PROYECTO FINAL

PROGRAMACION.

UNIVERSIDAD MARIANO GALVES DE CHIMALTENANGO


INGENIERIA EN SISTEMAS
PROGRAMACION
ING. ALFREDO OCHOA

PROYECTO FINAL, MANUAL TECNICO

GEISER LIZARDO TOASPERN GAITAN


1990-10-11801
JOSUE MISAEL BUCH CHIROY
1990-10-14621

INTRODUCCION:

Este manual ha sido creado con el fin de ayudar al tcnico programador para poder realizar
el mantenimiento necesario y/o modificacin del cdigo fuente , en el cual se especifican
algunas de las funciones utilizadas en el programa y para que sirven, la funcion principal del
proyecto es leer un archivo de texto contenedor de expreciones aritmeticas las cuales son leidas y
resueltas atravez de procedimientos que tienen como base la utilizacion de pilas y colas asi como
la creacion de nuestras propias librerias.

CREANDO LA LIBRERA COLA.H


----------------------------------------------------------------------------------------------------------------------------------La creacion de esta librera nos sirve para poder reservar la memoria a utilizar para cada valor
agregado a la pila
/* Ejemplo de una cola. */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <alloc.h>
#include "data.h"
//nuevonodo: reserva memoria para un nuevo nodo
struct nodo *nuevonodocola()
{
struct nodo *p;
p=(struct nodo *)malloc(sizeof(struct nodo));
if(p==NULL)
{
printf("Memoria RAM Llena");
getch();
exit(0);
}
return p;
}
//push: agrega un elemento en la parte superior de la pila
void insertar(struct queue &cola, struct elemento x)
{
struct nodo *p;
p=nuevonodocola();
(*p).dato=x;
(*p).siguiente=NULL;
if (cola.fin == NULL)
{
cola.fin=cola.ini=p;
}
else
{
(*cola.fin).siguiente=p;
cola.fin=p;
}
}
//pop: extrae el elemento superior de la pila
struct nodo *extraer(struct queue &cola)
{
struct nodo *p;
if (cola.ini == NULL)

return NULL;
p = cola.ini;
cola.ini = (*cola.ini).siguiente;
return p;
}
----------------------------------------------------------------------------------------------------------------------------------Lo que hace esta funcion es posicionar el apuntador en la posicion siguiente de la pila y liberar la
posicion en donde se encuentra el apuntador
void liberar(struct queue &cola)
{
struct nodo *p;
while (cola.ini != NULL)
{
p = cola.ini;
cola.ini = (*cola.ini).siguiente;
free(p);
}
cola.ini = NULL;
cola.fin = NULL;
}

CREANDO LA LIBRERA SCAN.H


----------------------------------------------------------------------------------------------------------------------------------Se declaran las libreras necesarias para la creacin de la nueva librera scan.h
//unidad scan.h
/*unidades standar incluidas*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/*constantes*/
----------------------------------------------------------------------------------------------------------------------------------Se definen las variables constantes a utilizar para nuestro escaner y saber exactamente si el
archive contiene datos o expresiones aritmticas para resolver.
#define false
0
#define true
1
#define E_identificador 2 /*estado identificador*/
#define E_num
3 //estado numerico
#define E_mas
4 // estado signo "+"
#define E_min
5 // estado signo "-"
#define E_por
6 // estado signo "*"
#define E_div
7 // estado "/"
#define E_puncoma
8 // estado ";"
#define E_corcheteA
9 // estado "["
#define E_corcheteC
10 // estado "]"
#define E_parA
11 // estado "("
#define E_parC
12 // estado ")"
#define E_FinArchivo 13 // estado fin archivo
#define E_ascii
14 // estado cualquier ascii
#define E_inicial
15 // estado inicial
#define E_texto
16 // texto
#define E_salto
17 // estado "salto de linea"
#define E_com
25 // estado "\""
----------------------------------------------------------------------------------------------------------------------------------Se utiliza token para saber exactamente si el digito ledo por el scanner es un numero
// Mis tokens
//INSTRUCCIONES EN UN ARCHIVO DE ENTRADA
#define E_crear_categoria 101
struct lexico
{
char C_lex[150];
int atrib;
};
/*Estructura para guardar las Palabras Rervadas*/
struct Reservadas
{

char reservada[35]; /*nombre de la reservada*/


int codigo;
/*codigo*/
};
int Fin=false;
int numlinea = 1 ; /*Numero de Linea del Archivo*/
struct Reservadas Rec_Res[20]={
{"CREAR_CATEGORIA",101},
};
/*variables globales del programa*/
char lexema[150]; // Guarda el componente lexico
char letra[2];
int salir; // Bandera de Lectura
char token; // Caracter ledo desde el teclado
----------------------------------------------------------------------------------------------------------------------------------Declaramos las variables tipo FILE para poder leer el archivo de texto y poder guardarlo
FILE *file_in; // Archivo de entrada
FILE *file_out;
int estado; // Estado actual del scaner
char pala[13];
char codigo[15];
/* imprime error en el archivo de prueba*/
void error(char *lex)
{
fprintf(file_out,"ERROR EN LA LINEA # = %d\n",numlinea);
fprintf(file_out,"VERIFIQUE EL INGRESO: %s\n",lex);
exit(0);
}
----------------------------------------------------------------------------------------------------------------------------------Utilizamos esta funcion para para saber si el carcter ledo es un numero o un operador
void ReturnFile2()
{
ungetc(token,file_in); //retrocede un caracter en el archivo de entrada
if (token=='\n')
numlinea--; // decrementar lnea leida
}
/* estado letra del scanner*/
void Identificador()
{
if(isalpha(token) || isdigit(token) || token=='_'|| token=='-')
estado=E_identificador;
else {
ReturnFile2();

salir=true;
lexema[strlen(lexema)-1]='\0';
}
}
----------------------------------------------------------------------------------------------------------------------------------Validamos la apertura del archivo de entrada a leer, si es NULL nos mostrara: Error al abrir
archivo!! archivo no existe!! , de lo contrario el programa se ejecutara
/*abre el archivo de entrada*/
int abre_arch(char nombre[40])
{
file_in = fopen(nombre,"r");
if(file_in == NULL)
{
// gotoxy(17,9);
printf("Error al abrir archivo!! archivo no existe!!
// gotoxy(17,10);
printf(" ***Presione <ENTER> para salir*** \n\r");
return 0;
}
else
return(1);
}

\n\r");

int File_Out(char nombre[40])


{
char nom[20];
file_out = fopen(nombre,"a+");
if (file_out == NULL)
{
return 0;
}
else
return(1);
}
----------------------------------------------------------------------------------------------------------------------------------Leemos un carcter del archivo de entrada
void lee_car()
{
token=getc(file_in);
// if (token == 255)
//
strcpy(lexema,"caracter 255");
if (token=='\n')
numlinea++;
}

----------------------------------------------------------------------------------------------------------------------------------Reinserta el Lexema en el archivo de entrada


void ReturnfileLexema()
{
int i=(strlen(lexema)-1);
while (i>=0)
{
token=lexema[i];
i--;
ReturnFile2();
}//while
}
/*estado inicial del scanner*/
void Inicial()
{
if((token==' ')||(token=='\t'))
lexema[strlen(lexema)-1]='\0';
else if(isalpha(token))
estado=E_identificador;
else if(isdigit(token))
estado=E_num;
else if(token=='+')
estado=E_mas;
else if(token=='-')
estado=E_min;
else if(token=='*')
estado=E_por;
else if(token=='/')
estado=E_div;
else if(token=='(')
estado=E_parA;
else if(token==')')
estado=E_parC;
else if(token=='\n')
estado=E_salto;
else if (token == '[')
estado = E_corcheteA;
else if (token == ']')
estado = E_corcheteC;
else if (token==EOF)
estado=E_FinArchivo;
else
{
estado=E_ascii;
salir=true;
}//else
}

/*estado Numero*/
----------------------------------------------------------------------------------------------------------------------------------Cuando el programa contiene un numero, busca el siguiente digito
void numero()
{
if (isdigit(token)) // Busca el siguiente digito
estado= E_num;
else
{
if((token==' ')||(token=='\t')) //fin de linea
lexema[strlen(lexema)-1]='\0';
else
{
ReturnFile2(); // siguiente lexema
salir=true;
lexema[strlen(lexema)-1]='\0';
}
}
}
/* estado punto */
int abre_archivo(char *nom1)
{
file_in=fopen(nom1,"r");
if (file_in!=NULL) return true;
else return false;
};
/* identifica las reservadas*/
int identifica_reservada()
{
char lexema2[150];
strcpy(lexema2,lexema);
int i=0;
for (i=0;i<strlen(lexema);i++)
lexema2[i]=toupper(lexema2[i]); // Convierte a mayusculas el ID //
i=0;
while (i < 21)
{
if (strcmp(Rec_Res[i].reservada,lexema2)==0)
{
strcpy(lexema,lexema2);
estado = Rec_Res[i].codigo;
i = 21;
}
else
i++;

};
return estado;
};
----------------------------------------------------------------------------------------------------------------------------------/*funcion principal que devuelve el token*/
lexico Token(int tipo)
{
lexico RegLex; // devuelve el componente lexico y el atributo //
estado =E_inicial;
strcpy(lexema,"");
strcpy(letra," ");
Fin = false;
salir=false;
while (!salir && token!=EOF)
{
lee_car();
letra[0]=token;
letra[1] = 0;
strcat(lexema,letra);
switch (estado){
case E_inicial :
Inicial(); break;
case E_identificador : Identificador();
break;
case E_num:
numero();
break;
default:
salir=true;
lexema[strlen(lexema)-1]='\0';
ReturnFile2();
break;
}//switch
}//while
if (token == EOF)
Fin=true;
if(estado == E_identificador && strlen(lexema) > 35)
estado = E_texto;
if (estado == E_identificador && tipo == 1)
estado =identifica_reservada();
strcpy(RegLex.C_lex,lexema);
RegLex.atrib = estado;
return RegLex;
}
void cerrar_archivo()
{
fclose(file_in);
}
void cerrararch()
{
fclose(file_out);
}

CREANDO LA LIBRERA DATA.H


----------------------------------------------------------------------------------------------------------------------------------Creamos la libreria data.h para poder saber que operador se encuentra dentro de la expresion
para luego trabajarlo segun su orden gerarquico
#ifndef _DATA_H
#define _DATA_H
#define E_NUM
#define E_MAS
#define E_MIN
#define E_POR
#define E_DIV
#define E_PARA
#define E_PARC

1 // estado numerico
2 // estado signo "+"
3 // estado signo "-"
4 // estado signo "*"
5 // estado signo "/"
6 // estado signo "("
7 // estado signo ")"

#define E_OPERANDO
#define E_OPERADOR
#define E_UNDEF

10 // define un operando
11 // define un operador
-1

struct elemento
{
int tipo;
int valor;
int precedencia;
double real;
};
struct nodo
{
struct elemento dato;
struct nodo *anterior;
struct nodo *siguiente;
};
struct queue
{
struct nodo *ini;
struct nodo *fin;
};
struct stack
{
struct nodo *top;
};
#endif

PROGRAMA PRINCIPAL
----------------------------------------------------------------------------------------------------------------------------------Declaramos las librerias necesarias para la utilizacion del programa incluyendo las librerias creadas
anteriormente
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
#include "data.h"
#include "cola.h"
#include "pila.h"
#include "scanner.cpp"
----------------------------------------------------------------------------------------------------------------------------------Declaracin de funciones a utilizar
void leer_archivo(char nombre_archivo[40]);
struct queue convertir(struct queue &lista);
float evaluar(struct queue &lista);
void mostrar(struct queue &lista);
/* fin de la delcaracin de funciones*/
----------------------------------------------------------------------------------------------------------------------------------Iniciamos nuestro programa principal
void main()
{
char nom[40];
int opc;
textcolor(LIGHTRED);
gotoxy(33,4);cprintf("INSTRUCCIONES DE USO:" );
gotoxy(10,6);cprintf("1. Al leer el archivo con las expresiones aritmeticas, asegurarse");
gotoxy(10,7);cprintf(" de, presionar la tecla ENTER al final de la expresion ya que ");
gotoxy(10,8);cprintf(" si no se hace esto, el programa no reconocera ninguna ");
gotoxy(10,9);cprintf(" expresion, y por lo tanto se cerrara automaticamente
");
gotoxy(10,12);cprintf("2. La expresion debe estar bien escrita, si tiene algun error ");
gotoxy(10,13);cprintf(" no sera reconocida por el programa");
gotoxy(10,15);cprintf("Presione cualquier tecla para continuar...");
----------------------------------------------------------------------------------------------------------------------------------Creamos el menu principal de nuestro programa
getch();
do{
clrscr();
textcolor(LIGHTBLUE);
gotoxy(20,5);cprintf("UNIVERSIDAD MARIANO GALVEZ DE CHIMALTENANGO" );
gotoxy(30,6);cprintf("INGENIERIA EN SISTEMAS ");
gotoxy(40,11);cprintf("MENU: ");
gotoxy(35,12);cprintf("1. Leer archivo ");
gotoxy(35,13); cprintf("2. Instrucciones ");
gotoxy(35,14);cprintf("3. Salir ");
gotoxy(35,15);cprintf("OPCION: ");

cin>>opc;
----------------------------------------------------------------------------------------------------------------------------------Creamos un switch para poder elegir opcion a realizar en nuestro programa
switch (opc)
{
case 1:
clrscr();
//gotoxy(5, 5);
textcolor(LIGHTMAGENTA);
gotoxy(1,1);cprintf("Ingrese el nombre y direccion del archivo: ");
scanf("%s",nom);
//leemos el archivo de entrada
leer_archivo(nom);
break;
case 2:
clrscr();
textcolor(WHITE);
gotoxy(33,4);cprintf("INSTRUCCIONES DE USO:" );
gotoxy(10,6);cprintf("1. Al leer el archivo con las expresiones aritmeticas, asegurarse");
gotoxy(10,7);cprintf(" de, presionar la tecla ENTER al final de la expresion ya que ");
gotoxy(10,8);cprintf(" si no se hace esto, el programa no reconocera ninguna ");
gotoxy(10,9);cprintf(" expresion, y por lo tanto se cerrara automaticamente
");
gotoxy(10,12);cprintf("2. La expresion debe estar bien escrita, si tiene algun error ");
gotoxy(10,13);cprintf(" no sera reconocida por el programa");
gotoxy(10,15);cprintf("Presione cualquier tecla para continuar...");
getch();
break;
case 3:
clrscr();
textcolor(LIGHTBLUE);
gotoxy(20,5);cprintf("UNIVERSIDAD MARIANO GALVEZ DE CHIMALTENANGO" );
gotoxy(30,6);cprintf("INGENIERIA EN SISTEMAS ");
textcolor(YELLOW);
gotoxy(50,18);cprintf("CREADO POR:");
gotoxy(50,19);cprintf("\nGEISER TOASPERN 1990-10-11801");
gotoxy(50,20);cprintf("\nJOSUE BUCH 1990-10-14621");
getch();
break;
}
}while(opc!=3);
}
----------------------------------------------------------------------------------------------------------------------------------DEFINICION DE FUNCIONES
//leer_archivo: se encarga de leer el archivo de entrada
void leer_archivo(char nombre_archivo[40])
{
//variables locales
float val;

char str[50];
str[0]='\0';
//estructuras
struct lexico lex;
struct queue lista;
struct elemento dat;
//punteros
FILE *salida;
//inicializaciones
lista.ini = NULL;
lista.fin = NULL;
----------------------------------------------------------------------------------------------------------------------------------Abrimos el archivo de salida
salida = fopen("C:\\bc5\\salida.txt", "w");
if (abre_arch(nombre_archivo) == NULL)
{
gotoxy(5, 15);
printf("Error al crear archivo de salida ");
}
else{
textcolor(LIGHTBLUE);
gotoxy(5,15);
clrscr();
cprintf("Archivo creado exitosamente ");
gotoxy(5, 16);
cprintf("Revisar en C:\\bc5\\salida.txt");
gotoxy(5, 17);
cprintf("Presione cualquier tecla para regresar al menu ");
getch();
}
do{
lex=Token(1);
//si llegamos a un salto de linea evaluamos
if (lex.atrib == E_salto)
{
lista = convertir(lista);
val = evaluar(lista);
fprintf(salida, "%s = %0.2f\n", str, val);
liberar(lista);
str[0] ='\0';
}
else
{
if (lex.atrib == E_num)

{
dat.tipo = E_OPERANDO;
dat.valor = atoi(lex.C_lex);
dat.precedencia = 6;
}
else
{
dat.tipo = E_OPERADOR;
dat.valor = lex.atrib;
switch(lex.atrib)
{
case E_mas:
case E_min:
dat.precedencia = 1;
break;
case E_por:
case E_div:
dat.precedencia = 2;
break;
case E_parA:
case E_corcheteA:
dat.precedencia = 5;
dat.valor = E_parA;
break;
case E_parC:
case E_corcheteC:
dat.precedencia = E_UNDEF;
dat.valor = E_parC;
break;
}
}
//agregamos los datos leidos a una lista
insertar(lista, dat);
strcat(str, lex.C_lex);
}

} while(lex.atrib != E_inicial);
//finalizacin del proceso
fclose(salida);
}
----------------------------------------------------------------------------------------------------------------------------------Conververtirmos una expresin infija a postfija, para el manejo de los operadores por gerarquia
struct queue convertir(struct queue &lista)
{

struct queue nueva;


nueva.ini = NULL;
nueva.fin = NULL;
//1. inicializamos la pila
struct stack pila;
pila.top = NULL;
struct nodo *node = NULL;
struct nodo *aux;
//2. repetir hasta que ya no hayan datos de entrada
while (lista.ini != NULL)
{
//2.1 leer un caracter de la exresin
if (node == NULL)
node = extraer(lista);
//2.2 si es un operando se pasa a la nueva expresin POSTFIJA
if ((*node).dato.tipo == E_OPERANDO)
{
(*node).dato.real = (*node).dato.valor;
insertar(nueva, (*node).dato);
free(node);
node = NULL;
}
else
{
//2.3 si es un operador distinto de ")"
if ((*node).dato.valor != E_parC)
{
//2.3.1 si la pila esta vacia el operador se mete a la pila
if (pila.top == NULL)
{
//cambiamos el valor de presedencia de "(" en la pila
if ((*node).dato.valor == E_parA)
(*node).dato.precedencia = 0;
push(pila, (*node).dato);
free(node);
node = NULL;
}//2.3.2 si la pila no esta vacia
else
{
//si la prioridad del operador es mayor que la prioridad
//del operador en la cima de la pila se mete en la pila
aux = pop(pila);

if ((*node).dato.precedencia > (*aux).dato.precedencia)


{
//cambiamos el valor de presedencia de "(" en la pila
if ((*node).dato.valor == E_parA)
(*node).dato.precedencia = 0;
//hacemos un doble push por haber extraido un dato
//previamente de la pila
push(pila, (*aux).dato);
push(pila, (*node).dato);
free(node);
node = NULL;
}
else
{
insertar(nueva, (*aux).dato);
free(aux);
}
}
}
//2.4 si el elemento es el operador ")" entonces
else
{
//se sacan operadores de la pila hsata encontrar "("
aux = pop(pila);
while ((aux != NULL) && ((*aux).dato.valor != E_parA))
{
insertar(nueva, (*aux).dato);
free(aux);
aux = pop(pila);
}
free(aux);
free(node);
node = NULL;
}
}
}
//3. pasamos el resto del contenido de la pila a la expresin postfija
aux = pop(pila);
while (aux != NULL)
{
insertar(nueva, (*aux).dato);
free(aux);
aux = pop(pila);
}

return nueva;
}
//evaluar: evalua una expresin postfija y devuelve su valor
float evaluar(struct queue &lista)
{
//1. inicializamos la pila
struct stack pila;
pila.top = NULL;
struct nodo *node = NULL;
struct nodo *aux1;
struct nodo *aux2;

//2. repetir hasta que ya no hayan datos de entrada


while (lista.ini != NULL)
{
//2.1. obtene el siguiente item de la expresin
node = extraer(lista);
//2.2. si el elemento es un operando se mete a la pila
if ((*node).dato.tipo == E_OPERANDO)
{
push(pila, (*node).dato);
free(node);
}
else
{
//2.3.1. se extraen los dos elementos superiores de la pila
aux1 = pop(pila);
aux2 = pop(pila);
//2.3.2. se evaluan los dos elementos almacenando el resultado en una
//variable temporal
switch((*node).dato.valor)
{
case E_mas:
(*aux1).dato.real=(*aux2).dato.real + (*aux1).dato.real;
break;
case E_min:
(*aux1).dato.real=(*aux2).dato.real - (*aux1).dato.real;
break;
case E_por:
(*aux1).dato.real=(*aux2).dato.real * (*aux1).dato.real;
break;
case E_div:

(*aux1).dato.real=(*aux2).dato.real / (*aux1).dato.real;
break;
}
//2.3.3 Se introduce el nuevo valor en la cima de la pila
push(pila, (*aux1).dato);
//liberamos la memoria
free(aux1);
free(aux2);
}
}
//3. obtener el valor de la expresin en la sima de la pila
aux1 = pop(pila);
return (*aux1).dato.real;
}

void mostrar(struct queue &lista)


{
if (lista.ini == NULL)
return;
struct nodo *aux = NULL;
printf("\nExrpresin: ");
aux = extraer(lista);
while (aux != NULL)
{
printf("%d ", (*aux).dato.valor);
free(aux);
aux = extraer(lista);
}
}

You might also like