16
UNIVERSIDAD CATOLICA ANDRES BELLO. FACULTAD DE INGENIERIA. ESCUELA DE INGENIERIA INFORMATICA PUERTO ORDAZ – ESTADO BOLIVAR. CATEDRA: HUMANIDADES I. SEMESTRE: II ANGEL FABRICIO PEÑA PROF. JESUS LAREZ CIUDAD GUAYANA, NOVIEMBRE 2014 Proyecto 1: Dicciona rio de sinónimo s y antónim os

UNIVERSIDAD CATOLICA ANDRES BELLO. FACULTAD DE INGENIERIA. ESCUELA DE INGENIERIA INFORMATICA PUERTO ORDAZ – ESTADO BOLIVAR. CATEDRA: HUMANIDADES I. SEMESTRE: II

Embed Size (px)

Citation preview

UNIVERSIDAD CATOLICA ANDRES BELLO.FACULTAD DE INGENIERIA.

ESCUELA DE INGENIERIA INFORMATICAPUERTO ORDAZ – ESTADO BOLIVAR.

CATEDRA: HUMANIDADES I.SEMESTRE: II

ANGEL FABRICIO PEÑA PROF. JESUS LAREZ

CIUDAD GUAYANA, NOVIEMBRE 2014

Proyecto 1:

Diccionario de

sinónimos y

antónimos

Índice

Planteamiento del problema 1

Premisas 2

Estructuras de datos 3

Funciones del Codigo Principal 5

Tipo Abstracto de datos Listas 7

Casos de Pruebas 8

Casos de errores 12

Conclusiones 13

Referencias 14

Planteamiento del Problema

El manejo de la memoria dinámica es una herramienta importante para cualquier programador. Un problema puede simplificarse mediante el alocamiento de memoria en tiempo de ejecución y una solución poco eficiente en términos de uso de memoria, puede volverse eficiente mediante el uso de estas técnicas.

Y aunque es algo extremadamente importante, lamentablemente el manejo dinámico de la memoria es algo engorroso de aprender para alguien que se inicia en la programación, ya que requiere cierto conocimiento acerca de la estructura del computador.

Es por esa razón que realizar un proyecto que dependa en gran parte del uso de la memoria dinámica es importante para alguien que se está adentrando al mundo de la programación. Debido a ser un lenguaje de medio nivel, C posee elementos de alto nivel y la flexibilidad de un lenguaje de bajo nivel, lo cual lo hace un lenguaje adecuado para realizar este tipo de proyectos.

El proyecto que consiste en un diccionario de sinónimos y antónimos, los cuales son introducidos desde un archivo, requiere una base de datos para almacenar todas las palabras, y la mejor forma de hacerla es mediante estructuras que se creen en tiempo de ejecución como las listas enlazadas y los arreglos dinámicos. Es por esto que la finalidad principal de este proyecto es aprender sobre el uso de la memoria dinámica.

Premisas

El proyecto consta en hacer un diccionario de sinónimos y antónimos. Los sinónimos y antónimos están dados por un archivo con extensión ‘.dic’ con una lista de dos palabras y un indicador de si son sinónimos o antónimos. Dicho archivo es cargado por el usuario y puede ser cambiado en cualquier momento mediante el uso del modo interactivo y el comando ‘cargar’. Dicho archivo tiene el siguiente formato:

La letra ‘s’ y ‘a’ definen si la segunda palabra es sinónimo o antónimo de la primera respectivamente y los pares de palabras no tienen que estar necesariamente ordenados. Se supone que las palabras están compuestas por letras, pero de todas formas se valida en caso de encontrarse con un numero o signo.

El diccionario debe trabajar mediante dos modalidades distintas. En una basta con introducir (en la terminal de Linux) el nombre del programa a ejecutar, un indicados ‘s’ o ‘a’, y una palabra, seguido de esto se mostraran todos los sinónimos o antónimos de la misma, dependiendo del indicador. La segunda modalidad es un diccionario interactivo, en el que después de cargar un archivo, se pueden revisar sinónimos y antónimos de palabras completas o palabras que comiencen con un expresión. Esta modalidad debe iterar hasta que el usuario desee salir del diccionario. Los comandos en este modo son:

Cargar palabra: carga el archivo palabra.dic s palabra : muestra los sinónimos de la palabra a palabra: muestra los antónimos de la palabra e expresión: muestra los sinónimos y antónimos de las palabras que comiencen con

dicha expresión ayuda . : muestra el menú de ayuda, en donde se describen todos los comandos. salir . : sale del modo interactivo.

Estructuras de datos

Para la realización del diccionario, se usaron estructuras de datos ya definidas por el lenguaje C, como lo son los arreglos, y estructuras personalizadas como los nodos y las listas:

Estructura node Estructura Lista

Para almacenar los datos del archivo, se usa una estructura auxiliar, la cual es un arreglo que contiene punteros a caracteres. Se leen las líneas del archivo y se van colocando en las posiciones de uno de dos arreglos, dependiendo de si las palabras son sinónimos o antónimos. Después de haber leído las líneas del archivo, se ordenan los dos arreglos mediante Shellsort.

Luego, a partir de ese arreglo auxiliar, se crean listas de palabras relacionadas entre sí. Todos los nodos de una de estas listas contienen palabras que son sinónimos o antónimos (pero no ambos) de la primera palabra de la lista. Finalmente, estas listas se van colocando en un arreglo de punteros a listas, creando así la estructura de datos principal del programa. Al igual que con los arreglos auxiliares, existen dos de estas estructuras, una para antónimos y una para sinónimos, y en esta es donde se realiza la búsqueda binaria.

1

2

Archivo .dic introducido por el usuario.

Arreglo auxiliar donde se cargan las líneas del archivo.

Estructura Principal. Consta de un arreglo de punteros a listas, en las cuales se encuentran, en

Este caso, los Sinónimos de la palabra en la primera posición de la lista.

Funciones Incluidas en el Archivo principal

3

1

2

3

FILE *openfile ( char *nombre )

Esta función abre el archivo con el nombre dado. En el caso en el que dicho archivo no exista, muestra un mensaje de error y retorna NULL. En caso de éxito, retorna un puntero al archivo abierto.

void * asignar_memoria( int n )

Retorna un puntero que apunta a una dirección de memoria del tamaño de n. En caso de un error al momento de asignar la memoria, la función muestra un mensaje de error y hace que la ejecución del programa termine.

void Shell ( char *array[], int size )

Esta función usa el método de ordenamiento Shell para ordenar el arreglo auxiliar que contiene las líneas del archivo.

void cargarArreglos( FILE *archivo , char *sin[ ] , char *ant[ ] , int *Ssin, int *Sant )

Esta función importa las líneas del archivo dado, las coloca en dos arreglos auxiliares de strings (uno para sinónimos y uno para antónimos), para después poder ordenarlos alfabéticamente. La función lee una línea del archivo mientras esa línea no sea el final del archivo (EOF), asigna memoria a la posición del arreglo siguiente a la actual y coloca ahí la línea del archivo. Cuando llega al final del archivo, coloca un puntero a NULL en la posición actual, denotando el final del arreglo. Además, ordena los dos arreglos usando la función “Shell”, es decir, los arreglos están ordenados después de llamar esta función.

lista** estructura_datos( char *array[ ], lista **array_lista, int *tamano )

La función “estructura_datos” crea, a partir de uno de los arreglos auxiliares creados con la función “cargarArreglos”, un arreglo de punteros a listas, las cuales poseen las palabras relacionadas entre sí (ya sean sinónimos o antónimos). Esto permite buscar la palabra especificada por el usuario y devolver todos sus sinónimos o antónimos. De conseguir dos líneas iguales dentro del arreglo, se omite la segunda, así se evitan palabras repetidas. El parámetro ‘tamano’ es un puntero a enteros, cuyo valor aumenta cada vez que la estructura crece. Al retornar la funcion, este parámetro tendrá el valor del tamaño de la estructura, el cual será útil al momento de realizar la búsqueda binaria.lista* Busqueda_Binaria(lista **arreglo, char palabra[], int min, int max)

Esta función, mediante búsqueda binaria, localiza en la estructura de datos principal la palabra solicitada por el usuario, mostrando los antónimos o sinónimos de haberlos. Si no existen, retorna un mensaje de error.

int my_substr ( char sa[], char sb[] )

Determina si una expresión se encuentra contenida dentro de otra. La expresión debe estar al principio de la palabra para que la función retorne verdadera. Esta función se usa en la búsqueda de sinónimos y antónimos de una expresión en el modo interactivo.

int Busqueda_Secuencial( lista **arreglo, char expresion[] )

Esta busca todas las ocurrencias de una expresión en la estructura de datos principal usando “my_substr”, e imprime todos los sinónimos y antónimos de dichas ocurrencias. Este método de búsqueda solo se usa para buscar las ocurrencias de expresiones.

FILE *archivo_comando( FILE *archivo)

Abre el archivo con el nombre dado y regresa un puntero al archivo abierto. De haber fallado la apertura de dicho archivo, se termina la ejecución del programa.

Tipo Abstracto de datos Listas

En el proyecto se usa el tipo abstracto de datos lista, con las cuales se pueden realizar distintas operaciones, pero para el programa fueron necesarias 6 operaciones básicas. Las siguientes funciones permiten el manejo de las listas y están contenidas en la cabecera “listas.h”. Siendo ‘lp’ una lista y ‘newp’ un nodo, estas funciones son:

nueva_lista( void )

Crea una nueva lista, cuyos campos de inicio y fin apuntan a NULL.

nuevo_nodo( char dato[] )

Crea un nuevo nodo de una lista. Coloca la string, pasada como parámetro de la función, dentro del campo string del nodo. addfrente( *lp, *newp )

addfin ( *lp, *newp )

Añaden el nodo pasado como parámetro a la lista pasada como parámetro, al frente de la misma y al final de la misma respectivamente.

mostrar( *lp )

Muestra la lista pasada como parámetro. liberar_arreglo( char *arreglo[] )

free_all( lista *lp )

liberar_estructura( lista *arreglo[], int size )

Estas tres funciones se usan al momento de tener que liberar la memoria asignada mediante la función malloc(). La primera libera la memoria asignada al momento de crear los arreglos auxiliares que se usan como contenedores para las líneas del archivo al momento de importar los datos. La segunda libera todos los nodos de la lista pasada como parámetro. Y por ultimo, la función ‘liberar_estructura’ libera la memoria asignada para la creación de la estructura principal de datos, usando la función ‘free_all’ para liberar cada una de las listas.

Casos de Prueba

El programa siendo compilado y ejecutado en modo interactivo

Para buscar los sinónimos y antónimos de una palabra, primero se debe cargar un archivo .dic mediante el comando “cargar”.

En caso de necesitar más información sobre los comandos, se puede usar la interfaz de ayuda.Al introducir un comando desconocido se le sugiere al usuario usar el comando “ayuda”.

Después de haber cargado el archivo .dic, el programa está listo para mostrar resultados de la búsqueda de antónimos y sinónimos. De introducir una palabra no incluida en el archivo, se

mostrara un mensaje de error.

Además se puede buscar una expresión. Usando el comando ‘e’ seguido de una expresión, se mostraran los antónimos y sinónimos de las palabras que comiencen con dicha expresión. De

no obtener resultados de la búsqueda se muestra un mensaje de error.

El programa también incluye un modo de comandos, en el cual al ejecutar el programa, se puede escribir un comando (‘s’ o ‘a’) y una palabra, y se mostraran los sinónimos o los

antónimos de esa palabra, luego saldrá del programa.

Estas son algunas validaciones del modo comando. En la primera se introduce un nombre de un archivo que no existe. En la segunda se abre el archivo correctamente pero se da una palabra

que no existe dentro del archivo.

Casos de errores

Existen 2 errores conocidos en el programa, no son errores graves ni afectan el funcionamiento general del programa, pero igual deben ser tomados en cuenta al momento del uso del diccionario.

En el archivo usado durante de esta prueba, existe la palabra “Alto”, así que si se busca el sinónimo de “Alto” se obtendrán resultados positivos. Pero al momento de buscar los

sinónimos de “alto” no se muestran resultados. Esto ocurre debido a un error al momento de evaluar las mayúsculas y minúsculas de una palabra. El programa es sensible a las mayúsculas,

por lo que la palabra “caso” es diferente a la palabra “Caso”.

Para arreglar este error se debería primero transformar todas las palabras a minúsculas al momento de ser almacenadas en el arreglo auxiliar, y además transformar a minúsculas todas las palabras introducidas por el usuario para la evaluación de sinónimos y antónimos, de este modo todas las palabras a evaluar estarán en minúsculas y serán comparadas correctamente.

El programa toma una serie de números ‘2345’ como si fuesen palabras, y no tiene problemas en mostrar su sinónimo en el caso de que en el archivo este otro número definido de esta manera. Lo que se esperaría es que omitiera cualquier número o cualquier palabra con un

número, lo cual se debería evaluar al momento de pasar las líneas desde el archivo hasta el arreglo auxiliar.

Conclusiones

Cualquier programados experimentado, considerara el uso dinámico de memoria una herramienta extremadamente poderosa y útil, y hasta una solución obvia para muchos problemas. Pero para una persona que apenas se adentra al mundo de la programación, puede que no le sea tan claro el cómo y porque manejar la memoria de esta forma.

Son programas como estos, los cuales requieren una estructura de datos sólida, los que le explican al programador con poca experiencia, la importancia del uso de la memoria dinámica al momento de realizar un programa, y además le servirán de practica para dominar este tema el cual puede llegar a ser algo engorroso para el que se adentra por primera vez en este tipo de manejo de memoria.

Referencias

Para la realización del proyecto se usó como referencia la información de los siguientes temas de la página de foros ‘stackoverflow.com’:

http://stackoverflow.com/questions/15178132/c-dynamically-create-array-named-after-for-loop-iterator

http://stackoverflow.com/questions/7221981/how-to-make-a-dynamic-sized-array-in-c http://stackoverflow.com/questions/9496012/how-can-i-create-a-dynamically-sized-

array-of-linked-lists http://stackoverflow.com/questions/18575090/best-way-to-shift-an-array-in-c http://stackoverflow.com/questions/12337836/shifting-elements-in-an-array-in-c-

pointer-based http://stackoverflow.com/questions/12633039/shift-elements-in-array http://stackoverflow.com/questions/12136329/how-does-strcmp-work http://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-

using-scanf http://stackoverflow.com/questions/3765023/how-do-i-read-white-space-using-scanf-

in-c http://stackoverflow.com/questions/7812178/how-do-prefix-x-and-postfix-x-operations-

work http://stackoverflow.com/questions/4733649/freeing-memory-which-has-been-

allocated-to-an-array-of-char-pointers-strings http://stackoverflow.com/questions/1879550/should-one-really-set-pointers-to-null-

after-freeing-them

Para obtener información acerca de las funciones de las librerías estándar, se usó como referencia las siguientes páginas:

http://www.tutorialspoint.com/c_standard_library/stdio_h.htm http://www.tutorialspoint.com/c_standard_library/stdlib_h.htm http://www.tutorialspoint.com/c_standard_library/string_h.htm

Además se usaron como referencia general las siguientes páginas:

http://www.cprogramming.com/tutorial/c/lesson6.html http://www.cprogramming.com/tutorial/c/lesson14.html http://www.dreamincode.net/forums/topic/29381-pass-values-of-a-file-to-an-array/ http://www.youtube.com/watch?v=qirdxJDYcEw http://www.youtube.com/watch?v=cV6UxwdkLuc http://www.greenend.org.uk/rjk/tech/inline.html