Capitulo 2. Programación Modular
Consiste en dividir un programa en módulos o subprogramas con el fin de hacerlo más legible y manejable. Se presenta históricamente como una evolución de la programación estructurada para solucionar problemas de programación más grandes y complejos de lo que ésta puede resolver. Al aplicar la programación modular, un problema complejo debe ser dividido en varios subproblemas más simples, y estos a su vez en otros subproblemas más simples. Esto debe hacerse hasta obtener subproblemas lo suficientemente simples como para poder ser resueltos fácilmente con algún lenguaje de programación. Ésta técnica se llama refinamiento sucesivo, divide y vencerás ó análisis descendente (Top-Down). En C a los módulos se les llama funciones (FNC s) otros nombres a los módulos son: rutinas, subrutinas. Como ya sabemos las funciones tienen argumentos que se separan por comas.
2.1 Declaración de funciones.
Ejemplo: float b cos(float b ang); Nombre de la función => cos (identificador de la función) Argumento de IN => float ang (lado derecho, tiene tipo_dato e identificador) Argumento de Out => float (lado izquierdo recuerde que SOLO tiene tipo_dato) Funciones vistas: printf(), scanf(), main() Imagine como serían: suma() - Division_entera() area_cuadrado() Recuerde: Solo se puede Trasmitir/Enviar UN valor/dirección (lado izquierdo). Se pueden Recibir varios valores/direcciones con tipo_dato (lado derecho) conservado su orden. Nota: I) Todas las funciones tienen un nombre que las identifica y no deben haber dos funciones con el mismo nombre. II) la declaración de variables se diferencia de la declaración de funciones por los paréntesis que existen en la declaración de funciones. Todo lo que tiene paréntesis y termine en punto y coma; es una función. Int a; // Valor Int *a; // Dirección Int a(void); // Función Int a[3]; // Arreglo
III) Todo programa tiene mínimo una función y es la main( ). La función main es la única que se comunica con S.O. Se dice que un programa termina satisfactoriamente si retorna 0 al SO (main al S.O). El programa inicia con la ejecución del bloque de la función main() y termina cuando se ejecutan las instrucciones de main(). IV) En un programa TODAS las funciones tienen 3 partes: Declaración (Prototipo). Llamada de la función. Definición de la función.
Si la función es propia de C la definición y la declaración están en el archivo de cabecera (.h) correspondiente. En el programa aparece solo su llamada con sus argumentos correspondientes. Cada vez que se utilice una función de C debe incluirse (#include) el archivo de cabecera correspondiente. Si la función es del programador deben aparecer las 3 partes de la función en el programa (prototipo, llamada y definición para cada función).
V) Las funciones se pueden llamar cuantas veces sea necesario en un programa, solo se coloca la llamada de la función con su argumentos de I/O en el lugar que se necesite. (solo se necesita UN prototipo y UNA definición por función, así se realicen varias llamadas de dicha función en el programa)
2.2 Esqueleto de un programa en C. # include<stdio.h> archivos de cabecera (.h) # include<math.h> // prototipos de las funciones del programador int suma (int a, int b); void imprimir (int c); int main (void)..//llamada de fnc.z=suma(a,b); Definición de la función principal int suma(int a, int b) ::::::::::::::::::::::::::::::::: int c; ::::::::::::::::::::::::::::::::: c=a+b; Definición de las funciones del programador Void imprimir(int c) (Debe de existir PROTOTIPO para ellas) ::::::::::::::::::::::::::::::::: printf( el ); :::::::::::::::::::::::::::::::::
2.3 Funciones del programador Declaración de la función (PROTOTIPO) arriba e igual a la declaración de la función: Se realiza igual que la declaración de función. Se ubica entre los archivos de cabecera y la función main(). Sirve para ayudarle al compilador a verificar coincidencia de tipo_datos. Definición de la función: Abajo, sin punto y coma y termina con bloque: Se realiza igual que la declaración de función, pero sin punto y coma y siempre termina en bloque. Se ubica después de la función main(), si existen varias funciones no importa el orden. Sirve para indicarle al compilador que hace la función (mediante instrucciones de IN/OUT, declaración de más variables, instrucciones de asignación y llamadas a funciones de C y del programador).
2.4 Transferencia de valores y direcciones entre funciones Existen tres formas básicas: a. Paso por valor (envía valor de la variable). Lado Derecho b. Paso por referencia (envía la dirección de variable). c. Retorno de valor/dirección. Lado Izquierdo a. Paso por valor: Es el valor, lo que se envía de la función invocante a la función receptora, lo que implica que si se cambia el valor de la variable en la función receptora NO se ve reflejada en la función invocante. En la declaración de función, del lado derecho se colocan (con tipo de dato) las variables que se quieren tratar por valor. En la llamada de la función, dentro del paréntesis sin tipo de dato se colocan las variables tratadas por valor (si 3 + 1 separados por coma) En la definición de la función se utiliza la variable tratada por valor.
Valor de a int main(void) int a =3; imprimir(a); // llamado a la fnc printf( a en main %d \n, a); return 0; Función invocante void imprimir(int a) a++; printf( a en imprimir %d\n, a); Función receptora En pantalla: a en imprimir 4 a en main 3
#include <stdio.h> int main(void) int a =3; imprimir(a); // llamado a la fnc printf( a en main %d \n, a); return 0; void imprimir(int a) a++; printf( a en imprimir %d\n, a);
b. Paso por dirección: es la dirección de la variable lo que se envía de la función invocante (la que realiza la llamada) a la función receptora, lo que implica que si se cambia el valor en la función receptora SI se cambia en la invocante. En la declaración de la función, del lado derecho se colocan (con tipo dato) las variables que se quieren tratar por dirección, precedido de * c/u. En llamada de la función dentro del paréntesis sin tipo dato se colocan las variables tratadas por dirección (si hay más de 1separadas por coma), precedidas cada una por &. En la definición de la función cada vez que se utiliza 1 variable tratada por referencia o dirección se preceden por * (en todas partes).
Dirección de a int main(void) int a =3; imprimir(&a); // llamado a la fnc printf( a en main %d \n, a); return 0; Función invocante void imprimir(int *a) (*a)++; printf( a en imprimir %d\n, *a); Función receptora En pantalla: a en imprimir 4 a en main 4
c. retorno de valor o dirección: es el valor/dirección lo que se envía (Tx o retorno) de la función receptora a la invocante. Si hay retorno de valor del lado izquierdo debe ser diferente del tipo-dato void (definición y en la declaración). En la llamada de la función del lado izquierdo debe haber 1 variable donde se almacena lo que la función receptora envió (Tx retorno). Es obvio que hay en la llamada el símbolo de =. En la definición dentro del bloque debe de haber como mínimo 1 instrucción return. La instrucción return retorna inmediatamente/ a la función invocante, lo que significa que hay instrucciones o llamadas a funciones debajo del return nunca se ejecutan (return apagado tv) por lo general el return es la ultima instrucción de la función. Sintaxis: return constante; ejemplo: return 0; return variable; ejemplo: return a; Programación con funciones: calcula el área y el perímetro del rectángulo dada la base y la altura.