Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ingeniería del software = Conjunto de etapas necesarias para desarrollar programas a gran
escala y de gran calidad.
• Análisis
• Diseño
• Codificación
• Pruebas y Mantenimiento
• Compiladores
• Intérpretes
• Programación funcional
• Programación lógica
• Programación imperativa
• Modelo de flujo de datos
-Objetivos de la programación
• Elemento terminal: Son elementos que forman parte del lenguaje C+-
Para poder controlar los valores máximo y mínimo que podemos utilizar no es preciso
recordar estos valores, podemos utilizar las constantes INT_MAX y INT_MIN que están
en la librería <limits.h>
Este tipo puede tomar valores positivos y negativos, y puede tener una parte decimal.
Es una representación no exacta. El rango de valores que puede tomar depende de la
plataforma (combinación de procesador, sistema operativo y compilador) utilizada.
Lo utilizaremos para manejar caracteres imprimibles: "A", "a", "B", "b", ... ."@","{", ....
y no imprimibles: RETURN, ESCAPE, F1, F2, .... Incluye la práctica totalidad de
caracteres utilizados en el Mundo
Para hacer referencia a un carácter de la mesa del código ASCII podemos hacer uso de
la función char(x): char(13), Tecla Return char(27), tecla ESCAPE, char(65) letra "A"
También podemos hacer referencia al lugar de la tabla que ocupa un carácter en uso
de la función int(c):
int ("Z") 90
Si hacemos uso de la librería <ctype.h> podemos utilizar las siguientes funciones para a
manejar caracteres:
1. Operadores multiplicativos * / %
2. Operadores aditivos + -
El procedimiento printf está en la librería <stdio.h> y sirve para mostrar o escribir por
pantalla un valor:
Ejemplos:
printf ("Introduce tu nombre:"); printf ("---- Bienvenido a este programa --- \ n ");
Cuando aparte de texto queremos mostrar valores numéricos, la función printf necesita saber
el tipo de datos que tiene que escribir para saber cómo las ha de escribir. El formato o forma
de utilizar esta función es:
• Un carácter: c Valor real con / o sin notación exponencial, con un número dado de
decimales de precisión. Los ceros y puntos decimal salen si es necesario: g
Nota: %10.3f real en coma fija que reserva 10 espacios y una precisión de 3 decimales
LLAMADAS EN LIBRERÍAS Y
#include <nombre_libreria.h>
DEFINICIONES DE CONSTANTES
DECLARACIÓN DE FUNCIONES
int a; float b;
FUNCIÓN PRINCIPAL
tipo_dato main () {
instrucciones
Cualquier dato que se utiliza en un programa tiene asociada los siguientes atributos:
• Pueden utilizarse las 52 letras mayúsculas y minúsculas del alfabeto inglés, la barra de
subrayado y los dígitos de 0 a 9.
3.2 CONSTANTES
Son datos que mantienen su valor durante toda la ejecución del programa. La forma de
declarar una constante es:
3.3 VARIABLES
Son datos que pueden ir variando su valor durante la ejecución del programa. La forma de
declarar la variable es:
• tipoDeVariable nombreVariable;
Para leer variables desde el teclado hacemos uso de la función scanf que está en la librería
<stdio.h>
Scanf (“%d”,&a); lee un valor entero por teclado, el valor se asigna a la variable int a;
TEMA 4 METODOLOGÍA 1
4.1 DESCOMPOSICIÓN EN SUBPROBLEMAS (REFINAMIENTOS SUCESIVOS)
• Encolumnado
• Comentarios
• Elección de nombres
• Uso correcto de mayúsculas y minúsculas
SI NO
Acción
El flujo de control durante la ejecución del programa se refleja mediante líneas o vías que van
de un elemento a otro. Las acciones tienen una sola vía de entrada o comienzo y una de
terminación o salida. Las condiciones tienen una vía de entrada, y dos vías de salida marcadas
son “SI” y “NO”.
• Sentencia WHILE
• Sentencia FOR
TEMA 6 METODOLOGÍA 2
6.1 DESARROLLO CON ESQUEMAS DE SELECCIÓN E ITERACIÓN
Consiste en plantear una acción compuesta como la realización de una acción entre varias
posibles, dependiendo de ciertas condiciones. Para desarrollar un esquema de selección
debemos identificar sus elementos componentes. Por tanto habrá que:
• Identificar cada una de las alternativas del esquema, y las acciones correspondientes.
Una iteración o bucle consiste en la repetición de una acción o grupo de acciones hasta
conseguir el resultado deseado.
• Identificar las acciones útiles a repetir, y las variables necesarias. Precisar el significado
de estas variables al comienzo y final de cada repetición.
• Identificar los valores iniciales de las variables, y si es necesaria alguna acción para
asignárselos antes de entrar en el bucle.
7.2 FUNCIONES
• El encabezamiento de la función
• El cuerpo de la función
declaración de variables;
instrucciones….
va a transferir información.
Tipo_resultado representa el tipo de dato (void, int, char, float…) que devuelve la función al
otro mòdulo.
Librería ctype.h
Librería math.h
7.3 PROCEDIMIENTOS
Son subprogramas que realizan una cierta tarea o acción. No devuelven ningún valor.
Cuando una función llama a otra función para que se ejecute hay un intercambio de
información entre las dos funciones. Este intercambio de información se lleva a cabo
• Parámetros formales: son variables locales, que pertenecen al módulo invocado, que
reciben el valor o la dirección de memoria de los parámetros actuales del módulo que
lo invoca en el momento de ser ejecutada la llamada.
• Por valor: Se envía una copia del valor que tienen cada uno de los parámetros actuales
en el momento de realizar la llamada. Esta valoración es recogida por los parámetros
formales del módulo invocado. En este caso el módulo invocado no puede modificar el
valor original de las variables actuales.
• Por referencia: en este caso, el módulo invocado, en lugar de trabajar con los valores
de las variables actuales, trabaja sobre las direcciones de las variables locales. Por
tanto, en este caso el módulo invocado puede modificar los valores de las variables
actuales del módulo que hace la llamada. Este uso ofrece menos seguridad que el paso
por valor.
• Variable local: Es aquella que su uso está restringido a la función que la ha declarado,
se dice entonces que la variable es local a esa función. Esto implica que esa variable
sólo va a poder ser manipulada en esa sección, y no se podrá hacer referencia fuera de
esa sección. Cualquier variable que se define dentro de las claves del cuerpo de una
función se interpreta como una variable local en esa función.
• Variable global: es aquella que se define fuera del cuerpo de cualquier función,
normalmente al principio del programa, tras la definición de los archivos de biblioteca,
de la definición de constantes y antes de cualquier función. El ámbito de una variable
global son todas las funciones que componen el programa, cualquier función puede
acceder a esas variables para leer y escribir en ellas.
If (n<=1){
Return 1;
} else {
return n * FactorialRecursivo(n-1);
Int main () {
El uso inadecuado de las variables que pasamos como argumentos puede dar lugar a algunos
problemas:
• Efectos secundarios.
• Redefinición de elementos.
• Doble referencia(aliasing)
Se produce cuando una misma variable se referencia con dos nombres diferentes. Se
puede dar los siguientes casos:
TEMA 8 METODOLOGÍA 3
8.1 OPERACIONES ABSTRACTAS
• Eficiente: Que consume los mínimos recursos en cuanto a tiempo y memoria. Se dice
que un programa es robusto si controla sus operaciones aunque le introducimos datos
incorrectos y erróneos.
• Haciendo el código fuente comprensible (el código fuente debe ser legible y
comprensible, a prueba de una auditoría de código.
Ante la posibilidad de errores con los datos que se opera a un programa, hay que considerar
dos actividades diferentes:
... ....
accion1
if (error1) {
} ...
accion2 if (error2) {
} ...
}
Una vez declarados los tipos se pueden definir y declarar variables de esos tipos que acabamos
de definir, por ejemplo, sería valido:
• TipoSexo sexo;
• TipoAltura altura;
Y podríamos utilizar estas variables como las variables que hemos visto hasta ahora:
• Sexo = ‘H’;
• Altura = 1,72;
Podemos definir una lista de valores con los tipos predefinidos y con los tipos que el
programador cree. Esta lista tomar valores numéricos automáticamente empezando por el
valor 0 y hasta n-1.
Los tipos enumerados se consideran tipos ordinales (al igual que los int y char), ya que tienen
un orden establecido de antemano.
Como los tipos enumerados son ordinales, podemos utilizarlos en comparaciones como, por
ejemplo:
Int (abril)>3
Dia= jueves;
Dia = tipodia(int(dia)+1);
El tipo predefinido bool se puede considerar como un tipo enumerado con dos valores:
Está constituido por una serie de valores, todos ellos del mismo tipo, a los que se les da un
nombre común que identifica a toda la estructura globalmente. Cada valor concreto dentro de
la estructura se distingue por su índice o número de orden que ocupa en la serie.
Donde TypoVector es el nombre del nuevo tipo de vector que se declara y NumElementos es
un valor constante que indica el número de elementos que constituyen el vector. El tamaño
del array estará comprendido entre 0 y NumElementos-1. TipoElemento corresponde al tipo
de dato de cada uno de los elementos del vector y puede ser cualquier tipo de dato
predefinido del lenguaje o definido por el programado.
OPERACIONES CON VECTORES: La mayoría de las operaciones interesantes con vectores hay
que realizarlas operando con sus elementos uno por uno. La referencia a un elemento
concreto de un vector se hace mediante el nombre del vector seguido, entre corchetes, del
índice del elemento referenciado.
VectorUno[0]; // frase[13];
Las cadenas de caracteres son en realidad vectores de caracteres. En C+- cualquier tipo vector
se considera una cadena o string, con independencia de su longitud particular, esto es, del
valor de N. Es un vector en el que se pueden almacenar textos de diferentes longitudes (si
caben). Para distinguir la longitud útil en cada momento se reserva siempre espacio para un
carácter más, y si hace que toda cadena termine con carácter nulo ‘\0’ situado al final.
FUNCIONES:
Por ejemplo, una fecha se escribe habitualmente como un dato compuesto de los elementos,
día mes y año.
Tupla: Colección de elementos componentes, de diferentes tipos, cada uno de los cuales se
identifica por un nombre.
Los esquemas de tupla pueden usarse en programas en C+- definiéndolos como estructuras del
tipo registro o struct. Un registro struct es una estructura de datos formada por una colección
de elementos de información llamados campos.
Tipo-campo1 nombre-campo1;
Tipo-campo2 nombre-campo2;
….
};
Cada una de las parejas Tipo-campo y nombre-campo, separadas por punto y coma, define un
campo o elemento componente y su correspondiente tipo. Además, hay que tener en cuenta
que la estructura acaba siempre con punto y coma:
Enero, febrero ……
};
VARIABLES DE TIPO REGISTRO Y SU INICIALIZACIÓN: Para declara variables de tipo registro es
necesario haber realizado previamente la deinición del tipo del registro. No se permite
declarar variables de tipo anónimo.
USO: Al manejar datos estructurados de tipo registro se dispone de dos posibilidades. Operar
con el dato completo, o bien operar con cada campo por separado. Las posibilidades de operar
con el dato completo son bastante limitadas. La única operación admisible es la de asignación.
En estas asignaciones debe cumplirse la compatibilidad de tipos. No es suficiente la
compatibilidad estructural, es decir, dos estructuras con los mismos campos no son
compatibles si sus definiciones se hacen por separado.
ACCESO A UNA ESTRUCTURA: Dado que los campos de una estructura se procesan
generalmente de forma individual, deberá poder acceder a cada uno de estos campos
individualmente. Para acceder a un determinado campo para poder leer o escribir en él
haremos: variable.campo
A veces resulta más natural comprobar la condición que controla las iteraciones al finalizar
cada una de ellas, en lugar de hacerlo al comienzo de estas. La condición que controla las
repeticiones es una expresión cuyo resultado es un valor de tipo bool. Si el resultado es true se
vuelve a ejecutar la acción y cuando el resultado es false finaliza la ejecución de la estructura.
Do {
Operaciones….
Scanf(“%” &tecla);
} while (tecla== ‘s’);
Esta sentencia dentro de cualquier bucle (while, for o do) finaliza la iteración en curso e inicia
la siguiente iteración. A veces dependiendo de la evolución de los cálculos realizados en una
iteración, no tiene sentido completar la iteración que se está realizando y resulta más
adecuado iniciar una nueva.
If (vectorCoeficientes[i] == 0){
Continue;
El if es una estructura de selección pero cuando tenemos que hacer muchos if unidades se
vuelve inestable y difícil de entender para resolver este problema utilizaremos el switch.
Cuando la selección entre varios casos alternativos depende del valor que toma una
determinada variable o del resultado final de una expresión, es necesario realizar
comparaciones de esa misma variable o expresión con todos los valores que puede tomar, uno
por uno, para decidir el camino a tomar.
Switch (expresion) {
Case valor1:
Acción A;
Break;
Case valor2:
Case valor3:
Accion B;
Break;
………
La sentencia comienza con la palabra clave switch y a continuación, entre paréntesis, se indica
la expresión, después, para cada valor que puede tomar la variable utilizaremos la palabra
clave case seguido del valor que pueda tomar y dos puntos (:) Y después la sentencia a realizar,
y para cerrar el case utilizaremos un break. El manual de estilo de C+- impone que cada acción
finaliza siempre con la sentencia break para que finalice la sentencia swith después de cada
acción. El uso del break es obligatorio para C+- y opcional para C/C++.
Los vectores con un tamaño indefinido se denominan vectores abiertos. En C+- los
argumentos de tipo vector abierto se especifican de manera similar a una declaración de tipo
vector, omitiendo el tamaño explicito, pero no los corchetes (^*): const int V[ ];
El precio que hay que pagar por disponer de esta facilidad es tener que pasar siempre la
longitud concreta del vector como argumento, en cada llamada.
Las matrices son estructuras de tipo formación (array) de dos o más dimensiones. Una forma
sencilla de plantear la definición de estas estructuras es considerarlas como vectores cuyos
elementos son a su vez vectores. Los vectores multidimensionales más utilizados son los
bidimensionales o matrices, los cuales vendrán definidos por dos índices ( normalmente, fila y
columna).
Una vez tenemos definido el TipMatriz ya podemos definir una variable de ese tipo:
TipoMatriz tabla1,tabla2;
OPERACIONES: Las operaciones con elementos individuales de una matrid pueden hacerse
directamente, de forma análoga a la operación con variables simpes de ese tipo. En cambio las
operaciones globales con matrices han de plantearse de manera similar a las operaciones
globales con vectores. En general se operará elemento a elemento, o a lo sumo por filas
completas.
Hay aplicaciones en las que resultaría deseable que el tipo de un dato variase según las
circunstancias. Si las posibilidades de variación son un conjunto finito de tipos, entocnes se
puede decir que el tipo del dato corresponde a un esquema que es la unión de los tipos
particulares posibles. Cada uno de los tipos particulares constituye una variante o alternativa
del tipo unión. Como situaciones típicas en las que se pueden aplicar los esquemas unión
tenemos:
Un tipo unión se define como una colección de campos alternativos, de tal manera que cada
dato particular sólo usará uno de esos campos en un momento dado, dependiendo de la
alternativa aplicable. La definición es similar a la de un agregado o struct, usando ahora la
palabra clave unión:
Typedef unión TipoNumero {
Int valorEntero;
Float valorReal;
TipoFraccion valorRacional;
};
La referencia a los elementos componentes se hace también como en los tipos struct:
Numero.valorentero = 33;
Fraccion2.valorracional = fraccion1.valorracional;
Como se ha dicho, sólo una de las variantes puede estar vigente en un momento dado. Si
asignamos valor a una de ellas será ésta la que exista a partir de ese momento, al tiempo que
dejan de existir las demás.
int numerador;
int denominador;
float valorReal;
TipoFraccio valorracional; };
TipoValor valor; }
switch (n.clase) {
n.valor.valorRacional.denominador); break;
Consiste en realizar cierta operación con todos y cada uno de los elementos de una formación.
Aplicable a vector con cualquier dimensión y mátrices. La forma más general del esquema de
recorrido sería:
Iniciar operación
completar operación
La terminación del elemento while está garantizada ya que el número de elementos que faltan
por tratar es un valor finito no negativo, que va disminuyendo en cada iteración. Para el
recorrido de matrices necesitaremos dos for por ejemplo:
Z [i][j]=0;
En ciertos casos el elemento a procesar debe elegirse realizando ciertos cálculos y el contador
de iteraciones sirve fundamentalmente para contabilizar el avance del recorrido y detectar el
final del bucle.
primer elemento hasta el último y comprobar si alguno de los elementos del vector contiene el
Para vectores con muchos elementos esta búsqueda quizás no sea muy conveniente.
La búsqueda binaria requiere menos comparaciones (iteraciones) que la secuencial, pero para
realizar la búsqueda es necesario que el vector esté previamente ordenado.
Estos pasos se repetirán hasta que encontremos el elemento o hasta que el tramo a buscar se
reduce a un elemento y basta.
12.3 INSERCION
El problema que se plantea aquí es insertar un nuevo elemento en una colección de elementos
ordenados, manteniendo el orden de la colección. Tenemos elementos almacenados en un
vector, ocupando posiciones desde el principio hasta el final quedando libre algunos
elementos del final.
La operación se puede realizar de forma iterativa, examinando los elementos empezando por
el final hasta encontrar uno que sea inferior o igual al que se quiere insertar. Los elementos
mayores es que el que se quiere insertar se van moviendo una posición hacia delante, con lo
que va quedando un huevo en medio del vector. Al encontrar un elemento menor que el
nuevo, se copia el nuevo elemento en el hueco que hay en ese momento.
Vector original
2 8 15 23 56
2 8 15 23 56
Vector final
2 8 15 64 23 56
12.4 ORDENACIÓN POR INSERCIÓN DIRECTA
Aquí se aborda una solución para la ordenación de datos almacenados en un vector. El método
más sencillo es el de ordenación por inserción directa. Está basado en el esquema de inserción
mostrado en el apartado anterior. Ejemplo: queremos ordenar un vector v de diez elementos
(0 a 9) y que inicialmente esta desordenado, {21,5,3,12,65,9,36,7,2,45} Para comenzar el
primer elemento (21) ya está ordenado consigo mismo. Luego extraemos el segundo elemento
(5) y se genera un hueco , que se puede utilizar para ampliar la parte del vector ya ordenada. El
método de ordenación consiste en insertar el elemento extraído en su lugar correspondiente
entre los elementos ya ordenador. Este proceso se repite con el tercero y sucesivamente.
frecuencia realizar un tratamiento especial de los elementos extremos del vector o, en general,
de los elementos del contorno de una formación. A continuación veremos algunas técnicas
particulares para evitar la necesidad de detectar de manera explícita si se ha llegado a un
elemento del contorno y/o realizar con él un tratamiento especial.
Estas estructuras se caracterizan por la reserva y liberación de memoria que se realiza durante
la ejecución del programa, y este espacio puede variar.
Puede definirse como un esquema de datos del tipo iterativo, pero con un número variable de
componentes. La estructura secuencia resulta parecida a una formación con número variable
de elementos. Hay 2 tipos de operaciones:
Operaciones de construcción:
Operaciones de acceso:
• Acceso secuencial: las componentes deben tratarse una por una, en el orden en que
aparecen en la secuencia.
13.2.1 PUNTEROS
Son variables simples cuyo contenido es precisamente una referencia a otra variable. El valor
de un puntero no es representable como número o texto. En su lugar usaremos una
representación gráfica en la que utilizaremos una flecha para enlazar una variable de tipo
puntero con la variable a la que hace referencia.
puntero
Variable
apuntada
Declaración de punteros: El tipo de
Una vez declarado el tipo, se pueden declarar variables puntero de dicho tipo. Una variable
puntera se puede usar para designar la variable apuntada mediante la notación:
*puntero
Ejemplo:
Tp_entero pe;
*pe = 33;
printf (“%d”,*pe);
Estas sentencias asignan el valor 33 a la variable dinámica señalada por el puntero pe, y luego
la imprime.
Para poder detectar si un puntero señala realmente o no a otra variable, existe el valor
especial NULL (no es una palabra clave, está dentro de la librería stdlib.h) Este valor es
compatible con cualquier tipo de puntero, e indica que el puntero no señala a ninguna
variable. Se usará para inicializar las variables de tipo puntero al comienzo del programa:
If (*pe ¡= NULL) {
*pe = 33;
Las variables dinámicas no tienen reservado el espacio en memoria que tienen las demás
variables, sino que se crean a partir de punteros en el momento en que se indique. Una vez
creadas siguen existiendo incluso después de que termine la ejecución del subprograma donde
se crean. Se crean así:
Tipo-puntero puntero;
El operador new crea una variable dinámica del tipo indicado y devuelve una referencia que
puede asignarse aun puntero de tipo compatible.
La variable dinámica se crea a base de reservarle el espacio necesario en una zona general de
memoria gestionada dinámicamente. En principio no se puede asumir que la variable recién
creada tenga un valor concreto, igual que las variables normales que se declaran sin un valor
inicial explicito.
Una vez creadas siguen existiendo hasta que el programador no especifique que ya no se
necesita. Para ello existe la sentencia delete, que permite destruir la variable dinámica:
Delete puntero;
Los punteros son un elemento de programación de muy bajo nivel. Los lenguajes de
programación simbólicos deberían evitar su empleo, sustituyendo por mecanismos más
potentes de declaración de estructuras de datos, que permitiesen definir directamente
estructuras dinámicas ilimitadas.
Para crear una secuencia ilimitada tendremos que recurrir al empleo de variables dinámicas y
punteros, enlazando cada elemento de la secuencia con el siguiente. Cada elemento de la
secuencia se materializa como un registro con dos campos: el primero contiene el valor de una
componente, y el segundo es un puntero que señala al siguiente. El último apuntará a NULL.
Una lista es una estructura de datos dinámica formada por un conjunto de elementos,
llamados nodos, del mismo tipo y almacenados en la memoria principal siguiendo una
secuencia lógica.
Podemos distinguir:
→ Listas contiguas: Son aquellas en las que los elementos se guardan en posiciones de
memoria contiguas, de forma que equivalen a tablas o vectores unidimensionales . Las
operaciones que podemos hacer en una lista contigua son:
Tipo_elemento valor:
Tiponodo* siguiente;
};
La dificultad reside en el hecho de que pasar un puntero por valor no evita que el subprograma
pueda modificar la variable apuntada.
Un enfoque más moderno de la programación trata de asociar la idea de tipo de datos con la
clase de valores, abstractos, que pueden tomar los datos. Esto quiere decir que la
representación o codificación particular de los valores no cambia, el tipo del dato considerado.
• Hacer referencia al tipo en sí, mediante un nombre, para poder definir variables,
subprogramas, etc.
Un tipo abstracto de datos es una agrupación de una colección de valores y una colección de
operaciones de manipulación.
Es importante comprender que estas colecciones son cerradas, es decir sólo se deben poder
usar los valores abstractos y las operaciones declaradas para ese tipo. Además los detalles de
cómo se representan los valores y cómo se implementan las operaciones pueden estar ocultos
para quien utiliza el tipo abstracto.
• Los campos de datos sirven para almacenar el contenido de información del dato
abstracto.
Ejemplo de TAD
float x;
float y;
};
A parte de definir dentro del registro los procedimientos y funciones estos subprogramas
deben implementarse fuera del registro (fuera del .h) de la siguiente manera:
void TipoPunto::Leer( ) {
void TipoPunto::Escribir( ) {
deltaX = xp.x;
deltaY = yp.y;
14.2 OCULTACIÓN
Para que un tipo sea realmente abstracto haría falta que los detalles de implemtenación no
fueran visibles. Tanto en los campos como en los procedimientos. En el caso anterior del
TipoPunto los campos x e y son visibles en todo momento, y pueden funcionar consultados y
modificados por el código que usa el tipo.
Para permitir esta ocultación los tipos struct admiten la posibilidad de declarar ciertos
elementos componentes como privados, utilizando la palabra clave private para delimitar una
zona de declaraciones privadas dentro de la estructura.
Ejemplo
........
private:
};
Las variables dia, mes y año slo son visibles (accesibles) desde las funciones y procedimientos
que están definidos dentro de la estructura, ya que están definidas con el modificador private.
En cualquier caso el desarrollo deberá atender tanto a la organización de las operaciones como
a la de los datos sobre los que operan, de manera que habrá que ir realizando
simultáneamente las siguientes actividades:
En cada etapa de refinamiento de una operación hay que optar por una de las alternativas
siguientes:
Ahora podemos reformular estas opciones para las estructuras de datos a utilizar:
• Considerar el dato como un dato abstracto y especificar su interfaz, dejando para más
adelante los detalles de su implementación.
TEMA 15 MÓDULOS
CONCEPTO: un módulo es un fragmento de programa desarrollado de forma independiente
(diseñado y compilando de forma independiente del programa que lo va a utilizar). El concepto
de módulo está íntimamente asociado a la abstracción de datos. Cuando utilizamos un módulo
a un programa, solo hay que saber qué hace el módulo y sus funciones, pero no tenemos por
qué saber cómo esta implementado.
La razón de exigir compilación por separado para los distintos módulos de un programa
obedece a la necesidad de limitar la complejidad de aquello que está siendo elaborado por una
persona en un momento dado. El programador podrá concentrarse en el módulo
prescindiendo en parte de cómo se utiliza ese modulo desde el resto del programa.
• La especificación del módulo es todo lo que se necesita para poder usar los elementos
definidos en él. (que hace el módulo) (interfaz)
• Compilación separada: El programa está formado por varios ficheros fuente, cada uno
de los cuales se compila por separado.
En este diagrama se representa cada módulo como un rectángulo, con el nombre del módulo
en suinterior.
C D
Las líneas indican las relaciones de uso, pueden llevar punta de flecha
• La cohesión indica el grado de relación que existe entre los distintos elementos de un
mismo módulo, y debe ser lo mayor posible. Esto quiere decir que dos elementos
íntimamente relacionados deberían ser definidos en el mismo módulo, y que un
mismo módulo no debe incluir elementos sin relación entre sí.
Un fichero fuente es un fichero de texto que contiene el código de una unidad de compilación,
es decir, es posible invocar el compilador dándole como entrada solo ese fichero fuente.
La compilación de un fichero fuente produce un fichero objeto que contiene la traducción del
código C+- a instrucciones de máquina. Los ficheros fuente tienen la extensión .cpp, los
ficheros objeto la extensión .o.
Un fichero fuente es un fichero de texto que contiene el código de una unidad de compilación,
es decir, es posible invocar el compilador dándole como entrada solo ese fichero fuente.
La compilación de un fichero fuente produce un fichero objeto que contiene la traducción del
código C+- a instrucciones de máquina. Los ficheros fuente tienen la extensión .cpp, los
ficheros objeto la extensión .o.
15.2.2 MÓDULO PRINCIPAL
Cuando se descompone un programa en módulos uno de ellos debe ser el módulo principal
uno de ellos ha de ser el programa principal (main).
No permiten generar un programa ejecutable por sí solos ( sin main). Están destinados a ser
usados por el programa principal. Hay que distinguir los elementos públicos y los privados. La
distinción de estos elementos se hace repartiendo el código del módulo en dos ficheros fuente
separados: un fichero interfaz (.h) o fichero de cabecera, y un fichero de implementación
(.cpp).
Los ficheros de cabecera (.h) se deben incluir en los ficheros de implenteación (cpp) y esto se
hace con la directiva #include que sirve para hacer referencia a un fichero fuente desde otro, y
tiene como parámetro el nombre dl fichero físico (.h) incluyendo la extensión.
Para usar los elementos públicos definidos en un módulo hay que incluir la interfaz de ese
módulo en el código donde se vaya a utilizar, con la directiva #include. La novedad ahora es
que los nombres de los ficheros de la propia aplicación deben escribirse entre comillas (“….”) y
no entre ángulos (<…>). Con esto se indica al compilador que debe buscar dichos ficheros en
donde reside elcódigo fuente de la aplicación y no donde está instalada.
Las relaciones de uso entre módulos se corresponden, con las directivas #include usadas en un
fichero fuente para hacer visibles los elementos de otro, y que pueden aparecer en el fichero
.cpp y/o en el .h. La recomendación es:
• Un fichero xxx.cpp debe incluir su propio xxx.h y otros yyy.h que use directamente.
Cuando definimos un tipo abstracto de datos, luego hay que declarar variables de ese tipo para
poder trabajar con ellas.
Los datos encapsulados nos permiten declarar dentro de un módulo una variable y evitar una
declaración explicita externa.
…valor interno…
void Operacion1 ( ) {
…valor interno…
void Operacion2 ( ) {
…valor interno…
}
Hay que recordar que por defecto las variables y subprogramas definidos en el nivel más
externo de un módulo son globales por defecto. Para que sean tratados como locales hay que
poner delante de ellos la palabra static.