/**
  * Programa Ejemplo #1 de la Clase #10
  * Este programa se presenta como ejemplo para iniciar la práctica
  * con el lenguaje de programación C++
  * Apuntadores (Punteros): Uso de Memoria Dinámica
  * Autor:  Carlos Roberto Arias
  * Elaborado como Recurso de la Clase de Programación III
  * Universidad Tecnológica Centroamericana
  * 2003
  */
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>

using namespace std;

double* createArray(int);
void freeArray(double*);

int main(int argc, char* argv[])
{
    // Acerca de los tamaños
    // ¿ Cuál será la salida ?
    cout << "Tamanios de los punteros " << endl;
    cout << sizeof(char*) << endl
         << sizeof(int*)  << endl
         << sizeof(long int*) << endl
         << sizeof(long double*) << endl;
         
    // Creacion de Variables en el Heap
    int* p = NULL;  // Siempre es buena idea inicializar los punteros en NULL
                    // NULL NO es una palabra reservada, es una constante!
    p = new int;    // Reserva espacio para 1 entero en el Heap
    
    *p = 91;        // Se asigna este valor al entero que está en el Heap
    cout << "Direccion guardada en p es: " << p << endl
         << "El valor al que apunta p es :  " << *p << endl;
    
    delete p;       // Libera la memoria que está en reservada en el Heap
    p = NULL;
    
    // Ahora para crear arreglos dinámicos...
    int size;
    cout << "De que tamanio quiere el arreglo... : " ;
    cin  >> size;
    
    p = new int[size];
    
    cout << "Introduzca los elementos del arreglo dinamico: " << endl;
    for (int i=0; i < size; i++){
        cout << "p[" << i << "] = ";
        cin  >> p[i];
    }
    
    cout << "Los elementos del Arreglo dinamico... " << endl;
    for (int i=0; i < size; i++){
        cout << setw(5) << p[i];
    }
    cout << endl << endl;
    // Liberando el Arreglo dinamica...
    delete[] p; // Fijese en los [] antes... de no ponerlo sólo libera el 1ero
    p = NULL;
    
    // La memoria dinámica no depende del ámbito!!!
    
    double* pd = createArray(20);
    
    // A pesar que retVal muere al terminar el ámbito de createArray
    // la memoria dinámica reservada trasciende, y esa dirección es
    // almacenada en pd.
    
    for (int i=0; i<20; i++){
        pd[i] = (rand() % 1000 + 1) / 1000.00;
        cout << setprecision(6) << setw(10) << pd[i] << endl;
    }
    
    // Para liberar pd, podemos llamar a la función
    freeArray(pd);
    
    // Y para crear arreglos bidimensionales dinámicos...
    
    float** matriz;
    
    int n, m;
    
    cout << "Las dimensiones de la matriz: (n x m) " ;
    cin >> n >> m;
    
    // Creación de la Matriz:
    matriz = new float*[n]; // Crea el arreglo de punteros (El arreglo de arreglos)
    for (int i=0; i<n; i++)
        matriz[i] = new float[m];
    
    // Colocamos valores al azar en la matriz... (solo demostrativo)
    
    for (int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            matriz[i][j] = ( rand() % 100 + 1) / 100.0 ;
    
    // Impresion de la matriz...
    for (int i=0; i<n; i++){
        for(int j=0; j<m; j++)
            cout << setw(5) << setprecision(3) << matriz[i][j];
        cout << endl;
    }
    
    // Para liberar la matriz:
    for (int i=0; i<n; i++)
        delete[] matriz[i];    // Primero los elementos...
    delete[] matriz;
    
    
    system("pause");
    return 0;
}

double* createArray(int size)
{
    double* retVal = new double[size];
    assert(retVal != 0);
    return retVal;
}
void freeArray(double* ptr)
{
    if (ptr)
        delete[] ptr;
}

