Clase Teórica Nro 9

Anuncio
INFORMATICA CBI – 2015
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 (no olvidar que
la memoria es secuencial). 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:
Offset para M[2,4] = PosInicio + [(Fila – 1) x DIM2] + (Col-1)
Offset para M[2,4] = PosInicio + (2 – 1) x 10 + 3
Offset para M[2,4] = 13
Offset significa el desplazamiento desde PosIni.
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:
Offset para M[2,4] = PosInicio + [(Fila – 1) x DIM2 + (Col - 1)] x Sizeof(Tipo)
Clase Teórica Nro 9
Pág 1/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
Es posible obtener una expresión para 3 dimensiones, pero normalmente trabajaremos
solo hasta 2.
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/14
INFORMATICA CBI – 2015
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];
Clase Teórica Nro 9
Pág 3/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
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.
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;
Clase Teórica Nro 9
Pág 4/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
‘o’,’O’ : Voc[4]:=Voc[4]+1;
‘u’,’U’ : Voc[5]:=Voc[5]+1;
end;
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:
Clase Teórica Nro 9
Pág 5/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
Frase[ i ]
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/14
INFORMATICA CBI – 2015
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.
Procedimientos y Arreglos.
Este es el momento de ver otras de las aplicaciones de los parámetros por referencia:
cuando un subprograma recibe un arreglo sobre el cual debe trabajar.
(* --- INFORMATICA 2014 - Procedimientos y arreglos 01.pas ---Un procedimiento denominado CargarMatriz( ) recibirá como único parámetro una
matriz de enteros de 10 x 15 y le asignará valores aleatorios en el rango 10, 50 mostrándola por pantalla en forma matricial. Este procedimiento también efectuará la suma
de cada fila, y dicho resultado será mostrado a la derecha de la matriz (a continuación
de cada fila).
Como forma de verificación, vuelva a imprimir la matriz, pero esta vez desde el main( ),
posterior a la invocación.
NOTA: Al pasar la matriz como parámetro variable, TODO lo que se
haga sobre ella subsistirá al finalizar la invocación.
-------------------------------------------------------------------------------------------------------- *)
uses crt;
const DIM1
DIM2
type TMat
var
Mat
i,j
=
=
=
:
:
10;
15;
array[1..DIM1,1..DIM2]of integer;
TMat;
integer;
Clase Teórica Nro 9
Pág 7/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
{ ---------------------------------------------------------------}
procedure CargarMatriz( var M : TMat);
var SumaFila : integer;
i,j
: integer;
begin
for i:=1 to DIM1 do begin
SumaFila:=0;
textcolor(WHITE);
for j:=1 to DIM2 do begin
M[i,j]:=10+random(41);
SumaFila:=SumaFila+M[i,j];
write(M[i,j]:3);
end;
textcolor(LIGHTRED);
writeln(SumaFila:6);
end;
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat);
readkey;
textcolor(LIGHTGREEN);
writeln('---------------------------------------------------');
textcolor(WHITE);
for i:=1 to DIM1 do begin
for j:=1 to DIM2 do write(Mat[i,j]:3);
writeln;
end;
end.
MUY IMPORTANTE: En la declarativa de parámetros formales de un subprograma, ya
sea función o procedimiento, NO SE PERMITEN DECLARACIONES ESTRUCTURADAS, pero en cambio sí un tipo simple creado en la línea type. Por eso es que hemos
declarado un tipo TMat que en realidad representa un dato estructurado: una matriz.
(* --- INFORMATICA 2014 - Procedimientos y arreglos 02.pas ---La misma matriz anterior, pero ahora no sumaremos cada fila sino que simplemente la
cargaremos, la mostraremos y desde el procedimiento se invocara una función de
nombre SumarDiagonal( ) que la recibirá como parámetro por referencia y determinara la suma su diagonal principal (valor que retornara). Este valor será mostrado en
pantalla desde el procedimiento CargarMatriz( ).
--------------------------------------------------------------------------------------------------------- *)
uses crt;
const DIM = 10;
type TMat = array[1..DIM,1..DIM]of integer;
var
Mat : TMat;
Clase Teórica Nro 9
Pág 8/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
{ ------------------------------------------------------------- }
function SumarDiagonal(var M : TMat):integer;
var SumaDiag : integer;
i
: integer;
begin
SumaDiag:=0;
for i:=1 to DIM do
SumaDiag:=SumaDiag+M[i,i];
SumarDiagonal:=SumaDiag;
end;
{ ---------------------------------------------------------------}
procedure CargarMatriz( var M : TMat);
var i,j
: integer;
begin
for i:=1 to DIM do begin
for j:=1 to DIM do begin
M[i,j]:=10+random(41);
write(M[i,j]:3);
end;
writeln;
end;
writeln;
writeln('SUMA DE LA DIAG PRINCIPAL : ',SumarDiagonal(M));
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat);
readkey;
end.
Este es un caso en el cual desde un subprograma se invoca los servicios de otro suprograma: desde el procedimiento CargarMatriz( ) se ha llamado a la función SumarDiagonal( ) la cual retorna a dicho procedimiento el valor solicitado: la suma de la diagonal principal.
(* --- INFORMATICA 2014 - Procedimientos y arreglos 03.pas ---Un procedimiento denominado CargarMatriz( ) recibirá como parámetros una matriz
de enteros de 10 x 15 y un valor dado. La matriz deberá ser cargada con valores aleatorios en el rango 100, 999 y mostrada por pantalla. Este procedimiento también encontrará el máximo valor almacenado (no lo mostrará por pantalla), pero si en cambio
se mostrará desde el punto de invocación (en el main( )).
--------------------------------------------------------------------------------------------------------- *)
uses crt;
const DIM1 = 10;
DIM2 = 15;
Clase Teórica Nro 9
Pág 9/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
type
var
TMat = array[1..DIM1,1..DIM2]of integer;
Mat : TMat;
Max : integer;
{ ------------------------------------------------------------- }
procedure CargarMatriz( var M
: TMat;
var Max : integer);
var i,j
: integer;
begin
Max:=0;
for i:=1 to DIM1 do begin
for j:=1 to DIM2 do begin
M[i,j]:=100+random(900);
write(M[i,j]:4);
if(M[i,j]>Max)then Max:=M[i,j];
end;
writeln;
end;
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat,Max);
writeln(' ------------------------------------------------ ');
writeln('MAXIMO : ',Max);
readkey;
end.
Nótese que los dos parámetros del procedimiento han sido recibidos por referencia, lo
cual indica que en el punto de invocación (main), se mantendrán todas las modificaciones que el procedure haga sobre la matriz y la variable pasadas.
(* --- INFORMATICA 2014 - Procedimientos y arreglos 04.pas ---Un procedimiento denominado CargarMatriz( ) recibirá como parámetros una matriz
de enteros de 10 x 15 y un vector dado, también de enteros. La matriz deberá ser cargada con valores aleatorios en el rango 100, 999 y mostrada por pantalla. Este procedimiento buscará todos los pares que hayan salido y lo almacenará en el vector recibido. Este vector será mostrado desde el main.
---------------------------------------------------------------------------------------------------------- *)
uses crt;
const DIM1
DIM2
type TMat
TVect
=
=
=
=
var
: TMat;
: TVect;
: integer;
Mat
Vect
i
10;
15;
array[1..DIM1,1..DIM2]of integer;
array[1..DIM1*DIM2]of integer;
Clase Teórica Nro 9
Pág 10/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
{ ------------------------------------------------------------- }
procedure CargarMatriz( var M
: TMat;
var V
: TVect );
var i,j,k : integer;
begin
for i:=1 to DIM1*DIM2 do V[i]:=0;
k:=1;
for i:=1 to DIM1 do begin
for j:=1 to DIM2 do begin
M[i,j]:=100+random(900);
write(M[i,j]:4);
if(M[i,j] MOD 2 =0)then begin
V[k]:=M[i,j];
k:=k+1;
end;
end;
writeln;
end;
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat,Vect);
writeln(' ------------------------------------------------ ');
i:=1;
while(Vect[i]<>0)do begin
write(Vect[i]:4);
i:=i+1;
end;
readkey;
end.
Ahora a nuestro famoso procedimiento CargarMatriz( ) le agregaremos más generalidad estableciendo que los limites de los aleatorios ingresen como parámetros. También estableceremos que solamente formarán parte de la matriz aquellas magnitudes
cuyo dígito central sea 5. Para ello nos valdremos de los operadores DIV y MOD. Finalmente este procedimiento rescatará en un vector todos aquellos valores de la matriz cuya suma de dígitos sea igual a 12. He aquí los códigos:
(* --- INFORMATICA 2014 - Procedimientos y arreglos 05.pas ---Un procedimiento denominado CargarMatriz( ) recibirá como parámetros una matriz
de enteros de 10 x 15, un vector de enteros y dos enteros simples. La matriz deberá
ser cargada con valores aleatorios en el rango establecido por los enteros simples, pero con la condición de que todos los valores posean el digito central igual a 5. También
deberá mostrarla por pantalla.
Este procedimiento detectara también todos aquellos valores cuya suma de dígitos
sea igual a 12 y los cargara en el vector.
Este vector será mostrado desde el main.
-------------------------------------------------------- *)
Clase Teórica Nro 9
Pág 11/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
uses crt;
const DIM1
DIM2
type TMat
TVect
=
=
=
=
var
: TMat;
: TVect;
: integer;
Mat
Vect
i
10;
15;
array[1..DIM1,1..DIM2]of integer;
array[1..DIM2]of integer;
{ ------------------------------------------------------------- }
procedure CargarMatriz( var M
: TMat;
var V
: TVect;
Linf : integer;
Lsup : integer
);
var i,j,k : integer;
Dig1 : integer;
Dig2 : integer;
Dig3 : integer;
begin
for i:=1 to DIM1*DIM2 do V[i]:=0;
k:=1;
for i:=1 to DIM1 do begin
for j:=1 to DIM2 do begin
repeat
M[i,j]:=100+random(900);
Dig1:= M[i,j] MOD 10;
Dig2:=(M[i,j] DIV 10) MOD 10;
Dig3:= M[i,j] DIV 100;
until(Dig2=5);
write(M[i,j]:4);
if(Dig1+Dig2+Dig3 = 12)then begin
V[k]:=M[i,j];
k:=k+1;
end;
end;
writeln;
end;
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat,Vect,100,900);
writeln(' ------------------------------------------------ ');
i:=1;
while(Vect[i]<>0)do begin
write(Vect[i]:4);
i:=i+1;
end;
readkey;
end.
Clase Teórica Nro 9
Pág 12/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
(* --- INFORMATICA 2014 - Procedimientos y arreglos 06.pas ---Un procedimiento denominado CargarMatriz( ) recibirá como parámetros una matriz
de enteros de 10 x 15, dos enteros simples (Linf y Lsup) y otros dos parámetros adicionales. La matriz deberá ser cargada con valores aleatorios en el rango establecido
por Linf y Lsup. También deberá mostrarla por pantalla.
Este procedimiento detectara también cual de todas las filas posee suma máxima y
cual fue esa suma, valores que retornara a través de los dos parámetros adicionales.
----------------------------------------------------------------------------------------------------------- *)
uses crt;
const DIM1
DIM2
type TMat
var
= 10;
= 15;
= array[1..DIM1,1..DIM2]of integer;
Mat
FilaSumaMax
SumaMaxima
i
:
:
:
:
TMat;
integer;
integer;
integer;
{ ------------------------------------------------------------- }
procedure CargarMatriz( var M
: TMat;
var FilaSumaMaxima : integer;
var SumaMaxima
: integer;
Linf
: integer;
Lsup
: integer
);
var i,j
: integer;
SumaParcial : integer;
{ suma parcial para cada fila }
begin
SumaMaxima:=0;
for i:=1 to DIM1 do begin
SumaParcial:=0;
for j:=1 to DIM2 do begin
M[i,j]:=Linf+random(Lsup-Linf);
SumaParcial:=SumaParcial+M[i,j];
write(M[i,j]:4);
end;
writeln;
if(SumaParcial>SumaMaxima)then begin
SumaMaxima:=SumaParcial;
FilaSumaMaxima:=i;
end;
end;
end;
{ -------------------------------------------------------------- }
begin (* main *)
clrscr; randomize;
CargarMatriz(Mat,FilaSumaMax,SumaMaxima,100,900);
writeln('-------------------------------------------------');
writeln('SUMA MAXIMA
: ',SumaMaxima);
Clase Teórica Nro 9
Pág 13/14
INFORMATICA CBI – 2015
Dictado : Ing. Juan Manuel Conti
writeln('FILA P/SUMA MAXIMA : ',FilaSumaMax);
readkey;
end.
Clase Teórica Nro 9
Pág 14/14
Descargar