Professional Documents
Culture Documents
MODULARIDAD
Una vez conocidas las estructuras de control disponibles en la programacin estructurada, es posible desarrollar cualquier programa. Sin embargo, a medida que los problemas se hacen ms complejos, resulta ms difcil su resolucin como un todo, al tener que considerar simultneamente todos los aspectos que afectan al problema. En este captulo se introduce la modularidad, una tcnica basada en la separacin de problemas complejos en tareas ms simples, simplificando su resolucin y contribuyendo a mejorar la claridad de las soluciones alcanzadas. Adems, se estudiarn los mecanismos disponibles en C para implementar esta tcnica.
Clculo IRPF
Lectura datos
Clculo resultados
Visualizacin resultados
58
5. MODULARIDAD
Adems, la lectura de datos del contribuyente podra an desglosarse, por ejemplo, en lectura de datos personales y lectura de datos econmicos:
Clculo IRPF
Lectura datos
Clculo resultados
Visualizacin resultados
Datos personales
Datos econmicos
Las ventajas de esta forma de resolver los problemas son numerosas: Facilita la depuracin y el mantenimiento de programas. As, en el ejemplo del clculo del IRPF, un error en la lectura de la fecha de nacimiento del contribuyente podra buscarse directamente en el mdulo Datos personales, mientras que una modificacin de las escalas de gravamen afectara nicamente al mdulo Clculo resultados. Facilita el trabajo en equipo, ya que la asignacin de tareas puede hacerse de forma sencilla y, con una buena divisin modular, la independencia entre dichas tareas permitir a cada individuo concentrarse en su trabajo sin preocuparse del mtodo de resolucin empleado para realizar las restantes tareas. A este respecto, debe sealarse que el diseo modular ha de buscar siempre la encapsulacin de sus mdulos, es decir, la ocultacin de los aspectos internos de implementacin del mdulo (el cmo) al resto de mdulos que lo utilizan, los cuales slo requerirn conocer qu hace (el qu). Posibilita la reduccin del tamao de los programas, ya que un mdulo puede ser utilizado en varias ocasiones dentro de un mismo programa, mientras que las instrucciones que describen la tarea del mdulo slo ser necesario incluirlas una vez. Por ejemplo, en el clculo del IRPF la lectura y validacin de una fecha podra considerarse un mdulo independiente. Si durante la lectura de los datos personales es necesario leer la fecha del contribuyente y la de su cnyuge, slo ser necesario repetir la llamada a dicho mdulo y no la descripcin de cmo se realiza la lectura y validacin de una fecha. Favorece la reutilizacin del cdigo, es decir, el aprovechamiento de resoluciones de subproblemas llevadas a cabo con anterioridad. El desarrollo de mdulos que resuelven problemas frecuentes permitir al programador recopilar en una biblioteca de funciones propia una batera de soluciones genricas que incrementen su rendimiento futuro. Por ejemplo, un mdulo que lea una fecha y la valide podra reutilizarse fcilmente en la resolucin de otros problemas. Por lo tanto, la metodologa empleada consiste en comenzar, desde una visin general del problema, determinando los subproblemas que la componen. Cada uno de estos se divide a continuacin, si se estima necesario, en otros ms simples. Como se ha visto, esto puede representarse como una estructura jerrquica en cuya parte superior se encuentra el problema principal y en la inferior los subproblemas ms simples. Por esto, a esta metodologa tambin se la denomina de diseo descendente. Cada nivel de esta estructura representa un grado de detalle y, por tanto, de abstraccin, distinto.
59
5. MODULARIDAD
Las soluciones de un diseo descendente pueden implementarse en C con el concepto de mdulo. El mdulo correspondiente al problema principal se denomina programa principal y el resto de mdulos en los que se divide subprogramas. En lenguaje algortmico utilizaremos los trminos algoritmo principal y subalgoritmos. Normalmente, un mdulo es llamado desde otro mdulo situado en un nivel jerrquico superior al suyo. Tras la llamada, el flujo de ejecucin se traslada a la primera instruccin del mdulo llamado y comienza su ejecucin. Cuando esta termina, el control es devuelto al lugar del mdulo llamador desde el que el mdulo fue invocado. Como se ha comentado, esto puede ocurrir en diferentes lugares del mdulo llamador. A continuacin se ilustra esa transferencia del flujo de ejecucin en el ejemplo anterior.
Calculo IRPF
. . . leerDatos(...) . . calculoResultados(...) . . verResultados(...) . .
ada Llam
leerDatos(...)
. . . datosPersonales(...) . . . datosEconomicos(...) . . .
da ma Lla
datosPersonales(...)
. . . leerFecha(...) . . . . leerFecha(...) . . .
1 ada Llam 2 a ad m Lla
leerFecha(...)
Re to rn o 1 Re torn o2
o rn to Re
En C, el concepto de mdulo se corresponde con el de funcin. A continuacin, se detallan los aspectos de definicin y uso de las mismas.
o rn to Re
5. MODULARIDAD
cumple dicho dato cuando llega a la funcin. Igualmente, los datos de salida pueden tener como destino, no solamente el monitor, sino tambin el mdulo llamador si son el resultado de la funcin. En la fase de diseo, en la parte declarativa y antes de la definicin de constantes simblicas y la declaracin de variables de que haga uso la funcin, deber indicarse la cabecera de la funcin, que contendr los identificadores de los parmetros formales, el tipo asociado a cada uno de ellos y el tipo asociado al valor devuelto por la funcin, utilizando el siguiente diagrama sintctico:
identificador del mdulo ( identificador de parmetro , : tipo ) : tipo
El identificador del mdulo se refiere al nombre de la funcin. A continuacin, entre parntesis, se incluirn los identificadores de los parmetros formales junto con sus tipos correspondientes (o nicamente los parntesis si la funcin carece de parmetros). Por ltimo, se indicar el tipo devuelto por la funcin. La representacin algortmica ser muy similar a la vista en el Captulo 3 para un algoritmo completo. La nica diferencia es que en un subalgoritmo, el primer smbolo del que parten el resto de instrucciones ser el que se indica a continuacin: identificador_mdulo(lista de parmetros) BLOCK La lista de parmetros se refiere a los parmetros formales que utiliza la funcin. Ser, por lo tanto, una lista de identificadores separados por comas (sin indicar tipos). En cuanto a identificador_mdulo ser el nombre de la funcin. Adems, para expresar en el subalgoritmo el valor que finalmente devolver la funcin como resultado al mdulo llamador, se emplear la siguiente representacin: devolver(expresin) En la fase de resolucin en el ordenador, en C la definicin de una funcin se sita despus del programa principal (funcin main()). Una funcin tiene una constitucin similar al programa principal, es decir, posee una seccin de definicin de constantes simblicas, una cabecera de funcin y un cuerpo que contiene la declaracin de variables y las instrucciones correspondientes al diagrama de Tabourier. La cabecera, sigue el siguiente diagrama sintctico:
tipo identificador de la funcin ( tipo identificador de parmetro , )
Las secciones de definicin de constantes simblicas y declaracin de variables contendrn, respectivamente, las constantes simblicas y variables que la funcin utilice. El resto del cuerpo estar formado por el conjunto de instrucciones que llevan a la obtencin del valor que la funcin debe devolver. La ltima instruccin del cuerpo de la funcin deber ser de la forma: return expresin; indicando as el valor que esta devuelve como resultado al mdulo llamador.
61
5. MODULARIDAD
EJEMPLO 5.1. Desarrollar un mdulo que calcule y devuelva el factorial de un nmero recibido como parmetro. ANLISIS: a) Datos de entrada: n: Valor del que quiere calcularse el factorial. Mdulo llamador. (n 0) b) Datos de salida: factorial: Factorial de n. Mdulo llamador. c) Comentarios: Emplearemos una variable para contar el nmero de multiplicaciones efectuadas. DISEO: a) Parte declarativa: factorial(n:entero):real VARIABLES i:entero f:real b) Representacin algortmica: factorial(n) BLOCK f1
i 2, n, 1
M. llamador f n
factorial
for do
devolver (f) f fi
CODIFICACIN:
/* factorial(n) */ /* Devuelve el factorial de un nmero n */ double factorial(int n) { int i; double f; f=1; for (i=2; i<=n; i=i+1) f=f*i; return f; }
62
5. MODULARIDAD
Una llamada a una funcin implica los siguientes pasos: 1. El control de la ejecucin se transfiere del mdulo llamador a la funcin. 2. A cada parmetro formal se le asigna el valor del parmetro real que ocupe su misma posicin en la lista de parmetros. 3. Se ejecutan las instrucciones de la funcin. 4. El valor de la funcin es devuelto al mdulo llamador junto con el control de la ejecucin. 5. Se evala la expresin del mdulo llamador que contiene a la invocacin. El uso de mdulos definidos por el programador tambin afecta a las distintas fases de resolucin del mdulo llamador. En la fase de anlisis, deber incluirse un comentario por cada uno de los mdulos definidos por el programador que vayan a utilizarse, indicando su cometido y una descripcin de la informacin que se transferir desde y hacia el mdulo llamador. En la fase de diseo, en la parte declarativa y tras la definicin de constantes simblicas, deber indicarse la lista de mdulos a los que se invoca, empleando para cada uno la siguiente sintaxis:
identificador del mdulo ( tipo , ) : tipo
y precediendo a toda la lista del epgrafe MDULOS LLAMADOS. En la representacin algortmica, los pasos que contengan una invocacin a un mdulo definido por el programador estarn encerrados en el siguiente smbolo:
Por ltimo, en la fase de resolucin en el ordenador, en C deber indicarse, inmediatamente despus de la seccin de archivos de cabecera y de definicin de constantes simblicas del programa principal, para cada funcin externa utilizada en el programa, un prototipo de funcin, que debe seguir el siguiente diagrama sintctico:
tipo identificador de la funcin ( tipo , EJEMPLO 5.2. Calcular y mostrar por pantalla el nmero de combinaciones sin repeticin de n elementos tomados de m en m, solicitando n y m por teclado. ANLISIS: a) Datos de entrada: n: nmero total de elementos. Teclado. (n > 0) m: tamao de cada grupo de elementos tomado. Teclado. (n m > 0) M. P. n n f factorial ) ;
leerPositivo b) Datos de salida: result: nmero de combinaciones sin repeticin de n elementos tomados de m en m. Monitor. c) Comentarios: Se utilizar un mdulo para leer un nmero positivo desde teclado. Devolver dicho nmero.
63
5. MODULARIDAD
Se utilizar un mdulo para calcular el factorial de un nmero. Recibir dicho nmero y devolver el factorial calculado. DISEO: a) Parte declarativa: MDULOS LLAMADOS leerPositivo():entero factorial(entero):real VARIABLES n,m:entero result:real b) Representacin algortmica: combinatorio BLOCK nleerPositivo() mleerPositivo() m>n escribir ("Error") CODIFICACIN:
/***********************************/ /*** C O M B I N A T O R I O ***/ /***********************************/ #include <stdio.h> /* Prototipos de funciones */ int leerPositivo(); double factorial(int); /* Programa principal */ int main() { int n,m; double result; printf("Introduce un nmero: "); n=leerPositivo(); printf("Introduce otro nmero: "); m=leerPositivo(); while (m > n) { printf("Error, el segundo valor debe ser menor que %d: ",n); m=leerPositivo(); } result=factorial(n)/(factorial(m)*factorial(n-m)); printf("Combinaciones de %d elementos tomados de %d en %d (s.r.)= %.0f", n,m,m,result); return 0;
while do BLOCK
resultfactorial(n) / (factorial(m)factorial(n-m))
escribir (result)
mleerPositivo()
/* leerPositivo */ /* Devuelve un nmero positivo ledo desde teclado */ int leerPositivo() ... (aqu se situar la definicin de la funcin leerPositivo) /* factorial(n) */ /* Devuelve el factorial de un nmero n */ ... (aqu se situar la definicin de la funcin leerPositivo)
64
5. MODULARIDAD
tablaMultiplicar c) Comentarios: Utilizaremos una variable para contabilizar el nmero de multiplicaciones mostradas durante la visualizacin de la tabla de multiplicar. DISEO: a) Parte declarativa: tablaMultiplicar(mult:entero) VARIABLES i:entero b) Representacin algortmica: tablaMultiplicar(mult) BLOCK escribir (Tabla,mult) i 1, 10, 1 for do escribir (i,mult,imult)
65
5. MODULARIDAD
CODIFICACIN:
/* tablaMultiplicar(mult) */ /* Calcula y muestra la tabla de multiplicar de 'mult' */ void tablaMultiplicar(int mult) { int i; printf(" TABLA DE MULTIPLICAR DEL %2d\n",mult); printf("=============================\n"); for (i=1; i<=10; i=i+1) printf("%10d X %2d = %2d\n",i,mult,i*mult); }
el resultado del clculo combinatorio del Ejemplo 5.2 seguira siendo correcto, ya que las modificaciones que sufre el parmetro formal n dentro de la funcin no afectan al parmetro real con el que se realiza cada llamada. Cuando necesitemos definir un mdulo que devuelva ms de un valor al mdulo llamador, deberemos utilizar otro modo de transferir informacin entre mdulos: el pase de parmetros por referencia. Este modo permite establecer un canal de comunicacin bidireccional entre el mdulo llamador y el mdulo llamado. En concreto, consistir en transferir al mdulo llamado la direccin del parmetro real (utilizando el operador de direccin, &), en lugar de transferir una copia de su 66
5. MODULARIDAD
valor (parmetros real y formal representarn la misma direccin de memoria). As, a diferencia de lo que ocurre con el pase de parmetros por valor, las modificaciones realizadas sobre un parmetro formal pasado por referencia tambin se efectan sobre su correspondiente parmetro real, quedando as reflejadas en el mdulo llamador. Un mdulo puede pasar por referencia tantos parmetros como se quiera, ampliando as el nmero de valores que el mdulo puede devolver al mdulo llamador.1 Obsrvese que un parmetro pasado por referencia siempre actuar, al menos, como dato de salida del mdulo (a veces, podr actuar tambin como dato de entrada). En el caso de que el dato fuera slo de entrada al mdulo, el parmetro deber pasarse por valor.
EJEMPLO 5.4. Desarrollar un mdulo que intercambie en el mdulo llamador el valor de dos variables enteras. ANLISIS: a) Datos de entrada: x: valor a intercambiar. Mdulo llamador. y: valor a intercambiar. Mdulo llamador. b) Datos de salida: x': valor intercambiado (la y original). Mdulo llamador. y': valor intercambiado (la x original). Mdulo llamador.
c) Comentarios: Ser necesario utilizar una variable auxiliar que mantenga uno de los valores iniciales temporalmente, con el objetivo de que este no se pierda tras la primera asignacin. DISEO: a) Parte declarativa: intercambio(*x:entero, *y:entero) VARIABLES aux:entero b) Representacin algortmica: intercambio(x,y) BLOCK auxx CODIFICACIN:
/* intercambio(x,y) /* Intercambia los valores de x e y void intercambio(int *x, int *y) { int aux; aux=*x; *x=*y; *y=aux; */ */
xy
yaux
1 Si bien el lenguaje C permite que un mismo mdulo devuelva simultneamente un valor asociado al nombre de la funcin y otros valores asociados a parmetros pasados por referencia, el uso simultneo de ambos mtodos no se considera una buena prctica de programacin. Por ello, emplearemos el primer mtodo cuando el mdulo devuelva un nico valor y el segundo cuando devuelva ms de uno.
67
5. MODULARIDAD
En C:
void leerMatriz(int [][5]);
En C:
void leerMatriz(int m[][5])
68