/**
  * Programa Ejemplo #1 de la Clase #12
  * Este programa se presenta como ejemplo para iniciar la práctica
  * con el lenguaje de programación C++
  * Creación de Tipos Definidos por el Usuario
  * typedef, enum, struct, union
  * Autor:  Carlos Roberto Arias
  * Elaborado como Recurso de la Clase de Programación III
  * Segundo Parcial
  * Universidad Tecnológica Centroamericana
  * 2003
  */


#include <iostream>
#include <cstdlib>

using namespace std;

// Creando tipos usando typedef
typedef unsigned long int ULONG;
typedef double* PDOUBLE;

// Creando tipos usando enum
enum EColor {ROJO, VERDE, AZUL, CAFE, AMARILLO};

// Creando tipos usando struct
struct SPoint
{
    int x;
    int y;
};
struct SRect
{
    SPoint upperLeft;
    SPoint lowerRight;
};
struct SCosa
{
    char t;
    double d[4];
};

// Declaracion de Funciones
EColor seleccionaColor();
void printPoint(const SPoint&);
void printRectangle(const SRect&);

int main()
{
    // Uso de typedef
    ULONG distancia = 12124455548UL;
    double* a, b;
    // ¿Qué tipo es a? ¿Qué tipo es b?
    PDOUBLE c, d;
    // ¿Qué tipo es c? ¿Qué tipo es d?
    
    // Uso del enum
    switch (seleccionaColor())
    {
        case ROJO:
                cout << "Color Rojo..." << endl;
                break;
        case VERDE:
                cout << "Color Verde..." << endl;
                break;
        case AZUL:
                cout << "Color Azul..." << endl;
                break;
        case CAFE:
                cout << "Color Cafe..." << endl;
                break;
        case AMARILLO:
                cout << "Color Amarillo..." << endl;
                break;
    }
    // Uso de struct
    
    SPoint punto1;
    // Utilización del operador . de acceso a miembros
    punto1.x = 10;
    punto1.y = 12;
    
    SPoint* ppunto;
    // Hasta este punto SOLO se tiene el puntero!!!!
    ppunto = new SPoint;
    // Ya se creó... ¿En qué segmento de memoria?
    // Ahora para accesar los miembros:
    ppunto->x = 12;
    ppunto->y = -1;
    // Entonces cuando es puntero es con ->
    
    delete ppunto;
    
    // Ahora para una estructura dentro de una estructura:
    SRect rectangulo;
    rectangulo.upperLeft.x = 1;
    rectangulo.upperLeft.y = 1;
    rectangulo.lowerRight.x = 25;
    rectangulo.lowerRight.y = 14;
    // Es posible tener entonces estruturas dentro de estructuras!!
    
    // Imprimiento el Rectangulo
    printRectangle(rectangulo);
    
    // Arreglos:
    SPoint aPuntos[5];
    // Colocando puntos al Azar:
    for (int i=0; i<5; i++){
        aPuntos[i].x = rand() % 20;
        aPuntos[i].y = rand() % 20;
    }
    
    // Imprimiendo los puntos:
    for (int i=0; i<5; i++)
        printPoint(aPuntos[i]);
    
    // Ahora cuando el arreglo está dentro de la estructura:
    SCosa cosa;
    cosa.d[0] = 3.1212121;
    cosa.t = 'A';
    
    // Y si hicieramos un arreglo de esto:
    SCosa cosas[4];
    cosas[0].d[1] = 1.12121212155;
    cosas[0].t    = '\t';
    
    system("pause");
    return 0;
}
EColor seleccionaColor()
{
    return (EColor)(rand() % 5);
}
void printPoint(const SPoint& p)
{
    cout << "(" << p.x << ", " << p.y << ")" << endl;
}
void printRectangle(const SRect& r)
{
    int height = abs(r.upperLeft.y - r.lowerRight.y),
        width  = abs(r.upperLeft.x - r.lowerRight.x);
    cout << endl;
    for (int i=0; i<height; i++){
        for (int j=0; j<width; j++)
            cout << "*";
        cout << endl;
    }
}
