Pasaje por esquema de referencia Programa de verificación Subrutina PROGRAM test REAL : : a, b(4) INTEGER : : next ….. Call sun1 (a, b, next) …….. End test SUBROUTINE sun1(x, y, i) REAL, INTENT(OUT) : : x REAL, INTENT(IN) : : y(4) INTEGER : : i …………….. END SUBROUTINE sun1 memoria P. principal subrutina 001 a x 002 b(1) y(1) 003 b(2) y(2) 004 b(3) y(3) 005 b(4) y(4) 006 next i 007 Cuando se llama a una subrutina el programa principal señala la posición en memoria de cada argumento actual de la lista de argumentos. La subrutina busca los argumentos ficticios en el lugar indicado.→ Pasaje por referencia Los argumentos reales (programa principal) y ficticias ( subrutinas) tienen que coincidir en número, tipo y orden EJemplo de error Una variable real tomada como entera PROGRAM llamada_ equivocada ! Propósito: ejemplificar un error frecuente ! IMPLICIT NONE REAL : : x= 1. Call arg_erroneo(x) END llamada_ equivocada SUBROUTINE arg_erroneo(i) IMPLICIT NONE INTEGER : : i Write (*,*) “ i=“,i END SUBROUTINE arg_erroneo Al correr el programa el resultado es : i= 1065353216 Pasaje de un arreglo a una subrutina La subrutina necesita conocer la localización y el tamaño del arreglo Hay distintas maneras de especificar la longitud de una variable ficticia: Pasar los limites de cada dimensión del arreglo a la subrutina como argumento en el llamado y declarar el arreglo ficticio a esta longitud → Forma explicita de la variable ficticia Ej: SUBROUTINE proceso (dato1, dato2, n, nvalores) INTEGER, INTENT(IN) : : n, nvalores REAL, INTENT((IN), DINENSION(n) : : dato1 ! forma explicita REAL, INTENT((OUT), DINENSION(n) : : dato2 ! forma explicita ! DO i= 1, nvalores dato2(i) = 3* dato1(i) END DO END SUBROUTINE proceso Como la dimensión de las variables es conocida por la expresión explicita se puede realizar operaciones entre arreglos o secciones de arreglos. Ej: SUBROUTINE proceso2 (dato1, dato2, n, nvalores) INTEGER, INTENT(IN) : : n, nvalores REAL, INTENT((IN), DINENSION(n) : : dato1 ! forma explicita REAL, INTENT((OUT), DINENSION(n) : : dato2 ! forma explicita ! dato2(1:nvalores) = 3. * dato1(1: nvalores) END SUBROUTINE proceso2 Otra forma es el asumir el tamaño del arreglo ficticio a través de un *. En este como el compilador no conoce el tamaño del arreglo no puede efectuar operaciones entre arreglos o secciones de los mismos Ej: SUBROUTINE proceso3(dato1, dato2, n, nvalores) INTEGER, INTENT(IN) : : n, nvalores REAL, INTENT((IN), DINENSION(*) : : dato1 ! se asume el tamaño REAL, INTENT((OUT), DINENSION(*) : : dato2 ! se asume el tamaño ! DO i= 1, nvalores dato2(i) = 3* dato1(i) END DO END SUBROUTINE proceso3 Pasando variables “character “ a una subrutina Cuando se utiliza una variable character como argumento ficticio, su longitud es declarada con un *. Si queremos saber la longitud de texto usamos la función intrínseca LEN( ) Ej : SUBROUTINE ejemplo(texto) CHARACTER(len=*), INTENT(IN) : : texto WRITE(*, *) “ la longitud de texto es: “, LEN(texto) END SUBROUTINE ejemplo Es conveniente usar banderas dentro de una subrutina para no parar el proceso de un programa: Ej: Si restamos 2 números y calculamos la raíz cuadrada. SUBROUTINE proceso (a, b, resultado) IMPLICIT NONE ! Diccionario y declaración de variables REAL , INTENT(IN) : : a, b REAL , INTENT(OUT) : :resultado REAL : : tem ! Auxiliar temporaria tem= a-b IF(tem>=0).then result = SQRT(tem) ELSE WRITE(*, *) “La raiz no se puede calcular” STOP END IF END SUBROUTINE proceso Si utilizamos banderas SUBROUTINE proceso (a, b, resultado, error) IMPLICIT NONE ! Diccionario y declaración de variables REAL , INTENT(IN) : : a, b REAL , INTENT(OUT) : :resultado INTEGER , INTENT(OUT) : : error ! Aviso de error =1 REAL : : tem ! Auxiliar temporaria tem= a-b IF(tem>=0).then result = SQRT(tem) error= 0 ELSE result=0 error=1 END IF END SUBROUTINE proceso Compartiendo datos usando módulos MODULE comparto ! ! Propósito: declarar datos compartidos entre subrutinas ! IMPLICIT NONE SAVE INTEGER, PARAMETER : : nvalores = 5 REAL, DINENSION(nvalores) : : valores END MODULE comparto Un MÓDULO contiene las definiciones y valores iniciales que se quieren compartir entre programas unitario Un “MODULE” puede ser incluido en un programa a través de la sentencia “USE” Cada programa que utilice el módulo tiene acceso a los mismos datos Comienza con MODULE y continua con un nombre de hasta 31 caracteres. Termina con END MODULE nombre SAVE garantiza que todos los valores de los datos en el módulo son preservados en distintos procedimientos. Ej PROGRAM test_modulo ! ! Propósito: ver como se usa el módulo ! USE comparto IMPLICIT NONE REAL, PARAMETER : : PI= 3.14159 Valores = PI * (/1., 2., 3., 4., 5. /) CALL sub1 END PROGRAM test_modulo SUBROUTINE sub1 ! Propósito: ver como se usa el módulo ! USE comparto IMPLICIT NONE Write(*, *) valores END SUBROUTINE sub1