// lab11.cpp  (C) 2005 adolfo@di-mare.com

/** \file  lab11.cpp
    \brief Argumentos por valor y argumentos por referencia.

    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2005
*/

struct {
    int * pN; // Apunta a "n"
    int * pK; // Apunta a "k"
} GLOBAL;     ///< Variable global para este programa

#include <iostream> // cout
#include <iomanip>  // setw()

/// Calcula <code> n * n * n </code> y retorna el valor calculado.
int cuboPorValor( int n ) {
    return n * n * n;   // eleva al cubo la variable local n
}

/// Calcula <code> k * k * k </code> pero no retorna el valor calculado.
void cuboNO( int k ) {
    k = k*k*k;   // eleva al cubo la variable local n
}

/// Modifica la variable \c k para que su valor sea <code> k * k * k </code>.
void cuboPorReferencia( int& k ) {
    k = k*k*k;   // eleva al cubo la variable en main()
}

/// Modifica la variable \c *k para que su valor sea el cubo del valor original.
void cuboConPunteros( int *k ) {
    *k = *k * *k * *k;   // eleva al cubo la variable en main()
}   // *k se ve horrible-horrible

/// Ejercita las funciones que calculan el cubo de un número.
int main_cubo(void) {
    cout << endl << endl;

    int n = 5;
    GLOBAL.pN = &n;
    GLOBAL.pK = 0;

    cout << "Valor original == " << n;

    cout << endl << "cuboPorValor(" << n << ") == "
         << cuboPorValor(n);

    cuboNO(n);
    cout << endl << "cuboNO() ==> " << n;

    cuboPorReferencia(n);
    cout << endl << "cuboPorReferencia() ==> " << n;

    n = 9;
    cuboConPunteros(&n);
    cout << endl << "cuboConPunteros() ==> " << n;

    return 0;
}

/// Ordena en forma ascendente el vector \c V[] de \c "n" elementos.
void ordenaBurbuja ( int V[] , int n ) {
    for ( int i = 1; i < n; ++i ) { // hace (n-1) pasadas
        for ( int j = 0; j < n - 1; ++j )  {
            if ( V[j] > V[j+1] ) {      // compara
                int tmp = V[j];          // intercambia
                V[j] = V[j+1];
                V[j+1] = tmp;
            }
        }
    }
}

#include <iostream> // cout
#include <iomanip>  // setw()

/// Calcula la cantidad de elementos del vector \c V[]
#define DIM(V) (sizeof(V) / sizeof(*V)) // *V == *(V+0) == V[0]

/// Invoca \c ordenaBurbuja() para ordenar varios números.
int main_vector() {
    cout << endl; cout << endl;

    int i, A[] = { 22, 45, 11, 1, 0, 34, 89, 99, 12, 6 };

    cout << "Números en el orden original" << endl;
    for ( i = 0; i < DIM(A) ; i++ ) {
        cout << setw( 4 ) << A[i];
    }
    cout << endl;

    ordenaBurbuja( A, DIM(A) );

    cout << "Números ordendados" << endl;
    for ( i = 0; i < DIM(A) ; i++ ) {
        cout << setw( 4 ) << A[i];
    }
    cout << endl;

    return 0;
}

#include <iostream> // cout
#include <iomanip>  // setw()

/// Muestra la diferencia del llamado por copia y referencia.
int main_valref() {
    cout << endl; cout << endl;

    void hacedor(int por_valor, int& por_referencia);
    int igual, cambia;
    igual  = 1;
    cambia = 2;
    cout << "igual  [ANTES] == " << igual << endl;
    cout << "cambia [ANTES] == " << cambia << endl;
    hacedor(igual, cambia);
    cout << "igual  [DESPUES] == " << igual << endl;
    cout << "cambia [DESPUES] == " << cambia << endl;
    return 0;
}

/// Rutina que cambia los valores que recibe.
/// - \c por_valor pasa por valor (por copia).
/// - \c por_referencia pasa por referencia
void hacedor(int por_valor, int& por_referencia) {
    por_valor = 000;
    por_referencia = 333;

    cout << "  " << setw(3) << por_valor;
    cout << " ==> por_valor dentro de la función" << endl;
    cout << "  " << setw(3) << por_referencia;
    cout << " ==> por_referencia dentro de la función" << endl;
}

/// Muestra cómo funcionan los punteros.
int ejemplo_puntero() {
    cout << endl; cout << endl;

    char * pChr;  // puntero a un "char"
    int  * pInt;  // apunta a un "int"

    char VEC[] = {'a', 'b', 'b', 'a', 0}; // "abba";
    pChr = & VEC[0]; // "&" toma la dirección de "VEC[0]"

    cout << endl << "Como char [" << (*pChr) << ']';

    pInt = (int *) pChr;

    cout << endl << "Como int ["  << (*pInt) << ']';
    return 0;
/*
     Examine estas variables al ejecutar en BC++ v31.

    +------------------- Watch ----------------------+
    | VEC: "abba"                                    |
    | VEC,d: { 97, 98, 98, 97, 0 }                   |
    | (void*) pChr: DS:FFCA                          |
    | (void*) pInt: DS:FFCA                          |
    | (void*)  VEC: DS:FFCA                          |
    | *pChr: 'a'                                     |
    | *pInt: 25185                                   |
    | (unsigned long) pChr: 2412576714               |
    | (unsigned long) pInt: 2412576714               |
    +------------------------------------------------+
*/
}

/// Programa principal que invoca a todas las funciones.
int main(void) {
    main_cubo();
    ejemplo_puntero();
    main_vector();
    main_valref();

    return 0;
}

// EOF: lab11.cpp