jueves, marzo 31, 2005

Estructuras lineales

*Arreglos
*Registros


Arreglos
Conjunto de elementos del mismo tipo.Se almacena de manera adyacente y oucpa los bits que sean necesarios.


Cadenas (strings)
Un arreglo de caracteres delimitado por comillas, indica el principio y fin. Cada caracter se almacena en una posición del arreglo.

Veamos como quedaria la estructura:

En C:

char texto[10];
texto="hola";



Si queremos sacar solo la L, quedaria lo siguiente:

printf("%c",texto[2];

Es el numero dos, ya que en c, se cuenta desde cero y otros programas, menos en pascal... eso quiere decir que:

H=0
O=1
L=2
A=3



En pascal:

texto:string[10];
texto:='hola';

Si queremos imprimir la L, quedaria lo siguiente:

writeln(texto[3]);

Es el numero tres, ya que Pascal inicia desde 1, esto quiere decir que:

H=1
O=2
L=3
A=4


La maquina saca estos resultados con las siguientes formulas:

En C:
loc(i)=Li+c(i)

En pascal:
loc(i)=Li+c(i-1)

Veamos un ejemplo que no se puede realizar:

char texto[10];
texto='hola';

texto[5]='a';
texto[10]='r';

Aqui imprimiria la a sin ningun problema, ya que el texto contiene 10 bits o espacios para almacenar una letra.
printf("%c",texto[5]);

Pero en este otro, hay un problema, ya que no llega a 10 sino a 0 caracteres (recordemos que C inicia desde 0),surgiria un error y encimaria, habria muchos problemas, hay compiladores que lo toman bien y otros te avisan del error, depende del tipo de compilador, pero lo mejor es evitar este tipo de errores.
printf("%c",texto[10]);

Supongo que ah de surgir la duda de porque pascal inicia con 1 y los demas programas o la mayoria inician con 0, bueno la explicacion es sencilla:

Tenemos la palabra : HOLA
Esta conformada por 4 caracteres

H=1
O=2
L=3
A=4

Lo que hace pascal en poner en el cero los caracteres que ocupo, esto quiere decir que HOLA quedaria en un compilador de pasacal asi:

4=0 <--- Es cuatro porque hola ocupa 4 bits
H=1
O=2
L=3
A=4

Si tuvieramos mauricio quedaria :

8=0 ***
m=1
a=2
u=3
r=4
i=5
c=6
i=7
o=8

***Ya que mi nombre ocupa 8 bits, se le pone el 8.

Sabemos que:
Char = 1byte
Entero = 2Bytes
Flotante = 4 Bytes
Double = 8 Bytes


Bueno todo lo que hemos estado haciendo, es de una manera "lenta" por asi decirlo, ya que la maquina cuando le decimos que nos muestre:

printf("%c",texto[3]); <- Busca la posición 3 y la imprime. H = texto[0] ___54375
O = texto[1] ___54376
L = texto[2] ___54377
A = texto[3] ___54378

Lo que viene en texto[x], es donde esta almacenado la letra.
Se preguntaran que son esos numeros (54375...) Es la memoria del caracter, en el caso de la A seria 54378

Entonces aqui inician los dichosos apuntadores.

Apuntadores

Un apuntador es una variable que almacena direcciones de memoria. El apuntador sirve mas que nada para darle una dirección directa (Es mas rapido para la computadora), quizas a simpel vista no se note la velocidad, pero a la larga cuando se necesiten mas de 10000 de caracteres... se hara lenta la maquina, y el apuntador hace que el programa corra mas rapido..

Realmente el arreglo es un apuntador al inicio del arreglo:
arreglo -> Texto -> Apuntador

En texto se almacena la direccion de memoria, y es una variable.

Para accesar a los elementos de una arreglo el procesador obtiene el primer byte de este elemento usando una función de direccionamiento (Addressing Fuction).

En el caso de un vector:

loc(i)=Li+c(i-1) <- Pascal loc(i)=Li+c(i-1) <- En C


i= Elemento que se quiere (Indice del arreglo)
Li= Direccion de memoria donde comienza almacenarser el arreglo
c= Tamaño en byte del elemento que se quiere obtener.

Tenemos el arreglo Texto, para representarlo en apuntador seria de la siguiente forma:

374 _
-------
54375
<- Sabemos que este es la memoria, en este caso es el inicio del arreglo El apuntador puede estar almacenado en cualquier numero... no necesariamente uno fijo.

Si queremos ver:
printf("%c",texto[2]);

Se usaria la formula de la siguiente manera:

Loc(2)=54375+1(2)=54377

2 = El lugar que queremos
54375 = Inica nuestro arreglo
1 = Aqui es uno porque es un caracter 1 byte de char, si fuera int ocuparia 2, float 4, ...
2= Lugar que se quiere.

374 _
-------
54377 <- Aqui es donde se encuentra el texto[2]


Para entenderlo mejor seria:
Sabemos que en C, inicamos desde 0 esto quiere decir que el inicio del arreglo es 54377, el 1 seria 54378...

54375 54376 54377
___H_______O_______L
___0_______1_______2

Cuando guardamos en C:
scanf("%d",&x);

Realmente el & lo que hace es que x la ponga como apuntador.

& = Direccion de...


Queremos saber como nos daria las famosas direcciones en C, que en los ejemplos de arriba es 374 (Porque es donde almaceno el arreglo texto).

printf("%u",&texto);

%u = Entero sin signo
&texto = lo que hara es mostrarnos 374, que es la direccion de la variable.

Y para que nos muestre el numero del contenido, en el caso de arriba es 54375 seria:

printf(%u",*texto);

* = Contenido de...

Esto que vimos anteriormente solo nos imprime los numeros donde se encuentra la direcion y el contenido.
Ahora para que nos imprima el texto con y sin apuntador quedaria de la siguiente forma:

-Sin apuntador (que es lo que comunmente hacemos):
printf("%s",texto); <- Nos imprimira HOLA
-Con apuntador (que seria lo mejor):
printf("%s",*texto);

Como podemos ver usamos * ya que es donde esta el contenido.

Si ponemos atencion veremos que si queremos la direccion y el contenido en numeros (donde esta almacenado) usamos %u y cuando queremos el contenido en texto se usa %s,%c.....

Ahora si queremos una sola letra es cuestión de lógica:

HOLA

-Sin apuntador:
printf("%c",texto[2]); <-- Nos imprimira la L
-Con apuntador:
printf("%c",*(texto)+2));




Registros
Es una estructura de datos que diferencia de un arreglo puede almacenar informacion de distinto tipo, llamados campos.

Los registros se almacenan en memoria colocando los campos uno despues del otro, si se quiere la posición del campo I, la funcion de direccionamiento:

Ri=S1+S2+S3....-1

S= es el tamaño del componente aterior a i


La estructura en pascal seria:

type empleados = Record
nombre:string[30];
direccion:string[50];
telefono:tring[10];
RFC:string[12];
edad:integer;
sueldo:real;
end;

var
persona: empleados;
.
.
persona.nombre:='fulanito';
persona.direccion:='Niño perdido';
persona.telefono:='0123456';
persona.RFC:='ABCD123456';
persona.edad:=50;
persona.sueldo:=200000;


Entonces para encontrar la posicion de direccionamiento seria:

R5=S1+S2+S3+S4
=30+50+10+12
=102

El R5 es persona.edad, entonces se suman los espacios que ocupan los anteriores, esto quiere decir que ubicara en memoria los elementos en el numero 102.

Para leer la persona seria:
writeln(persona.edad);

Para guardarla
readln(persona.edad);

Como se puede ver es algo molesto estar poniedo persona...., persona. .... , hay una manera de resumirla, que seria de la siguiente manera:

with palabra do
begin
registros
end;


Quedaria de la siguiente forma:

with persona do
Begin
nombre:='fulanito';
direccion:='Niño perdido';
telefono:='0123456';
RFC:='ABCD123456';
edad:=50;
sueldo:=200000;
end;


Veamos ahora en C como quedaria :

struct empleados
{
char nombre[30];
char direccion[50];
int edad;
float sueldo;
}persona;

persona.nombre="fulanito";
persona.direccion="Niño perdido";
persona.edad=50;
persona.sueldo=200000;



Para imprimir todo el nombre:
printf("%s",persona.nombre);

Una sola letra:
printf("%c",persona.nombre[2]); /* Imprime la tercera letra */

Para guardar:
scanf("%d",&persona.edad);



Registros anidados
Son cuando hay registros dentro de otro registro...

La estructura seria la siguiente:

type destino=record
ciudad=record
nombre:string[20];
pais:string[15];
end;
arribo=record
hora:0..24; {No acepta mas del numero establecido}
minutos:0..59; {y los guarda como int}
end;
end;

var
avion:destino;

with avion do
begin
whit ciudad do
begin
nombre:='New York';
pais:='Estados unidos';
end;
with arribo do
begin
hora:=20;
minutos:=30;
end;
end;


Ahora imaginemos que queremos un registro de 1000 aviones.. seria bastante aburrido estar poniendolos todos.. para eso necesitariamos un Arreglo con registros.

Arreglo con registros

Es la combinacion como lo dice su nombre un arreglo con un registro... quedaria de la siguiente manera la estructura:


type destino=record
ciudad=record
nombre:string[20];
pais:string[15];
end;
arribo=record
hora:0..24; {No acepta mas del numero establecido}
minutos:0..59; {y los guarda como int} end;end;

Var
avion:array[1..1000] of destino ;
x:integer;

Begin
for x:=1 to 1000 do
Begin
with avion[x] do
begin
printf(ciudad.nombre);
end;
end;


Nos preguntaria el nombre del 1000 aviones...