Carátula para entrega de prácticas
Facultad de Ingeniería
Laboratorio de docencia
Laboratorios de computación
salas A y B
Profesor: Castillo Hernández Gabriel M.C.………………………… ……
Asignatura: Estructura de Datos y Algoritmos I……………………………
Grupo: 15………………………………………………………………………….
No. de Práctica(s): No. 0………………………………………………………………………...
Integrante(s): Tabares López Jahdiel Adrián …………………………….
……………………………………...
…………………………..
Semestre: 2° [2018 - 2]…………………………………………………-------
Fecha de entrega: 12 - Febrero – 2018………………………………………………-----
Observaciones: ……………………………………………………………….............................
Observaciones: …………………………………………………………………………………….
CALIFICACIÓN: __________
Práctica No. 0:
Manejo Correcto de un Programa en C.
Objetivo.
El objetivo de esta práctica es reafirmar el uso correcto de los archivos de encabezado, archivos fuente y directivas del compilador. Para ello, se creará un programa en C que despliegue las tablas de sumar y multiplicar, en el programa se indicará como entrada la máxima tabla a multiplicar. La salida del programa una vez que esté funcionando es (por ejemplo, si se le proporciona un 2 como máxima tabla).
Investigación Previa.
Directiva #Include
Cuando el preprocesador encuentra una directiva #include inserta en esa posición el contenido del fichero especificado, en otras palabras, cuando en un archivo .c se encuentra una línea con un #include seguido de un nombre de archivo, el preprocesador la sustituye por el contenido de ese archivo. La sintaxis del comando es la siguiente:
#include “nombre_del_archivo”
#include <nombre_del_archivo”
El nombre del fichero aparece entre los símbolos < y > cuando se encuentra en un directorio definido por defecto en el sistema, Este directorio es donde se encuentran los ficheros de cabecera como stdio.h, stdlib.h, etc. Un fichero de cabecera, cuyo nombre tiene la terminación .h, contiene habitualmente prototipos de funciones y directivas del compilador. Cuando el fichero se encuentra en cualquier otro directorio, entonces el nombre deberá especificarse entre comillas.
Directiva #define
Las líneas de código que empiezan con # son directivas del preprocesador, el cual se encarga de realizar modificaciones en el texto del código fuente, como reemplazar un símbolo definido con #define por un parámetro o texto, o incluir un archivo en otro archivo con #include.
La directiva #define permite asociar una cadena a un identificador. Cada vez que el preprocesador encuentre este identificador en el programa, lo sustituirá por la cadena. Por lo tanto, lo que realiza #define es una sustitución simbólica, es decir, establece una macro en el código fuente. Esto se utiliza para definir constantes o literales; se les nombra también como constantes simbólicas. Su sintaxis es la siguiente:
#define <nombre> <valor>
Al definir la constante simbólica con #define, se emplea un nombre y un valor. Cada vez que aparezca el nombre en el programa se cambiará por el valor definido. El valor puede ser numérico o puede ser texto.
Este mecanismo de sustitución, además de permitir definir constantes simbólicas, pueden ser cambiadas fácilmente, a la vez que el programa se mantiene completamente legible. De forma análoga, se pueden definir macros con parámetros.
Ejemplo:
Después de pasar el procesador por la línea correspondiente, habrá quedado de la siguiente manera:
Cuando se define un macros con argumentos, conviene ser muy cuidadoso para prever todos los posibles resultados que se pueden alcanzar, y garantizar que todos son correctos. Es recomendable tener presente que la directiva #define:
No define variables
Sus parámetros no son variables.
En el pre procesamiento no se realiza ninguna revisión de tipos, ni de sintaxis.
Sólo se realizan sustituciones de código.
Es por estas razones que los posibles errores señalados por el compilador en una línea de código fuente con #define se deben analizar con las substituciones ya realizadas. Por convención entre los programadores, los nombres de las macros se escriben con mayúsculas.
Directivas condicionales.
También llamadas directivas de compilación condicional, nos permiten compilar selectivamente parte del código fuente del programa, y son llamadas así, ya que, al utilizarlas y dependiendo del resultado de la evaluación de una expresión, ciertas partes del código de un programa podrán ser o no compilados. Muchas veces son usadas conjuntamente con el operador defined que determina si un identificador ha sido definido con la directiva #define.
#ifdef y #ifndef. Se pueden utilizar estas directivas de compilación, las cuales significan:
#ifdef - si definido. [Abrebiación de #If defined]
#ifndef - si no definido. [Abrebiación de #If !defined]
Para #ifdef si se ha definido el macro nombre previamente, se compila secuencia de sentencias1:
Para #ifndef si no se ha definido el macro nombre previamente, se compila secuencia de sentencias1:
Uno de los usos más frecuentes de las macros para establecer bloques de compilación opcionales. Por ejemplo:
El código que se compilará será printf(“hola”), en caso de estar definida la macro COMP_HOLA, en caso contrario, se compilará la línea printf(“adiós”).
De forma similar, el comando #ifndef pregunta por la no-definición de la macro correspondiente. Un uso muy importante de los comandos #ifdef y #ifndef es para evitar comandos #include del mismo fichero repetidos varias veces en un mismo programa.
Declaración extern
Esta declaración, le dice al compilador que una variable o una función existe, incluso si el compilado aún no la ha visto en el fichero que está siendo compilado en ese momento. Esta variable o función puede definirse en otro fichero o más abajo en el fichero actual.
Cuando se hace uso del término para la declaración de una variable, extern hace saber al compilador que la variable se va a encontrar en la tabla de símbolos de otra unidad. Se utiliza para exponer variables pertenecientes a un archivo a uno o varios archivos adicionales. La declaración externa no es traducida por el compilador sino por el enlazador, con ello extern es un mecanismo válido para instalar modularidad a nivel del compilador.
Sintaxis y Ejemplo:
En este primer archivo la variable VariableGlobal es definida
.
Pero para utilizar la misma variable en el archivo 2, tiene que ser declarada usando el extern. Independientemente de la cantidad de archivos, una variable global solo se define una vez, sin embargo, tiene que ser declarada usando extern en cualquier archivo aparte de aquel que contiene la definición
¿Qué es un Prototipo en C y cuál es su uso?
Un prototipo en lenguaje C es un modelo limitado de una entidad más completa que vendrá luego. El prototipo proporciona información sobre el tipo devuelto o producido por la función, así como sobre sus parámetros. Se utiliza para verificar los llamados a la función, ya que controla el número y el tipo de los parámetros, comprobando si son los apropiados. Es decir, en cada llamado a una función, esta debe tener exactamente los parámetros que se utilizarán a lo largo del programa, o el compilador dará un mensaje de error.
Para escribir el prototipo, simplemente se copia la cabecera de la función al comenzar el programa y se añade un punto y coma al final como una señal al compilador de que ésta no es una función sino un prototipo. Los nombres de las variables dadas en el prototipo son optativos y actúan meramente como comentarios al lector del programa, ya que ellos son completamente ignorados por el recopilador.
En resumen, una declaración de función precede a la definición de función y especifica el nombre, el tipo devuelto, la clase de almacenamiento y otros atributos de una función. Para ser un prototipo, la declaración de función también debe establecer tipos e identificadores para los argumentos de la función.
Los prototipos de función tienen los siguientes usos importantes:
Establecen el tipo de valor devuelto para funciones que devuelven tipos diferentes de int. Aunque las funciones que devuelven valores int no requieren prototipos, estos son recomendables.
Sin prototipos completos se realizan conversiones estándar, pero no se hace ningún intento de comprobar el tipo o el número de argumentos con el número de parámetros.
Los prototipos se utilizan para inicializar punteros a funciones antes de que se definan esas funciones.
La lista de parámetros se utiliza para comprobar la correspondencia de los argumentos de la llamada de función con los parámetros de la definición de función.
Desarrollo.
Elaborar un programa en C que despliegue las tablas de sumar y multiplicar, en el programa se indicará como entrada la máxima tabla a multiplicar.
Como primer paso, con el fin de que el compilador realizara las advertencias (warnings) necesarias, se habilitaron las siguientes opciones en CodeBlocks [Entorno de desarrollo de Lenguaje C utilizado] seleccionando del menú principal:
Banderas:
Enable extra compiler warnings [-Wextra] (Habilitar advertencias adicionales del compilador).
Esta bandera de compilación habilita algunos indicadores de advertencia adicionales que no están habilitados por [-Wall]:
Además, también imprime mensajes de advertencia para los siguientes casos:
Un puntero se compare un número entero, con el cero usando <, <=, >, o >=.
Un enumerador y un no enumerador aparecen en una expresión condicional. (Sólo para C ++)
Bases virtuales ambiguas. (C ++ solamente)
Subscribir una matriz que ha sido declarada register. (Sólo para C ++)
Tomando la dirección de una variable que ha sido declarada register. (Sólo para C ++)
Una clase base no se inicializa en el constructor de copia de una clase derivada. (Sólo para C ++)
Enable warnings demanded by strict ISO C and ISO C++[-pedantic]. (Habilitar advertencias exigidas por ISO C e ISO C ++).
Emite todas las advertencias exigidas por los estrictos ISO C e ISO C ++; rechaza todos los programas que usan extensiones prohibidas, y algunos otros programas que no siguen ISO C y ISO C ++. Los programas válidos ISO C y ISO C ++ deben compilarse correctamente con o sin esta opción. Sin embargo, sin esta opción, también se admiten ciertas extensiones de GNU y características tradicionales de C y C ++. Con esta opción, son rechazados.
[-pedantic] no causa mensajes de advertencia para el uso de las palabras clave alternativas cuyos nombres comienzan y terminan con '__'.
Las advertencias [-pedantic] también están deshabilitadas en la expresión siguiente __extension__. Sin embargo, solo los archivos de encabezado del sistema deben usar estas rutas de escape; los programas de aplicación deberían evitarlos.
Algunos usuarios intentan usar [-pedantic] para verificar si los programas cumplen estrictamente con la norma ISO C. Pronto descubren que no hace exactamente lo que quieren: encuentra algunas prácticas que no son ISO, pero no todas; solo aquellas para las que ISO C requiere un diagnóstico, y algunas otras para las que se han agregado diagnósticos.
Otras Banderas:
Stop compiling after first error [-Wfatal-errors] (Detener la compilación después del primer error).
Esta opción hace que el compilador anule la compilación al primer error, en lugar de intentar continuar e imprimir más mensajes de error.
Puede solicitar muchas advertencias específicas con opciones que comienzan con [-W], por ejemplo [-Wimplicit] para solicitar advertencias en declaraciones implícitas.
Enable all common compiler warnings (overrides many other settings)
[-Wall] (Habilite todas las advertencias comunes del compilador (anula muchas otras configuraciones)).
Esta bandera habilita todas las advertencias sobre construcciones que algunos usuarios consideran cuestionables, y que son fáciles de evitar (o modificar para evitar la advertencia), incluso en combinación con macros. Esto también habilita algunas advertencias específicas de lenguaje descritas en Opciones de Dialecto de C ++ y Opciones de Dialectos de Objetivo-C y Objetivo-C ++ .
Hay que tener en cuenta que algunas banderas de advertencia no están implícitas en [-Wall]. Algunos de ellos advierten acerca de construcciones que los usuarios generalmente no consideran cuestionables, pero que en ocasiones es posible que desee verificar; otros advierten sobre construcciones que son necesarias o difíciles de evitar en algunos casos, y no hay una forma simple de modificar el código para suprimir la advertencia.
Warn if main( ) is not conformant [-Wmain] (Advertir si main () no está acorde).
Advierte si el tipo de main es sospechoso; main debería ser una función con enlace externo, que retorna int, tomando cero, dos o tres argumentos de tipos apropiados correspondientes. Esta advertencia está habilitada por defecto en C ++ y está habilitada por cualquiera [-Wall] o [-pedantic].
Posteriormente, se creará un proyecto, capturando los tres archivos C que fueron entregados previamente por el profesor, sin agregar ninguna línea adicional ni tampoco algún otro archivo. [ main.c | tablas.c | operaciones.c ]
Al tratar de compilar los 3 archivos, se tendrán que obtener una serie de errores y advertencias:
Se tendrá que conseguir que el programa funcione, para ello cuando compile el programa no deben existir advertencias ni errores. Para ello, se hará el uso de los conocimientos adquiridos en la investigación previa.
Reglas a seguir para la corrección del programa:
Sólo puede agregar declaraciones (prototipos, extern, #include, etc), no puede modificar ninguna de las funciones del programa, ni agregar nuevas funciones.
Cree los archivos .h necesarios, en ellos solo debe estar la información estrictamente necesaria, no debe haber declaraciones innecesarias.
Comentarios. [Práctica No.0]
Primeramente, durante el desarrollo de esta práctica tuve presente en todo momento los conceptos que previamente investigué, para poder aplicarlos a la hora de corregir el programa. Para corregir el código necesité analizar la composición original para poder entenderlo y así agregar los archivos de cabecera .h, elementos importantes donde dentro de ellos hice prototipos de las respectivas funciones. En el archivo main.c añadí la declaración extern al prototipo de la variable ‘superior’, además de que en operaciones.c y tablas.c puse los #include correspondientes a las cabeceras, incluyendo <studio.h>.
Para corregir las advertencias que aparecieron gracias a la habilitación de las banderas de compilación, se cambió la sintaxis dentro de los archivos de cabecera dentro de la declaración #endif, donde la forma de escribir comentarios fue modificada a la forma correcta del lenguaje.
Finalmente, al compilar no se tuvo ningún error ni advertencia, y el programa funciona correctamente como fue diseñado.
Conclusiones.
Gracias a esta práctica y los conocimientos que me permitió reforzar, pude entender cómo se realiza el manejo correcto de los archivos de encabezado, y las directivas del compilador, algo que es de gran importancia conocer (funcionamiento y sintaxis) para tener las herramientas necesarias al diseñar o corregir un programa en lenguaje C. En este ejercicio, aprendí a cómo crear archivos de cabecera y a comprender qué funcion cumplen las directivas que se utilizan dentro de ellos. Además, pude ver la importancia de los prototipos en un programa como este, ya que, si no se maneja de manera correcta, creará conflictos con el compilador al no reconocer ciertas funciones; a su vez, gracias a la habilitación de las banderas del compilador GCC GNU, observé que función cumplían y qué se podía hacer para manejar el programa de la mejor manera con éstas activadas.