Estructuras de Datos
Una estructura es una colección de datos, normalmente, relacionados entre ellos. Esta serie de datos están agrupados bajo un mismo nombre identificador, el nombre de la estructura. Cada dato es conocido como un miembro de la estructura y al estar agrupados bajo el mismo identificador es fácil manipularlos todos simultaneamente.
Antes de concentrarnos en las estructuras, vamos a ver muy rápido lo que es una enumeración. Esta es simplemente un tipo de dato que contiene un set de identificadores a los que nos referimos como elementos o enumeradores. Un ejemplo simple es el color de tu pelo: rubio, castaño, negro, pelirrojo, otro.
enum colorDePelo {rubio, castano, negro, pelirrojo, otro};
colorDePelo miPelo=castano;
if(miPelo==negro)
cout << "Vaya, tienes el pelo negro";
Los valores de una enumeración toman un valor numérico entero empezando por 0 y incrementando por valor de uno, si no indicamos lo contratio. Es decir rubio tiene un valor de 0, castano = 1, negro=2… Aunque si deseamos que los valores sean distintos, desde luego, podemos hacerlo.
enum numeros_enum{UNO=1,DOS,TRES,SIETE=7,DIEZ=10,ONCE};
int numeroTrece = TRES + DIEZ;
cout<<numeroTrece; //imprimiria 13
Asignamos 1 a UNO, por lo que el siguente miemtro será igual a 2, 3 y así sucesivamente, pero como no querémos que SIETE tenga un valor de 4, especificamos SIETE=7.
Aunque los ejemplos hasta ahora han asignado un nombre a la enumeración, esto no es necesario. Una enumeración puede ser anónima. Veamos un pequeño ejemplo práctico.
#include <iostream>
using namespace std;
enum {pistola, rifle, metralleta, granada};
string tipo_cadena[4]={"Pistola","Rifle","Metralleta","Granada"};
int main(){
int miArma=granada;
cout<<tipo_cadena[miArma];
return 0;
}
Al granada equivaler a 3, tipo_cadena[miArma] obtiene el valor del array con índice 3, es decir “Granada”.
Ahora vemos son realmente las estructuras. Hay muchas ocasiones donde nos conviene agrupar una lista de variables, por ejemplo el nombre, sexo, arma… de un jugador. Los datos de una estructura no tienen porque ser del mismo tipo. Son algo parecidos a los registros de una base de datos. Esta es la forma de declarar una estructura.
struct arma{
int tipo;
int municion;
}miPistola;
Aquí hemos declarado una estructura con dos miembros, ambos de tipo int. Y hemos instanciado un objecto de tipo arma vacío llamado miPistola. Para acceder a los miembros de la estructura usamos el operador ‘ . ‘ por lo que para cambiar la munición simplemente tendríamos que hacer miPistola.municion=100; Podemos iniciar la instancia de la estructura directamente con valores si los listamos entre llaves. arma miGranada={granada,1}; Haciendo un par de modificaciones y juntando los ejemplos anteriores conseguimos algo asi.
#include <iostream>
#include <string>
using namespace std;
enum {pistola, rifle, metralleta, granada};
string tipo_string[4]={"Pistola","Rifle","Metralleta","Granada"};
struct arma{
string tipo;
int municion;
};
int main(){
arma miPistola = {tipo_string[pistola],30};
cout<<"Mi arma es: "<<miPistola.tipo;
cout<<endl<<"Y su cantidad de municion: "<<miPistola.municion;
return 0;
}
Como con todos los tipos de objetos, podemos tener un puntero a una estructura. Tambien podemos tener una estructura dentro de otra estructura, algo muy común. Usando lo que hemos aprendido hasta ahora, vemos a ver un ejemplo algo más complejo con mejor funcionalidad.
#include <iostream>
#include <string>
using namespace std;
//enumeracion de armas
enum {pistola, rifle, metralleta, granada};
string tipo_string[4]={"Pistola","Rifle","Metralleta","Granada"};
//estructura de armas
struct arma{
string tipo; //nombre de arma
int municion; //cantidad de municion
};
//estructura de jugador
struct jugador{
string nombre; //nombre del jugador
arma armas[3]; //array 3 armas
}usuario;
int main(){
//pedir nombre y guardan en usuario
cout<<"Hola, como te llamas? ";
getline(cin,usuario.nombre);
//pedir que introduzca sus tres armas
for (int i=0;i<3;i++){
cout<<"Elige tu arma numero "<<i<<endl;
cout<<"Pistola (0), Rifle (1), Metralleta(2), Granada(3) ";
unsigned int seleccion;cin>>seleccion;
if(seleccion>3)seleccion=0; //tipo erroneo, elegimos pistola
//guardar nombre del arma para cada una
usuario.armas[i].tipo=tipo_string[seleccion];
//vamos a dar munucion segun el arma que se haya escogido
switch (seleccion){
//si es pistola municion de 50
case 0: usuario.armas[i].municion=50;break;
//si es rifle o metralleta, 20
case 1:case 2: usuario.armas[i].municion=20;break;
//granada solo 1
case 3: usuario.armas[i].municion=1;break;
}
}
//mostrar los contenidos de la usuario
cout<<"Buena eleccion "<<usuario.nombre<<": "<<endl;
for (int i=0;i<3;i++){//tres armas
cout<<"Arma "<<i+1<<": "<<usuario.armas[i].tipo<<" (";
cout<<usuario.armas[i].municion<<")"<<endl;
}
}
En este ejemplo he incorporado varias cosas que hemos ido aprendiendo hasta ahora para formar un pequeño programa que podría ser parte de un juego. No he incorporado punteros a estructuras en este ejemplo ya que quieres enseñar esto aparte.
Acceder a los valores que una instancia (objeto de tipo) de una estructura, lo hacemos de una manera ligeramente diferente. En vez de usar el operador ‘ . ‘ usamos ‘->’ para establecer que estamos accediendo mediante un puntero de forma cómoda.
//instancia jugador miJugador; //puntero jugador* pJugador=&miJugador; //acceder al nombre miJugador.nombre; pJugador->nombre; //aunque tambien puedes acceder mediante (*pJugador).nombre; //OJO!! No hagais esto *pJugador.nombre; //esto equivale a *(pJugador.nombre);
