Arreglos Un arreglo es un tipo de datos que contiene varios elementos de un mismo tipo. Cada elemento tiene asociado un índice, y puede ser tratado como si fuera una variable. La cantidad de elementos que tiene un arreglo es fija, y no puede cambiar durante la ejecución del programa. La sintaxis para declarar un arreglo es: tipo, dimension(tamaño) :: nombre La sintaxis para referirse al elemento de índice i de un arreglo x es: x(i) Por ejemplo, el siguiente programa utiliza un arreglo para guardar seis notas ingresadas por el usuario y luego calcular el promedio: 1 2 3 5 6 7 8 9 10 11 12 13 1 15 16 17 18 program promedio_notas integer, dimension(6) :: notas integer :: promedio print *, 'Ingrese sus notas' read *, notas(1) read *, notas(2) read *, notas(3) read *, notas() read *, notas(5) read *, notas(6) promedio = nint((notas(1) + notas(2) + notas(3) + & notas() + notas(5) + notas(6)) / 6.0) print *, 'Su promedio es', promedio end program promedio_notas En este programa, se ha declarado un arreglo de enteros de tamaño 6, cuyos elementos están indexados desde el 1 hasta el 6. El ejemplo podría perfectamente estar escrito usando seis variables a,b, c, d, e y f para guardar las notas. La ventaja de usar arreglos es que se puede usar ciclos para recorrer todos los elementos. A continuación reescribiremos el ejemplo para aprovechar esta ventaja. Además, definiremos el número de notas como una constante: 1 2 3 5 6 program promedio_notas integer, parameter :: N = 6 integer, dimension(n) :: notas integer :: promedio, suma integer :: i
7 8 9 10 11 12 13 1 15 16 17 18 19 20 21 print *, 'Ingrese sus notas' read *, notas(i) suma = 0 suma = suma + notas(i) promedio = nint(suma / real(n)) print *, 'Su promedio es', promedio end program promedio_notas Otra ventaja de usar arreglos es que el mismo programa puede ser utilizado para conjuntos de datos de cualquier tamaño sin requerir mayores modificaciones. El programa para promediar seis notas es exactamente igual al que se usaría para promediar treinta notas. Sólo basta con modificar el valor de la constante N. Arreglos multidimensionales Un arreglo multidimensional es un arreglo cuyos elementos tienen más de un índice. El caso más simple son los arreglos bidimensionales, que tienen dos índices, y son útiles para representar datos con formato tabular, como tablas y matrices. Los arreglos multidimensionales son declarados indicando los tamaños a lo largo de cada una de las dimensiones, separados por comas. Por ejemplo, un arreglo de enteros de 5 3 es declarado así: integer, dimension(5, 3) :: a Este arreglo tiene quince elementos: desde a(1, 1) hasta a(5, 3). La manera típica de recorrer los elementos de un arreglo multidimensional es usar varios ciclos do anidados, uno por cada dimension. Por ejemplo, el siguiente programa suma todos los elementos del arreglo a declarado en el ejemplo anterior: suma = 0 do i = 1, 5 do j = 1, 3 suma = suma + a(i, j) Cada índice no tiene un significado por sí mismo. El programador puede interpretar cada uno como quiera, siempre que sea consistente a lo largo del programa. Por ejemplo, para los elementos a(i, j) de un arreglo bidimensional, uno puede interpretar i como las filas de una tabla y j como las columnas, pero hacerlo al revés también es correcto. Inicialización de arreglos A veces un programa necesita tener un arreglo cuyos valores están dados de antemano, por lo que no corresponde que los ingrese el usuario.
Para estos casos, es posible inicializar el arreglo durante la declaración. El siguiente ejemplo ilustra la sintaxis inicializando un arreglo con la cantidad de días que tienen los meses del año: program dias_mes integer, dimension(12) :: dias = (/ 31, 28, 31, 30, & 31, 30, 31, 31, & 30, 31, 30, 31 /) integer :: mes print *, 'Ingrese el numero del mes' read *, mes print *, 'El mes ', mes, ' tiene ', dias(mes), ' dias' end program dias_mes Índices arbitrarios Es posible declarar un arreglo de tamaño N de modo que sus índices no vayan desde 1 hasta N, sino que tomen otros valores. Por ejemplo, podemos usar un arreglo bidimensional para guardar los totales mensuales de lluvia caída de los últimos cinco años. No es muy conveniente que el índice que representa el año tome los valores de 1 a 5. Para hacer que los índices vayan desde 2006 hasta 2010, la declaración se hace así: real, dimension(2006:2010, 12) :: lluvia Para asignar el total de lluvia caída de agosto de 2010, se hace así: lluvia(2010, 8) = 13. Secciones de arreglos Para referirse a una sección de un arreglo que corresponde a un arreglo de menor dimensión se puede usar dos puntos (:) en lugar del índice para indicar que se desea obtener todos los elementos a lo largo de la dimensión correspondiente. Por ejemplo, en el arreglo de los totales de lluvia por mes,lluvia(2007, :) es el arreglo unidimensional con los doce totales mensuales del año 2007, mientras que lluvia(:, 9) es el arreglo unidimensional de tamaño cinco con los totales de lluvia de septiembre de cada año. Operaciones sobre arreglos Hay algunas operaciones que pueden ser usadas sobre arreglos. Por ejemplo, la función sum recibe un arreglo como parámetro y entrega como resultado la suma de los elementos del arreglo: real, dimension(5) :: a = (/6, 1, -, 3, 0/) print *, sum(a)! la salida es 6.0 Si una operación binaria es aplicada sobre un arreglo y un valor escalar, entonces la operación es aplicada sobre todos los elementos del arreglo. Por ejemplo, si a es un arreglo, entonces el resultado de la expresión a * 2 es el arreglo cuyos valores son el doble del elemento respectivo de a. Si una operación binaria es aplicada sobre dos arreglos, entonces la operación es aplicada elemento a elemento. Por ejemplo, si a y b son arreglos, a * b es el arreglo de los productos de los elementos respectivos de a y b. Entrada de elementos de un arreglo
Para que el usuario pueda ingresar todos los elementos de un arreglo en una misma línea de entrada, se puede usar la sintaxis llamada do implícito: read *, (arreglo(i), i = 1, N) Cuando en el programa aparece esta sentencia, significa que el usuario debe ingresar, en la misma línea, todos los N valores del arreglo separados por espacios. Cálculo de la desviación estándar La desviación estándar se calcula usando la siguiente fórmula: σx= 1N 1 Ni=1(xi xˉ)2, donde xˉ es el promedio y xi es el i-ésimo dato. La manera ordenada de diseñar el algoritmo es separar el proceso en varias etapas: leer los datos y guardarlos en un arreglo datos; sumar los datos para calcular el promedio; calcular los cuadrados de las diferencias de los datos con el promedio, e irlos guardando en un arreglo cuadrados_diferencias; sumar los cuadrados de las diferencias, dividir por N - 1 y sacar la raíz cuadrada del resultado. Escribir el código es mucho más simple si estas etapas están claras de antemano. El programa terminado es el siguiente: program desviacion_estandar integer, parameter :: N = 10 real, dimension(n) :: datos, cuadrados_diferencias real :: suma_datos, suma_cuadrados_diferencias real :: promedio, desviacion integer :: i print *, 'Ingrese', N, 'datos' read *, datos(i) suma_datos = 0.0 suma_datos = suma_datos + datos(i) promedio = suma_datos / N cuadrados_diferencias(i) = (datos(i) - promedio) ** 2 suma_cuadrados_diferencias = 0.0 suma_cuadrados_diferencias = suma_cuadrados_diferencias + & cuadrados_diferencias(i) desviacion = sqrt(suma_cuadrados_diferencias / (N - 1))
print *, 'Promedio:', promedio print *, 'Desviacion:', desviacion end program desviacion_estandar Usando operaciones que operan sobre los arreglos completos, el código queda mucho más sencillo: program desviacion_estandar integer, parameter :: N = 10 real, dimension(n) :: datos, cuadrados_diferencias real :: suma_datos, suma_cuadrados_diferencias real :: promedio, desviacion integer :: i print *, 'Ingrese', N, 'datos' read *, datos(i) promedio = sum(datos) / N desviacion = sqrt(sum((datos - promedio) ** 2) / (N - 1)) print *, 'Promedio:', promedio print *, 'Desviacion:', desviacion end program desviacion_estandar Ejercicio: cálculo de la moda Escribir un programa que reciba como entrada veinte números enteros, y que entregue como salida cuál es el número que aparece más veces: Ingrese 20 datos 7 7 17 5-20 -20 10 17 66 12 3 La moda es
Strings Un string es un tipo de datos para representar texto. Al igual que los arreglos, una variable de tipo string debe tener un tamaño fijo durante todo el programa, que es el máximo largo en caracteres del texto que puede contener. La sintaxis para declarar un string de largo N es: character(len=n) :: nombre Por ejemplo, el siguiente programa pregunta el nombre del usuario y lo saluda: program hola character(len=20) :: nombre read *, nombre print *, 'Hola, ', nombre end program hola Los strings literales se representan entre comillas simples: nombre = 'Fulanito' El texto contenido por una variable de tipo string siempre tiene el mismo largo que el declarado. Si se asigna un texto más corto, es rellenado con espacios. Por ejemplo, si la variable nombre es un string de largo 10, entonces la salida del siguiente código: nombre = 'Pepe' print *, 'Hola ', nombre, '!' es la siguiente: Hola Pepe! Si se intenta almacenar un string cuyo largo es mayor a la capacidad de la variable, el valor es cortado para que entre. Por ejemplo, en el siguiente programa, si la entrada es Guadalupe, la salida será Guad: program muy_corto character(len=) :: s read *, s print *, s end program muy_corto Funciones trim y len_trim Para obtener el valor de un string sin los espacios de relleno al final hay que usar la función trim: nombre = 'Pepe' print *, 'Hola', trim(nombre), '!' La salida será: Hola Pepe!
El largo de un texto sin incluir los espacios del final puede ser obtenido con la función len_trim: character(len=20) :: texto texto = 'paralelepipedo' print *, len_trim('')! la salida es 0 print *, len_trim('texto')! la salida es 5 print *, len_trim(texto)! la salida es 1 Leer una línea completa Cuando se usa read para pedir un string al usuario, el texto leído sólo incluye hasta el primer espacio. Por ejemplo, si el usuario ingresa el texto Perico Los Palotes, la variable sólo contendrá el valor 'Perico'. La manera de leer un string hasta el final de la línea, incluyendo los espacios, es reemplazando el asterisco de la sentencia read con el indicador de formato '(A)': read '(A)', nombre Concatenación de strings La concatenación de strings es la operación de pegar dos strings uno después del otro. Por ejemplo, al concatenar 'hola ' y 'mundo', se obtiene el string 'hola mundo'. En Fortran, la concatenación de strings es representada usando el operador //: a = 'perro' b = 'gato' c = trim(a) // trim(b) print *, c! imprime 'perrogato' Substrings Uno puede extraer una sección de un string, obteniendo un nuevo string como resultado, usando la siguiente sintaxis: string(inicio:final) donde inicio y final son números enteros indicando las posiciones de inicio y de término del substring dentro del string. El siguiente programa muestra los resultados de algunos ejemplos de substrings: program substrings character(len=20) :: s s = 'paralelepipedo' print *, s(1:20)! paralelepipedo print *, s(:8)! alele print *, s(10:)! print *, s(12:)! edo print *, s(:)! para print *, s(7:7)! l end program substrings
Ordenamiento Burbuja Existen numerosos algoritmos para ordenar. A continuación se verá Ordenamiento Burbuja (bublesort). Idea: vamos comparando elementos adyacentes y empujamos los valores más livianos hacia arriba (los más pesados van quedando abajo). Idea de la burbuja que asciende, por lo liviana que es. integer :: i, j, N do i = N-1, 1, -1 do j = 1, i, j++ if (V(j)>V(j+1)) tmp = V(j) V(j)=V(j+1) V(j+1)=tmp end if