Proyectos Con CodeBlocks v.1112
Proyectos Con CodeBlocks v.1112
Proyectos Con CodeBlocks v.1112
Proyectos -1-
Proyectos
Los módulos tienen la ventaja de que se pueden desarrollar, compilar, probar y depurar por
separado. Posteriormente con un enlazador (linker) o bien con la herramienta correspondiente
del entorno de desarrollo (el administrador de proyectos, en el caso del EDI de Code
Blocks), se generará un único ejecutable.
Este proceso se conoce como compilación y enlazado por separado, y constituye el hilo
conductor de la mayoría de los desarrollos.
PROGRAMA
archivos cabecera archivos cabecera archivos cabecera
...
módulo módulo 2 módulo n
principal
ENLAZADOR
Programa ejecutable
módulos.
Igualmente el mantenimiento del software es más sencillo2 y seguro, dado que hacer un
pequeño cambio en un programa exigirá solamente modificar, recompilar y probar el módulo
afectado por la modificación.
Además, en futuros programas pueden reutilizarse estos módulos, con lo que también
disminuiremos tiempos de desarrollos posteriores, al estar utilizando software ya verificado.
Ámbito o alcance
Se conoce como ámbito o alcance de una variable, a la parte de código del programa donde la
variable es conocida3 y por tanto accesible.
Existen cuatro tipos de ámbitos: función, bloque de código, archivo fuente o módulo y
programa. Los tres primeros ya se han explicado en temas anteriores. En el presente
documento nos centraremos en el ámbito de programa.
Ámbito de programa
Las variables que tienen ámbito de programa pueden ser referenciadas por cualquier función
en el programa completo, es decir, desde cualquiera de los módulos que forman el programa.
Tales variables se llaman variables globales al programa.
Para hacer una variable global al programa, debe definirse simplemente al principio de uno de
los fuentes del programa, al principio del mismo y fuera de cualquier función, y
posteriormente declararse dentro de cada uno de los restantes módulos precedida del
especificador de tipo de almacenamiento extern. La cláusula extern se detallará más
adelante.
Los tres primeros ya se han explicado en temas anteriores. En el presente documento nos
centraremos en el especificador de tipo de almacenamiento extern.
2
Es más cómodo editar un archivo fuente pequeño que no de uno con un gran número de líneas.
3
Si una función “reconoce” a una variable, se dice que la variable es “visible” en esa función.
Ejemplo:
#include <stdio.h>
float numf;
int main(void) {
leerReal();
printf("Valor de numero real = %f", numf);
return 0;
}
#include <stdio.h>
int leerReal(void) {
extern float numf;
printf("Introduzca un valor en coma flotante: ");
scanf("%f", &numf);
return 0;
}
Este ejemplo no tendrá ninguna utilidad especial, ya que su única finalidad es comprobar el
funcionamiento de las variables extern. Es más, se desaconseja el uso de variables extern tal
como entre estos dos módulos se realiza, puesto que no es una buena técnica de programación
utilizar variables globales como medio de comunicación de funciones.
Creando un Proyecto
En el EDI Code Blocks, los programas compuestos de varios archivos fuente se denominan
proyectos. Cada proyecto está asociado a un archivo de proyecto, en el cual se determinarán
cuales son los archivos fuente que forman parte del proyecto. El nombre del proyecto lo
escoge libremente el programador, pero la extensión es fija .cbp.
El menú Proyecto permite gestionar los archivos de un proyecto, tanto los fuente como los
archivos de cabecera (#include).
Aparecerá una ventana de dialogo (figura 4) que nos permitirá elegir entre los distintos tipos
de Proyectos.
En esta ventana será necesario escoger un nombre para el proyecto (en el ejemplo
MiProyecto), y una ubicación (directorio) en el disco duro. Para elegir este directorio se
puede acceder a un cuadro de diálogo de navegación, pulsando sobre los tres puntos (…) que
aparecen a la derecha de la segunda línea de entrada de datos.
El nombre que se le dé al título del proyecto es el que Code Blocks le dará al fichero
ejecutable que generará a partir de la compilación y enlazado de todos los archivos fuentes del
proyecto.
Por defecto será también el nombre del fichero de configuración del proyecto, aunque puede
cambiarse en esta ventana, en la entrada Proyect Filename.
Pulsando Next pasamos a la siguiente ventana (figura 7).
En esta ventana deberá seleccionarse el compilador a emplear, además de los perfiles (modos
de compilación) a utilizar.
Los perfiles por defecto son perfectamente adecuados para cualquier proyecto: debug servirá
para el proceso de desarrollo del software, mientras que release selecciona las opciones del
compilador de mayor optimización y elimina la información de depuración, para el momento
del acabado.
Una vez pulsado Finish en la anterior ventana (figura 7), el proyecto ha sido creado, así como
el archivo main.c, que aparecerá en el nuevo directorio y como archivo principal de la
compilación.
Una vez seleccionados los archivos deseados, en la ventana del proyecto aparecerán
correctamente ordenados.
Pulsando entonces el botón add para añadir un nuevo directorio. Entonces se escribe la nueva
ruta (como se ve en la figura 15), y es añadido a la lista de búsqueda.
Hay que tener en cuenta un detalle: si el path del directorio a introducir contiene espacios, es
posible que la compilación termine con varios errores aparentemente inexplicables, por lo que
es mucho más conveniente indicar el nuevo directorio de búsqueda como un camino relativo,
en lugar de absoluto. Así, si necesitamos un directorio llamado Lib que está al mismo nivel
que el directorio del proyecto (como ejemplo, MiProyecto), entonces será más conveniente
fijar el nuevo directorio de búsqueda como ..\Lib.
También es posible, en esta ventana (figura 14), cambiar el compilador que se ha estado
usando, o las opciones de depuración u optimización, o cualquier otra que se desee añadir.
Nótese que, a la izquierda, aparecen los perfiles que hayamos creado antes (por defecto,
debug y release), de manera que los cambios afectan independientemente a una de los
perfiles: para que afecten a ambos, será necesario repetirlos. Es sencillo comparar ambos
perfiles: el primero tiene todas las opciones de depuración seleccionadas, mientras el otro no
sólo no las tiene, sino que incluye todas las posibles optimizaciones.
También puede seleccionarse Open…, y aparecerá una ventana de navegación, desde donde
puede buscarse el fichero del proyecto (.cbp), y seleccionarlo para abrirlo.
EJEMPLO
Supongamos que queremos crear un proyecto que llamaremos Ordena.cbp el cual va a
contener los archivos TESTORD.C, METODOS.C, MEMORIA.C y AUXI.C. Estos
fuentes ya se encuentran codificados y guardado en un directorio. Además también existen los
archivos de cabecera METODOS.H, MEMORIA.H y AUXI.H.
Podemos seguir los pasos descritos anteriormente hasta conseguir crear un proyecto vacío.
En particular en la ventana de dialogo para elegir el nombre y ubicación de la carpeta del
proyecto, podemos informar lo siguiente (figura 20).
Añadimos al proyecto los fuentes anteriores (según hemos visto en apartados anteriores.
Así, finalmente tendremos, en la ventana Proyects de la izquierda, el nombre del proyecto (en
nuestro ejemplo Ordena) con la relación de ficheros fuente que incluye. Pulsando sobre cada
uno de ellos, se abrirán los fuentes en distintas ventanas de edición, para poder trabajar con
ellos.
En el menú Build (figura 25), las opciones Build y Run, construyen (compilan y linkeditan)
y ejecutan el programa, respectivamente.
Se pueden atajar mediante las pulsaciones de teclas Ctrl+F9 y Ctrl+F10 o, incluso, si se
desean realizar ambas acciones en secuencia, seleccionando Build and Run o pulsando F9.
El archivo de proyecto .cbp se utiliza para guiar al Code Blocks en la compilación de los
programas fuente. El contenido del archivo .cbp se lee, y se compilan los archivos fuente que
necesiten ser compilados, produciéndose por cada uno de ellos un archivo objeto (.O). A
continuación, se enlazan estos archivos objeto, generándose el ejecutable (.EXE).
Siempre que se compile un proyecto, sólo se compilarán aquellos archivos que realmente sea
necesario. Code Blocks determina esto, comprobando la fecha y hora asociados a cada
archivo fuente (.C) y a su correspondiente archivo objeto (.O). Si el fuente es más moderno
que el objeto, entonces Code Blocks determina que el archivo fuente ha sido modificado, y lo
recompila. En caso contrario, se limita a utilizar el archivo .O.
Lo mismo ocurre con el archivo .EXE. Mientras el archivo .EXE sea más moderno que todos
los archivos .O del proyecto, no se recompilará nada. En caso contrario, se compilan los
archivos necesarios, y se vuelve a enlazar el proyecto.
Además de comprobar las fechas que hay en los archivos .C, .O y .EXE, Code Blocks
comprueba si alguno de los archivos de cabecera (.h) utilizados en el proyecto es más
moderno que alguno de los fuentes que lo utiliza. De ser así, todos los archivos fuentes que lo
utilicen se recompilan automáticamente.
Si navegamos por la carpeta del proyecto de nuestro ejemplo, podremos observar que los
ficheros objeto, fruto de la compilación, se han creado en el subdirectorio
C:\Temp\Ordena\obj\Debug,
Ejercicios resueltos
EJERCICIO 1
Este ejercicios está parcialmente resuelto, paso a paso, en un ejemplo visto anteriormente.
De todas formas, el propósito de este ejercicio resuelto es presentar las técnicas del diseño
distribuido de programas en diversos fuentes, y la compilación por separado utilizando
proyectos, por lo que incluso no conociendo en profundidad todavía los temas antes
indicados, podrá realizarse el ejercicio para conseguir el objetivo señalado.
Las funciones con los métodos de ordenación deberán recibir el vector a ordenar (puntero a
entero y su longitud), ordenarán el vector recibido y devolverán como valor de retorno el
tiempo tardado en realizar dicha ordenación.
El programa principal debe ser capaz de medir y presentar en pantalla los tiempos de
ejecución de los diferentes algoritmos para vectores de distintas dimensiones. Para ello el
programa principal solicitará los siguientes datos de entrada:
− Longitud máxima del vector a ordenar (long)
− Número de puntos de muestreo que se presentarán (long)
− Tipo de iniciación del vector:
− (a) ordenada ascendentemente
− (d) ordenada descendentemente
− (otro) cargado con números aleatorios
Se deberá llegar a ordenar un vector de 10000 enteros, pero debemos mostrar 5 puntos de
muestreo intermedios, por lo que deberemos presentar el tiempo que cada uno de los
algoritmos tarda en ordenar vectores de 2000, 4000, 6000, 8000 y 10000 enteros.
METODOS DE ORDENACION
dim vector ord ini burbuja inserción selección
2000 d 0 0 0
4000 d 0 0 0
6000 d 0 1 0
8000 d 1 2 0
10000 d 2 4 1
La primera columna indicará la longitud de los vectores que se han ordenado, la segunda el
tipo de iniciación del vector y el resto, los tiempos tardados por cada uno de los algoritmos.
El proceso a que se habrá realizado para confeccionar la anterior tabla será el siguiente:
− Reservaremos memoria para un vector de 2000 enteros.
− Iniciamos de forma aleatoria dicho vector y lo ordenamos (el mismo) por cada uno de los
métodos, presentando el tiempo tardado por cada uno de ellos.
− Liberamos esta memoria y reservamos memoria para un vector de 4000 enteros.
− Lo iniciamos con números aleatorios y lo ordenamos (el mismo) por cada uno de los
métodos, presentando el tiempo tardado por cada uno de ellos
− Liberamos dicha memoria.
− Etc.
− Así hasta llegar a ordenar vectores de 10000 enteros.
Es importante que las ejecuciones de los algoritmos se realicen con vectores en las mismas
condiciones de orden/desorden.
Todas las funciones auxiliares para manejar los vectores (iniciación, duplicado para mantener
siempre el original, etc, ...) no se codificarán dentro del fuente del programa principal, sino en
un fichero fuente aparte que podremos llamar AUXI.C
Todas las funciones para la creación y liberación de los vectores utilizando memoria
dinámica, se codificarán en un fichero fuente aparte que podremos llamar MEMORIA.C
De esta forma, nuestro programa estará repartido en cuatro ficheros fuentes, con tres archivos
de cabecera, tal como se muestra en el siguiente esquema.
Todos los fuentes, ya codificados, y sus archivos de cabecera, se encuentran en ficheros con el
nombre antes indicado.
Deberá crearse en Code Blocks un proyecto y compilarlo para generar un ejecutable que
llamaremos ORDENA.EXE.
Ejercicios propuestos
EJERCICIO 2
CBFAUX.H
CBPPAL.C CBFAUX.C
EJERCICIO 3
Realizar un programa que pida por pantalla dos vectores de la misma dimensión y presente
posteriormente
− El módulo de cada uno de ellos.
− Su vector suma.
− Su producto escalar.
El programa deberá solicitar al usuario, previamente, la dimensión de los vectores con los que
trabajará, validando que ésta no supere el valor 25, el cual se definirá como constante dentro
del programa.
Recordar que dados dos vectores n-dimensionales a = (a1, a2, ..., an) y b = (b1, b2, ..., bn),
entonces:
De esta forma, nuestro programa estará repartido en tres ficheros fuentes, con dos archivos de
cabecera, tal como se muestra en el siguiente esquema.
VECTOR.H IOVECTOR.H
Ayuda: puede tomarse como partida para realizar este ejercicio, el código incluido en el
fuente VCTR.C.