Segundo ejemplo de uso de una función La función, que convierte una temperatura en grados Fahrenheit a grados Celsius, es llamada dos veces desde el programa principal. Se observa que la declaración de cent es REAL en la unidad de programa principal en concordancia con su tipo en la función y que el argumento actual en ambas llamadas es REAL, en concordancia con su tipo como argumento formal en la función. Los nombres de los argumentos actuales y sus correspondientes formales no tienen porqué ser iguales.
Argumento formal Sintaxis general: donde intencion_paso puede ser: El atributo INTENT ayuda al compilador a encontrar errores por el uso indebido de los argumentos formales de un procedimiento. Si el argumento formal es un valor de entrada. En el caso de un procedimiento función bien diseñado, el atributo de todos los argumentos formales debe ser IN. IN No para funciones TIPO, [INTENT( intencion_paso)] :: arg_formal Si el argumento formal es un valor de salida. OUT Si el argumento formal es un valor de entrada y salida. IN OUT No para funciones
Tercer ejemplo de uso de una función La función factorial es llamada desde un programa principal: Las variables n, i del programa principal no tienen nada que ver con las variables n, i de la función. Puesto que las variables locales a una unidad de programa son visibles únicamente en el interior de la misma, se pueden usar los mismos nombres para variables locales en unidades de programa diferentes, sin conflictos.
Subrutinas Son procedimientos más generales que las funciones, aunque comparten casi todas sus características. Pueden retornar más de un valor, o no retornar nada en absoluto. Reciben los valores de entrada y devuelven los valores de salida a través de su lista de argumentos. La estructura general de una subrutina es idéntica a la de una función: Cabecera de subrutina Sección de especificaciones Sección de ejecución Terminación de la subrutina
Subrutinas (definición) SUBROUTINE nombre_subrutina ([Lista de argumentos formales]) identifica esa unidad de programa como un procedimiento subrutina. Cabecera: Lista de argumentos formales nombre_subrutina identificador Debe incluir la declaración de los tipos de los argumentos formales con su atributo INTENT correspondiente a su intención de uso y la de las variables locales a la subrutina, si las hay. Sección de especificaciones: Debe incluir al menos las sentencia de asignación en la que se asignen valores a los argumentos de retorno. Sección de ejecución: Terminación: END SUBROUTINE [nombre_subrutina] Delimita el fin de la definición de la subrutina y produce el retorno al punto de llamada. El retorno también se puede forzar mediante instrucciones RETURN.
Llamada a una subrutina CALL nombre_subrutina ([Lista de argumentos actuales]) Llamada a una subrutina desde cualquier unidad de programa: Se asocian los argumentos actuales con sus correspondientes argumentos formales. El paso de los argumentos se realiza por dirección. Se evalúan los argumentos actuales que son expresiones. Se ejecuta el cuerpo de la subrutina especificada. Se devuelve el control a la unidad de programa que hizo la llamada, en concreto, a la sentencia siguiente a la sentencia CALL. La subrutina NO devuelve ningún valor a través de su nombre, sino que son los argumentos los encargados de realizar las transferencias de resultados. Debe haber concordancia en el número, tipo y orden de los argumentos actuales y sus correspondientes argumentos formales, al igual que en las funciones.
Ejemplo de uso de una subrutina Programa que llama dos veces una subrutina que convierte grados, minutos y segundos a grados expresados con decimales: La función intrínseca REAL devuelve el valor real de su argumento.
Transferencia de arrays a procedimientos Se transfiere la dirección de memoria del primer elemento del mismo. De esta manera, el procedimiento es capaz de acceder al array, pues todos sus elementos ocupan direcciones de memoria consecutivas. El procedimiento debe conocer el tamaño del array, en concreto, los límites de los índices de cada dimensión. Hay dos formas: array formal con perfil explícito. array formal con perfil asumido. Se pasan las extensiones de cada dimensión del array en la lista de argumentos y se usa en la declaración del array formal en el procedimiento. Ejemplo: Ambas formas permiten operaciones con arrays completos y subconjuntos de arrays. La declaración de un array formal de este tipo usa dos puntos, : , para cada índice. Ejemplo: CALL proced (matriz, d1, d2, resul) !llamada a subrutina SUBROUTINE proced (matriz, d1, d2, resul) INTEGER, INTENT(IN):: d1,d2 INTEGER, INTENT(IN), DIMENSION(d1,d2)::matriz ! perfil explícito INTEGER, INTENT(OUT):: resul MODULE mod1 CONTAINS SUBROUTINE sub1 (matriz) INTEGER, INTENT(IN OUT), DIMENSION(:,:)::matriz ! perfil asumido END SUBROUTINE sub1 END MODULE mod1
Procedimientos como argumentos Los argumentos actuales de un procedimiento pueden ser nombres de subrutinas o funciones definidas por el programador. Como el paso de argumentos se realiza por dirección, en este caso, se pasa la dirección de memoria de comienzo del procedimiento. Si el argumento actual es una función, necesita el atributo EXTERNAL en su sentencia de declaración de tipo, tanto en el procedimiento de llamada como en el procedimiento llamado. La sintaxis general es: TIPO, EXTERNAL:: nombre_funcion Ejemplo: Si el argumento actual es una subrutina, es necesario escribir una sentencia EXTERNAL, tanto en el procedimiento de llamada como en el procedimiento llamado. La sintaxis general es: EXTERNAL:: nombre_subrutina
Atributo y sentencia SAVE Cada vez que se sale de un procedimiento, los valores de sus variables locales se pierden, a menos que se guarden poniendo el atributo SAVE en las sentencias de declaración de tipo de aquellas variables que se quieren guardar. Para guardar todas las variables locales a un procedimiento escribir simplemente SAVE en una sentencia ubicada en la sección de especificaciones del procedimiento. La sintaxis general es: TIPO, SAVE:: variable_local1[, variable_local2] Ejemplo: Automáticamente, toda variable local inicializada en su sentencia de declaración se guarda. INTEGER FUNCTION fun(N) INTEGER INTENT(IN):: N INTEGER, SAVE:: cuenta
cuenta = cuenta + 1! Cuenta las veces que se llama la función … END FUNCTION fun
Procedimientos internos Existe un tercer tipo de procedimientos, los llamados procedimientos internos. Un procedimiento interno es un procedimiento completamente contenido dentro de otra unidad de programa, llamada anfitrión o host. La estructura general es: Cabecero de unidad de programa Sección de especificaciones Sección ejecutable CONTAINS Procedimiento interno Fin de unidad de programa El procedimiento interno se compila junto con su anfitrión, sólo es accesible desde él y debe escribirse a continuación de la última sentencia ejecutable del anfitrión, precedido por una sentencia CONTAINS. Un procedimiento interno tiene acceso a todos los datos definidos por su anfitrión, salvo aquellos datos que tengan el mismo nombre en ambos. Los procedimientos internos se usan para realizar manipulaciones de bajo nivel repetidamente como parte de una solución.
Ejemplo CONTAINS PROGRAM ejemplo REAL, DIMENSION (2) :: k1,k2,k3,k4 REAL, DIMENSION (2) :: y REAL :: t,h REAL, PARAMETER :: g=9.8 REAL, PARAMETER :: m0=5000.0 REAL, PARAMETER :: mb0=1000.0 REAL, PARAMETER :: tb0=60.0 REAL, PARAMETER :: isp=400.0 REAL :: c,mdot
….. Usa F1, F2, etc… F1(y(2)) …
CONTAINS FUNCTION F1(y) REAL :: y F1=-y END FUNCTION F1
FUNCTION F2(t) REAL :: t,m m=m0*(1.0 + mdot*t/m0) F2=c*mdot/m+g END FUNCTION F2
END PROGRAM ejer2
Resuelto 1 1.- Sumar dos números enteros usando una función para calcular la suma. La llamada a la función suma se realiza en una sentencia WRITE en el programa principal. Se asocian los argumentos actuales con sus correspondientes argumentos formales. Es decir, a se asocia con x (del mismo tipo que a) y b se asocia con y (del mismo tipo que b). Se ejecuta el cuerpo de la función suma, lo cual implica cargar en suma el resultado de la adición de x e y. Se devuelve el control a la sentencia WRITE del programa principal. La ejecución se produce de la siguiente manera:
Resuelto 2 2.- Calcular el número combinatorio sabiendo que m debe ser mayor o igual que n. Se realizan tres llamadas a la función fact, que calcula el factorial de un número. Estas llamadas forman parte de una expresión aritmética. En el caso de fact(m-n) , en primer lugar se evalúa el argumento actual (m-n) y, a continuación, se asocia con el argumento formal x definido en la función y se ejecuta la función. Cuanto mayor es el número de llamadas a una función, más justificada está su codificación por separado del programa principal.
Resuelto 3 3.- Calcular siendo n leído por teclado. Usar una función para calcular el factorial (i!). La llamada a la función fact se realiza desde el interior de un bucle, y forma parte de una expresión aritmética. La ejecución de la función se realiza tantas veces como valores toma el índice del bucle. El programa se ejecuta tantas veces como el usuario quiera, por ejemplo, mientras se teclee la letra S.
Resuelto 4 4.- Calcular la media de cinco números (leídos por teclado) utilizando para ello una función. Para transferir un array (vector o matriz) a un procedimiento como argumento basta escribir el nombre del mismo. El array formal XX se ha declarado usando la dimensión transferida en el argumento d1. ¿Qué cambios hay que hacer en el programa para usar perfil asumido en el array formal xx?
Página anterior | Volver al principio del trabajo | Página siguiente |