INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti ARREGLOS EN PASCAL. Un arreglo en cualquier lenguaje de programación es una sucesión consecutiva de bytes en memoria. Los arreglos pueden representar: Matrices (de 2 ó más dimensiones). Vectores (de una sola dimensión). La cantidad de bytes que ocupa un arreglo depende del tipo de dato que almacene cada domicilio. Así un arreglo de 4 domicilios de tipo char ocupará 4 bytes, mientras que un arreglo de 4 domicilios de tipo double ocupará 32 bytes. Este es un dato muy a tener en cuenta cuando se dimensiona un arreglo a fin de no sobrecargar demasiado la memoria. La forma clásica de una matriz de m x n que nosotros representamos como: m [filas] n [columnas] en una computadora no existe: allí los arreglos son siempre lineales. La simulación a una matriz bidimensional se obtiene como (por ejemplo para una matriz M de 3 x 10): 1 10 11 Fila 1 20 Fila 2 30 Fila 3 La posición correspondiente para el elemento [2,4] vendría dada por la expresión: Posición de M[2,4] = PosInicio + [(Fila – 1) x DIM2] + (Col-1) Posición de M[2,4] = PosInicio + (2 – 1) x 10 + 3 Posición de M[2,4] = 13 Por supuesto, hemos asumido que cada elemento del arreglo contiene un dato de tipo char o byte que solo ocupa 1 byte de memoria. En caso de que cada domicilio contuviera un dato de mayor longitud, por ejemplo de tipo Word, haríamos la siguiente modificación: Posición de M[2,4] = PosInicio + [(Fila – 1) x DIM2 + (Col - 1)] x Sizeof(Tipo) Es posible obtener una expresión para 3 dimensiones, pero normalmente trabajaremos solo hasta 2. Clase Teórica Nro 9 Pág 1/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti Declaración formal de un arreglo en Pascal. var Mat : array[DIM1,DIM2]of <Tipo>; En el cual DIM se especifica como un subrango de tipo ordinal que tiene un límite inferior y un límite superior: var Mat : array[1..4,1..5]of integer; Vect : array[1..100]of boolean; Letras: array[1..27]of char; etc. En realidad lo conveniente es crear un “alias” para los arreglos, mediante una declarativa type: const DIM1 = 4; DIM2 = 5; type TMat = array[1..DIM1,1..DIM2]of integer; TVect = array[1..100]of boolean; etc, Luego en el bloque var ponemos: var Mat : TMat; V1 : TVect; etc. El bloque type en realidad permite construir nuevos tipos de datos pero basados en los que ya se hallan predefinidos en el lenguaje. El límite inferior y superior de cada dimensión no tiene por qué arrancar siempre en 1 ni siquiera ser de tipo numérico. Las siguientes declarativas son perfectamente posibles: type TMat = array[‘A’..’Z’]of char; TVect = array[-10..-5]of double; En el primer caso la variable de control de lazo deberá ser de tipo char y moverse entre estos dos límites: var c : char; for c:=’A’ to ‘Z’ do ..... Cómo se accesa un domicilio de un arreglo. Los elementos de un arreglo pueden accesarse para leer o para escribir su contenido. La forma de hacerlo es: M[Fila,Col]:=....... Vect[i] :=..... Clase Teórica Nro 9 Pág 2/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti ó bien: if(Mat[i,j]=....) then ..... Para asignar por completo un arreglo: for i:=1 to DIM1 do for j:=1 to DIM2 do M[i,j]:=20+random(81); Para mostrarlo en pantalla: for i:=1 to DIM1 do begin for j:=1 to DIM2 do write(M[i,j]:4); writeln; end; Nótese que hemos utilizado la sentencia write( ) con formato para imprimir cada fila completa sobre el mismo renglón y encolumnando con 4 espacios. El writeln sólo, se emplea para bajar un renglón. Un caso particular de arreglos: las cadenas. Hasta ahora hemos estudiado un tipo individual de datos: los char o caracteres, que representan cualquier elemento de la tabla ASCII (American Standard Code Information Interchange) o Código Standard Americano para el Intercambio de Información. En esta tabla se hallan todos los caracteres alfabéticos, numéricos, de puntuación, caracteres especiales y caracteres de control. A nosotros sólo nos interesa los alfabéticos y numéricos. A cada caracter le es asignado un valor numérico único, por ejemplo: A B C .... a b c ... 65 66 67 0 1 2 48 49 50 97 98 99 { } [ 123 125 91 Así, al pulsar un caracter cualquiera del teclado, el mismo genera automáticamente alguno de estos códigos. Cuando muchos caracteres conforman palabras y texto, Pascal provee un tipo especial de dato que permite manejarlos de forma muy cómoda y sencilla: los datos de tipo string. Este tipo especial de dato se trata de un arreglo de char, aunque en su sintaxis no aparezca la declarativa array[...]of char. Su declarativa es la siguiente: var Texto : string; Frase : string[80]; La primera (string), es la declarativa por defecto. Pascal asigna 255 espacios para almacenar caracteres. Si lo que vamos a manejar son cadenas pequeñas, podemos acotar la cantidad de domicilios colocando entre corchetes el espacio requerido. Clase Teórica Nro 9 Pág 3/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti El domicilio 0 (cero) tiene un uso muy particular: Pascal almacena allí (en forma de equivalente char) la cantidad de caracteres que han ingresado a la cadena. De esta forma: Frase:=’Programación en Turbo Pascal’; que contiene 28 caracteres, se almacena como: 0 Pr og r a m a c i ó n en Turbo Pascal Equivalente char de la longitud de la cadena Cómo determinar la longitud de una cadena. Pascal provee una función específica: length( var string); Que retorna un entero equivalente a la cantidad de caracteres de la cadena. De esta manera: Longitud:=length(Frase) quedaría cargado con la magnitud 28. Cuándo emplear arreglos en un problema. Imaginemos que disponemos de una frase en la cual deseamos detectar la cantidad de vocales a, e, i, etc., presentes en la misma. type var TVoc = array[1..5]of integer; Voc : TVoc; Frase : string; i : integer; begin clrscr; highvideo; Frase:=’Esta es una frase breve de prueba’; for i:=1 to 5 do Voc[i]:=0; for i:=1 to lenght(Frase) do case Frase[i] of ‘a’,’A’ : Voc[1]:=Voc[1]+1; ‘e’,’E’ : Voc[2]:=Voc[2]+1; ‘i’,’I’ : Voc[3]:=Voc[3]+1; ‘o’,’O’ : Voc[4]:=Voc[4]+1; ‘u’,’U’ : Voc[5]:=Voc[5]+1; end; Clase Teórica Nro 9 Pág 4/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti for i:=1 to 5 do writeln(‘Vocal ‘,chr(64+i),’=’,Voc[i]); readkey; end. Aquí aparecen un par de cositas nuevas: una extensión de la instrucción case y una instrucción nueva: chr( ). La estructura case permite varias posibilidades. En una clase anterior la mostrábamos con un listado de constantes aisladas: case VarOrdinal of caso 1 : begin instrucciones 1; end; case 2 : begin instrucciones 2 ; end; case 3 : begin instrucciones 3; end; .......... case n : begin instrucciones n; end; end; También admite la siguiente sintaxis: case VarOrdinal of Valor1 .. Valor2 : begin instrucciones 1; end; Valor3 .. Valor4 : begin instrucciones 2; end; etc. end; en la cual cada opción se trata de un subrango, como las categorías en los deportes: case Edad of 5 .. 7 : writeln(‘categoría infantil’); 7 .. 10 : writeln(‘ categoría superjuvenil’); 10..13 : writeln(‘ ...................................’); etc. end; Otra sintaxis admitida es una especie de enumeración: case VarOrdinal of valor1,valor2,... : begin instrucciones 1; end; valor5,valor6,... : begin instrucciones 2; end; etc. end; Obviamente utilizaremos esta notación cuando los valores de cada opción NO SEAN CONSECUTIVOS, como en el caso de las vocales. Volviendo a nuestro problema con los arreglos de char, no hubo ninguna dificultad para referirnos a cada caracter almacenado en el arreglo, con la consabida notación: Frase[ i ] Clase Teórica Nro 9 Pág 5/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti IMPORTANTE: En un arreglo (matriz o vector) perteneciente a un determinado tipo, el contenido de cada domicilio goza de las mismas propiedades que un dato aislado perteneciente al mismo tipo. Por ejemplo: var n : integer; V : array[1..10]of integer; V[1], V[2], etc., gozan de las mismas propiedades que n, pues se trata de enteros: DIV división entera. MOD resto de una división entera. pred predecesor. succ sucesor. Otro ejemplo en el cual conviene utilizar arreglos es el siguiente: Convertir un número binario en su equivalente decimal. uses crt; type TBin = array[1..8]of byte; var NBin : TBin; NDec : integer; PesoDig : integer; i : byte; begin clrscr; highvideo; PesoDig:=128; NDec:=0; for i:=8 downto 1 do begin write('NBin ',i,'='); readln(NBin[i]); NDec:=NDec+NBin[i]*PesoDig; PesoDig:=PesoDig DIV 2; end; write('El binario ingresado fue '); for i:=8 downto 1 do write(NBin[i]); writeln; writeln('Su equivalente decimal es ',NDec); readkey; end. Clase Teórica Nro 9 Pág 6/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti Como en toda base de numeración los dígitos de mayor peso son los que están más a la izquierda, hemos trabajado con un lazo for decreciente (downto) de 8 hasta 1. Recuerde que los pesos binarios son: Pesos 128 64 32 16 8 4 2 1 --------------------------------------------------------------------------8 7 6 5 4 3 2 1 Posiciones En realidad a la primera posición es cero, pero a fin de no trabajar con potencias de 2, le llamaremos 1. Además recuerde que los dígitos binarios sólo pueden ser 1’s o 0’s. Imaginemos que ingresamos: 11001011 Para obtener su equivalente decimal tendríamos que hacer: 1x 128 + 1 x 64 + 0 x 32 + 0 x 16 + 1 x 8 + 0 x 4 + 1 x 2 + 1 x 1 o sea cada dígito por su correspondiente peso (como se vio en la primera clase). Esta sumatoria de productos se halla implementada dentro del lazo for. Analícela. Producto matricial de dos matrices. Si bien las reglas de este producto no son complicadas, hay que trabajar un poco con los lazos. En primer lugar dos matrices cualesquiera no pueden multiplicarse matricialmente salvo que cumplan con la siguiente condición: Cantidad de filas de la segunda matriz = Cantidad de columnas de la primera. x a [4,4] = b [4,2] c [4,2] c[1,1] = a[1,1] x b[1,1] + a[1,2] x b[2,1] + a[1,3] x b[3,1] + a[1,4] x b[4,1] c[1,2] = a[1,1] x b[1,2] + a[1,2] x b[2,2] + a[1,3] x b[3,2] + a[1,4] x b[4,2] c[2,1] = a[2,1] x b[1,1] + a[2,2] x b[2,1] + a[2,3] x b[3,1] + a[2,4] x b[4,1] c[2,2] = a[2,1] x b[1,2] + a[2,2] x b[2,2] + a[2,3] x b[3,2] + a[2,4] x b[4,2] etc. Clase Teórica Nro 9 Pág 7/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti Ahora tenemos que implementar un código Pascal para que esto se realice automáticamente. uses crt; const DIM1 DIM2 DIM3 DIM4 = = = = 4; 4; 4; 2; type TMat1 = array[1..DIM1,1..DIM2]of integer; TMat2 = array[1..DIM3,1..DIM4]of integer; var a b c i,j,k S Fila Col : : : : : : : TMat1; TMat2; TMat2; byte; integer; byte; byte; begin clrscr; highvideo; randomize; { --- Carga la matriz a[ ] ----- } for i:=1 to DIM1 do begin for j:=1 to DIM2 do begin a[i,j]:=random(11); write(a[i,j]:3); end; writeln; end; writeln; writeln; { --- Carga la matriz b[ ] ----- } Fila:=1; Col:=20; for i:=1 to DIM3 do begin for j:=1 to DIM4 do begin b[i,j]:=random(11); gotoxy(Col+(j-1)*3,Fila+i-1); write(b[i,j]); end; writeln; end; { --- realiza el producto matricial de a x b } Fila:=1; Col:=30; Clase Teórica Nro 9 Pág 8/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti for i:=1 to DIM1 do for k:=1 to DIM4 do begin S:=0; for j:=1 to DIM2 do S:=S+a[i,j]*b[j,k]; c[i,k]:=S; gotoxy(Col+(k-1)*5,Fila+i-1); write(c[i,k]); end; readkey; end. Si este problema ha sido correctamente comprendido, no habrá dificultad para los próximos ejemplos. Código de colores para resistencias eléctricas. En electrónica los valores de las resistencias suelen (o solían) estar codificadas en bandas de colores que tenían el siguiente significado: Banda1 Banda2 Bada3 Primera cifra. Segunda cifra. Número de ceros a agregar (multiplicador). Los colores establecidos eran los siguientes: negro marrón rojo naranja amarillo verde celeste lila gris blanco 0 1 2 3 4 5 6 7 8 9 qué mejor que colocar estos valores dentro de un vector de 10 domicilios: var Cod : array[0..9]of string[12]; begin Cod[0]:=’negro’; Cod[1]:=’marron’; Cod[2]:=’rojo’; etc. Clase Teórica Nro 9 Pág 9/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti De esta manera cuando necesitemos un código buscamos el color y nos quedamos con el índice. uses crt; type TVectCod = array[0..9]of string[12]; var Cod B1 B2 B3 i Mult Val1 Val2 Val3 R : : : : : : : : : : TVectCod; string[12]; string[12]; string[12]; integer; longint; integer; integer; integer; longint; begin clrscr; highvideo; Cod[0]:='negro'; Cod[1]:='marron'; Cod[2]:='rojo'; Cod[3]:='naranja'; Cod[4]:='amarillo'; Cod[5]:='verde'; Cod[6]:='celeste'; Cod[7]:='lila'; Cod[8]:='gris'; Cod[9]:='blanco'; B1:='rojo'; B2:='amarillo'; B3:='verde'; for i:=0 to 9 do begin if(B1=Cod[i])then Val1:=i; if(B2=Cod[i])then Val2:=i; if(B3=Cod[i])then Val3:=i; end; Mult:=1; for i:=1 to Val3 do Mult:=Mult*10; R:=(Val1*10+Val2)*Mult; writeln('R = ',R,' Ohms'); readkey; Clase Teórica Nro 9 Pág 10/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti end. (* --- Ejemplo ARR_04.PAS Cargar aleatoriamente una matriz de 5 x 7 con enteros entre 10 y 50 y mostrarla en pantalla. A continuación realizar la suma de los términos de cada fila mostrando dichos resultados a continuación de cada fila en pantalla. ¿Cual fue la máxima suma obtenida? ¿En cual fila se produjo? Indicar estos dos últimos ítems un poco mas abajo de la matriz. ------------------------------------------------------ *) uses crt; const DIM1 = 5; DIM2 = 7; type TMat = array[1..DIM1,1..DIM2]of integer; var Mat Smax Sparc FSmax i,j : : : : : TMat; integer; integer; byte; byte; { suma maxima } { suma parcial } { fila para suma maxima } begin (* main *) clrscr; highvideo; randomize; Smax:=0; for i:=1 to DIM1 do begin Sparc:=0; for j:=1 to DIM2 do begin Mat[i,j]:=10+random(51); write(Mat[i,j]:3); Sparc:=Sparc+Mat[i,j]; end; write('S=':8,Sparc); writeln; if(Sparc>Smax)then begin Smax:=Sparc; FSmax:=i; end; end; writeln; writeln('Suma maxima = ',Smax); writeln('Fila de Smax = ',FSmax); readkey; Clase Teórica Nro 9 Pág 11/12 INFORMATICA CBI – 2013 Dictado : Ing. Juan Manuel Conti end. Clase Teórica Nro 9 Pág 12/12