martes, 10 de enero de 2017

ESTRUCTURAS

CAPÍTULO 8         ESTRUCTURAS 





En muchos lenguajes, se le permite al programador definir sus propios tipos de
datos a partir de los tipos atómicos. En C y C++ pasa lo mismo, y además existen de
antemano los tipos union, enumeración y estructura. Estos tipos definidos forman
parte del estandar de C, y por consiguientede C++, en éste último existe también el
tipo class.
Para los objetivos de este trabajo excluiremos el tipo class (clase), pero a lo largo del
capítulo mencionaremos en varias ocasiones este concepto para tener una idea de lo
que se trata.
ENUMERACIONES
En ocasiones habremos de declarar constantes enteras una tras otra con valores
consecutivos, por ejemplo:
const int a=0,b=1,c=2,d=3;
para evitar este tipo de declaraciones una tras otra, existe el tipo enumerativo. La
declaración anterior se puede hacer de una mejor forma:
enum {a,b,c,d};
86
Una enumeración puede ser global o local. Además de que puede tener un nombre
que los identifique, podemos indicar desde donde empieza la numeración.
enum meses { enero=1, febrero, marzo, abril, mayo, junio,
julio, agosto, septiembre, octubre, noviembre, diciembre};
Los valores que se le asignarán empiezan por 1 a enero, 2 a febrero y así
sucesivamente. Si se le asignase un 5 a marzo, entonces abril tendría un 6 y así
continuaría la numeración.
Después de hacer esta enumeración, se puede hacer una nueva a partir del nombre.
meses calendario;
Un ejemplo sencillo ilustrará nuestras ideas.
#include<iostream.h>
enum colores{rojo,amarillo,verde};
int main(){
        int i=0,contador=0;     //unos contadores
        colores semaforo;
        cout<<"este programa mostrara el tipo enumerativo,"
            <<" por medio de un semaforo de crucero"
            <<" simulado"<<endl;
        while(contador<3){
        semaforo=verde;
        cout<<"semaforo en verde, el peaton no pasa"<<endl;
        cout<<"el peaton pide el paso con un boton"
            <<"(presione enter)"<<endl;
        cin.get();
        semaforo=amarillo;
        cout<<"semaforo en amarillo, precaucion"<<endl;
        for(i=0;i<500000000;i++);
        semaforo=rojo;
        cout<<"semaforo en rojo, ALTO, pasa el peaton"<<endl;
        for(i=0;i<500000000;i++);
87
        contador++;
        }
        return 0;
}
Debemos tomar en cuenta que al declarar un tipo de variable en base a una
enumeración, en este caso una variable semaforo de tipo colores, sólo se podrá
asignar valores declarados dentro de esta, para el ejemplo anterior sólo puede tomar
valores rojo amarillo o verde.
UNIONES
El tipo de datos union puede contener datos de tipos y tamaños diferentes, esta
variable almacenará cualquier tipo de dato en una única localidad en memoria. Por
ejemplo:
union edificio{
int habitaciones;
int despachos;
char empresa[10];
};
declara un nuevo tipo de dato llamado “edificio”, para usar una variable de tipo
edificio bastará con hacer una declaración como:
edificio casa;
la variable casa tendrá el suficiente espacio en memoria para almacenar una cadena
(el tipo de dato de mayor longitud dentro de la union). Es responsabilidad del
programador extraer adecuadamente el tipo de dato deseado.
88
La forma en que está estructurada en la memoria nuestra variable es como la que
sigue:
Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 Byte9 Byte10
Espacio para las variables “habitaciones” y “despachos”
Espacio para la cadena
“empresa”
Cuando se almacena un entero y posteriormente una cadena, ésta última se escribe
sobre el espacio de memoria asignado al entero, y por lo tanto, el contenido se
pierde.
Practique con el siguiente programa.
#include<iostream.h>
#include<iomanip.h>
union edificio{
        int habitaciones;
        int despachos;
        char empresa[10];
};
int main(){
        edificio casa, agencia, gobierno;
        cout<<"cuantas habitaciones tiene tu casa?"<<endl;
        cin>>casa.habitaciones;
        cout<<"escribe el nombre de la agencia en la\
        que trabajas"<<endl;
        cin.ignore();
        cin.getline(agencia.empresa,10);
        cout<<"cuantos despachos tiene la oficina de gobierno \
        de tu localidad?"<<endl;
        cin>>gobierno.despachos;
     cout<<"cuantos despachos tiene el edificio de la agencia "
            <<agencia.empresa<<"?"<<endl;
89
        cin>>agencia.despachos;
        cout<<"edificio"<<setw(25)<<"habitaciones/despachos"
            <<endl;
        cout<<"casa"<<setw(18)<<casa.habitaciones<<endl;
        cout<<"agencia"<<setw(15)<<agencia.despachos<<endl;
        cout<<"gobierno"<<setw(14)<<gobierno.despachos<<endl;
        cin.ignore();
        cin.get();
        return 0;
}
Para accesar a los miembros de una variable de tipo union es necesario utilizar el
operador punto (.), seguido de la variable a extraer. En este ejemplo hemos extraído
un entero de la variable “casa” por medio de casa.habitaciones, si se hace una
extracción como casa.empresa no sabemos exactamente que es lo que aparecerá
porque pueden existir otros datos en esa área de la memoria asignada a esta
cadena; y si se hiciese lo contrario, asignar una cadena y luego extraer un entero,
seguramente no obtendremos lo que deseamos. Como con cualquier otro tipo de
datos, podemos realizar operaciones con el contenido de los miembros de la union,
operaciones básicas, envío como argumentos, conversiones, etc.
El uso de las variables de tipo union no es muy común, alguien seguramente habrá
querido extraer un tipo entero, luego asignar una cadena y posteriormente utilizar de
nuevo ese entero. Que útil seria que dentro de una sola variable podamos tener
oportunidad de extraer tanto un tipo como otro sin perder los datos, ¿se imagina
poder regresar mediante la instrucción return más de un dato?.
90
ESTRUCTURAS
Las estructuras son colecciones de elementos, los cuales pueden ser de diferente
tipo, y a diferencia de las uniones, en éstas no se comparte la misma área de
memoria para los elementos.
La forma de declarar una estructura es más o menos como sigue:
struct nombre_estructura{
tipo nombre_elemento1;
tipo nombre_elemento2;
};
Es entonces cuando podemos declarar una variable del tipo de la estructura,
funcionando el nombre de la estructura como un nuevo tipo de datos, de esta
manera, la nueva variable tendrá cada uno de los elementos declarados en ella.
nombre_estructura nueva_variable;
Para acceder a cada uno de sus elementos usamos el operador punto (.), seguido
del nombre del nombre del elemento, de la misma forma que con las uniones.
Una estructura puede ser declarada de forma global o local, pero es más común
hacerlo fuera de toda función.
El siguiente es un ejemplo de su uso.
91
#include<iostream.h>
#include<math.h>
struct proyectil{
        float VelocidadInicial, angulo;
        float PosX, PosY;
};
float calculaCaida(proyectil cosa);
int main(){
        proyectil misil;
        misil.PosX=misil.PosY=0;
        float distancia;
        cout<<"Este programa calculará la distancia, en linea\
             recta,en la que caerá un proyectil"<<endl;
        cout<<"escribe la velocidad inicial para lanzarlo: ";
        cin>>misil.VelocidadInicial;
        cout<<"escribe ahora el angulo de lanzamiento: ";
        cin>>misil.angulo;
        distancia=calculaCaida(misil);
        cout<<"la distancia a la que caerá el proyectil es: "
                <<distancia<<" metros aproximadamente"<<endl;
        cin.ignore();
        cin.get();
}
float calculaCaida(proyectil cosa){
        int t=1;                //tiempo
        const float grav=9.81;  //gravedad
        cosa.angulo/=57.2957;   //transformamos a radianes
        do{
          cosa.PosX=(cosa.VelocidadInicial*cos(cosa.angulo)*t);
          cosa.PosY=(cosa.VelocidadInicial*sin(cosa.angulo)*t)\
                ­(0.5*grav*t*t);
             ++t;
        }while(cosa.PosY>0);
        return(cosa.PosX);
}
Debemos hacer notar que las estructuras no se pueden inicializar en su declaración.
Aunque las estructuras son una buena manera de mandar bloques de datos a una
función, y es posible regresar estructuras (por la instrucción return), el coste es
92
alto, el programa se hace lento, gasta CPU y memoria. Para ello, y gracias a que se
trata como un nuevo tipo de variable, es posible hacer una paso por referencia, así
evitaríamos que se hiciese una copia de toda la estructura, y sólo se pasara la
dirección.
La forma de hacer un paso por referencia es igual que con cualquier otro tipo de
variables, sin embargo, al accesar a sus miembros debemos de hacerlo por medio
del operador flecha (->). Usando nuestro ejemplo anterior, simplemente cambiarían
unas lineas:
.
.
cosa­>angulo/=57.2957;  //transformamos a radianes
do{
 cosa­>PosX=(cosa­>VelocidadInicial*cos(cosa­>angulo)*t);
 cosa­>PosY=(cosa­>VelocidadInicial*sin(cosa­>angulo)*t)\
       ­(0.5*grav*t*t);
   ++t;
}while(cosa­>PosY>0);
return(cosa­>PosX);
.
.
Y gracias a las nuevas referencias de C++ que describimos en el capítulo anterior,
podemos simplemente incluir un carácter más en nuestro código para utilizarlo como
referencia, en nuestra función (y la declaración por supuesto) incluimos un '&':
float calculaCaida(proyectil& cosa){
.
.
y bastará para que se trate como una referencia sin necesidad de usar el operador
flecha.
93
Las estructuras también pueden tener por miembros a funciones, en cuyo caso se
invoca de la misma forma en la que se accesa a una variable. Le sugiero animarse a
usarlas, intente hacer unos ejercicios con ellas. Sin embargo, para esos casos es
mejor y más útil utilizar otro tipo de datos definido en C++, se trata de las clases
(class), para los fines de este trabajo las clases quedan fuera, debido a que se
requiere describir y practicar bastante con la programación orientada a objetos. El
lector debe de tener en cuenta su existencia, para que en un futuro, si se está
interesado, se adentre más en el mundo de la programación, en una de mejor nivel,
con mejores técnicas, y por ende con más capacidades.
Aquí muestro un programa en donde se observa la utilización de funciones como
miembros de una estructura, y también un ejemplo de las referencias C++.
#include<iostream.h>
#include<iomanip.h>
const int NumMaterias=11;
struct alumno {
        int boleta, semestre;
        int calificaciones[NumMaterias];
        void constancia(alumno & este){
                cout<<"constancia impresa"<<endl;
                cout<<"alumno con boleta: "<<este.boleta;
                cout<<setw(50)<<"del semestre numero: "
                        <<este.semestre<<endl;
                cout<<endl<<"CALIFICACIONES DEL SEMESTRE: "
                        <<endl;
                for(int i=0;i<NumMaterias;++i){
                        cout<<"asignatura "<<i+1<<" : " 
                                <<este.calificaciones[i]<<endl;
                }
        }
        void inicia(alumno & este){
                for(int i=0;i<NumMaterias;++i)
                        este.calificaciones[i]=0;
                este.boleta=0;
                este.semestre=0;
        }
};
94
int main(){
        alumno alan;
        alan.inicia(alan);
        cout<<"alan creado"<<endl;
        alan.boleta=2005630170;
        alan.semestre=5;
        alan.constancia(alan);
        return 0;


No hay comentarios:

Publicar un comentario