Universidad de Costa Rica
Escuela de Ciencias de la
Computación e Informática
Profesor Adolfo Di Mare
CI-1201
I Semestre 2011
[<=] [home] [<>] [\/] [=>]
CI-1201 Programación II

Tarea #1 [solución]

Indentación y documentación de la clase Acumulador


uncrustify.exe -c ADHcrusti.cfg --no-backup Acumulador.h

#ifndef Acumulador_h
#define Acumulador_h ///< Evita la inclusión múltiple
class Acumulador{private:long m_total;long m_cantidad;long m_menor;long
m_mayor;public:Acumulador():m_total(0),m_cantidad(0),m_menor(0)
,m_mayor(0){/*borre();*/}~Acumulador(){}Acumulador(const
Acumulador&o){*this=o;}const Acumulador& operator=(const Acumulador&o){
m_total=o.m_total;m_cantidad=o.m_cantidad;m_menor
=o.m_menor;m_mayor=o.m_mayor;return*this;}void borre()
{m_total = m_cantidad = m_menor = m_mayor = 0;}long total() const{
return((m_cantidad <= 2) ? 0 : m_total-m_menor-m_mayor);}long
cantidad() const{return m_cantidad;}void acumule(long
val){m_total += val;m_cantidad++;if(m_cantidad > 1){
m_menor =( val < m_menor ? val : m_menor);m_mayor =( val > m_mayor
? val : m_mayor);}else{m_menor = m_mayor = val;}}void acumule( unsigned
n, const long * val){for(unsigned i=0; i<n; ++i){acumule(val[i]);
}}friend bool operator==(const Acumulador&A,const Acumulador&B){return(
A.m_total==B.m_total&&A.m_cantidad==B.m_cantidad&&A.m_menor==B.m_menor
&&A.m_mayor==B.m_mayor);}friend bool operator!=(const Acumulador&A,const
Acumulador&B){return!(A==B);}friend bool check_ok( const Acumulador&
A);friend class test_Acumulador;}; /* bool */
#endif
bool check_ok( const Acumulador& A){if( // Acumulador.cpp
!(&A!=0)){return false;}if(!(A.m_menor <= A.m_mayor)){return false;}if(!
(A.m_cantidad >= 0)){return false;}if((A.m_cantidad==0)&&((A.m_total !=0)
||(A.m_menor!=0)||(A.m_mayor != 0))){return false;}if((A.m_cantidad==1)
&&((A.m_total != A.m_mayor)||(A.m_menor != A.m_mayor))){return false;}
return true;}
Figura 1: Implementación de Acumulador

      El objetivo de esta tarea programada es darle la oportunidad de tomar un programa C++ completo para que usted le agregue la documentación y aprenda a compilarlo. Tome esta implementación de la clase Acumulador y dele formato de acuerdo a las convenciones de programación definidas en el curso. Haga tanto la documentación interna como la documentación externa, y construya un sitio Internet en donde instale tanto el código fuente como su documentación. Use Doxygen. Ejecute el programa paso a paso, usando el depurador simbólico. Entregue un reporte en el que relate su experiencia.

      Su reporte debe permitirle a una persona ajena al tema entender qué hizo y cómo lo hizo. Además, también debe servir para que esa persona pueda repetir el ejercicio desarrollado. Usted sabrá que su documentación es deficiente si solo le sirve a quien haya asistido a las lecciones del curso.

Di Mare, Adolfo
"INDENTACIÓN: Guía de calificación", Reporte técnico ECCI-2009-05 Escuela de Ciencias de la Computación e Informática, Universidad de Costa Rica, 2009.
      http://www.di-mare.com/adolfo/p/Indentacion.htm

// test_Acumulador.cpp (C) 2006 adolfo@di-mare.com

/** \file  test_Acumulador.cpp
    \brief Datos de prueba para la clase \c Acumulador.

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

#include "Acumulador.h"
#include "BUnit.h" // Módulo para prueba unitaria de programas

/// Datos de prueba para la clase \c Acumulador.
class test_Acumulador : public TestCase {
public:
    test_Acumulador() { setUp(); } ///< Constructor que invoca \c setUp()
    bool run();
private:
    void test_constructor();
    void test_copie_igual();
    void test_copie();
    void test_acumule();
    void test_total_cantidad();
    void test_borre();
    void test_Verifica_Suma();
    bool Verifica_Suma(long total, unsigned dim, long vec[]);
};

/// Ejecuta las pruebas.
bool test_Acumulador::run() {
    test_constructor();
    test_copie_igual();
    test_copie();
    test_acumule();
    test_total_cantidad();
    test_borre();
    test_Verifica_Suma();
    return wasSuccessful();
}

/// Cantidad de valores del vector \c V[].
/// - Esta una macro que no se puede implementar con plantillas.
#define DIM(V) (sizeof(V) / sizeof(*V)) // *V == *(V+0) == V[0]

/// Retorna \c true cuando la suma total de un acumulador es igual a \c total.
/// - En caso contrario, simplementer retorna \c false.
bool test_Acumulador::Verifica_Suma(long total, unsigned dim, long vec[]) {
    Acumulador A;
    assertTrue( check_ok( A ) );
    for (unsigned i=0; i<dim; ++i) {
        A.acumule( vec[i] );
        assertTrue( check_ok( A ) );
    }
    return ( A.total() == total );
}

/// Datos de prueba para el constructor y destructor de la clase.
void test_Acumulador::test_constructor() {
    {{  // test::constructor()
        Acumulador A;
        assertTrue( 0 == A.total() );
        assertTrue( 0 == A.cantidad() );
        long vec[] = { 1, 2, 3, 4,  5 };
        A.acumule( DIM(vec) , vec );
        assertTrue( 2+3+4 == A.total() );
        A.borre();
        assertTrue( 0 == A.total() );
    }}
    {   Acumulador A;
        {   // acumulador vacío
            A.borre();
            assertTrue( 0 == A.m_menor );
            assertTrue( A.m_menor == A.m_mayor );
            assertTrue( A.m_cantidad == 0 );
        }
    }
}

/// Datos de prueba para las operaciones de copia.
void test_Acumulador::test_copie() {
    {{  // test::copie()
        Acumulador A;
        long vec[] = { 1, 2, 3, 4,  5 };
        A.acumule( DIM(vec) , vec );
        Acumulador B; B = A;
        assertTrue( A.total()    == B.total() );
        assertTrue( A.cantidad() == B.cantidad() );
        assertTrue( A == B );
        A.borre();
        assertTrue( A != B );
        assertTrue( A.total()    != B.total() );
        assertTrue( A.cantidad() != B.cantidad() );
        B.borre();
        assertTrue( A == B );
    }}
}

/// Datos de prueba para las operaciones de copia y de comparación.
void test_Acumulador::test_copie_igual() {
    {{  // test::copie_igual()
        Acumulador A;
        long vec[] = { 1, 2, 3, 4,  5 };
        A.acumule( DIM(vec) , vec );
        Acumulador B = A;
        assertTrue( A.total()    == B.total() );
        assertTrue( A.cantidad() == B.cantidad() );
        assertTrue( A == B );
        A.borre();
        assertTrue( A != B );
        assertTrue( A.total()    != B.total() );
        assertTrue( A.cantidad() != B.cantidad() );
        B.borre();
        assertTrue( A == B );
    }}
}

/// Datos de prueba para \c Acumulador::borre().
void test_Acumulador::test_borre() {
    {{  // test::borre()
        Acumulador A;
        long vec[] = { 1, 2, 3, 4,  5 };
        A.acumule( DIM(vec) , vec );
        assertTrue( 2+3+4 == A.total() );
        assertTrue( 5 == A.cantidad() );
        A.borre();
        assertTrue( 0 == A.total() );
        assertTrue( 0 == A.cantidad() );
    }}
}

/// Datos de prueba para \c Acumulador::acumule().
void test_Acumulador::test_acumule() {
    {{  // test::acumule()
        Acumulador A;
        for ( long i=5; i>=0; --i ) {
            A.acumule( i );
        }
        assertTrue( 4+3+2+1 == A.total() );
        assertTrue( A.cantidad() == 6 );
        A.borre();
        assertTrue( 0 == A.total() );
        assertTrue( 0 == A.cantidad() );
    }}
    {   Acumulador A;
        {   // acumulación de puros ceros
            A.borre();
            assertTrue( 0 == A.total() );
            for ( long i=5; i>=0; --i ) {
                A.acumule( 0 );
            }
            assertTrue( 0+0+0+0 == A.total() );
            assertTrue( A.cantidad() == 6 );
        }
        {   // acumulación de solo un número
            A.borre();
            A.acumule( 12 );
            assertTrue( 12 == A.m_menor );
            assertTrue( A.m_menor == A.m_mayor );
            assertTrue( 0 == A.total() );
        }
        {   // acumulación ascendente de 2 números
            A.borre();
            A.acumule( 7 ); A.acumule( 11 );
            assertTrue(  7 == A.m_menor );
            assertTrue( 11 == A.m_mayor );
            assertTrue(  2 == A.m_cantidad );
            assertTrue(  0 == A.total() );
        }
        {   // acumulación descendente de 2 números
            A.borre();
            A.acumule( 11 ); A.acumule( 7 );
            assertTrue(  7 == A.m_menor );
            assertTrue( 11 == A.m_mayor );
            assertTrue(  2 == A.m_cantidad );
            assertTrue(  0 == A.total() );
        }
        {   // acumulación ascendente de 3 números
            A.borre();
            A.acumule( 7 ); A.acumule( 9 ); A.acumule( 11 );
            assertTrue(  7 == A.m_menor );
            assertTrue( 11 == A.m_mayor );
            assertTrue(  3 == A.m_cantidad );
            assertTrue(  9 == A.total() );
        }
        {   // acumulación descendente de 3 números
            A.borre();
            A.acumule( 11 ); A.acumule( 9 ); A.acumule( 7 );
            assertTrue(  7 == A.m_menor );
            assertTrue( 11 == A.m_mayor );
            assertTrue(  3 == A.m_cantidad );
            assertTrue(  9 == A.total() );
        }
        {   // vec[] en orden ascendente
            long vec[] = { -2, -1, -0, +0 , +1, +2, +3, +4  };
            A.borre();
            A.acumule( DIM(vec) , vec );
            assertTrue( A.total() == (-1) + (-0) + (+0) + (+1) + (+2) + (+3) );
            assertTrue( 8 == A.cantidad() );
        }
        {   // vec[] en orden decendente
            long vec[] = { +4, +3, +2, +1, +0, -0, -1, -2 };
            A.borre();
            A.acumule( DIM(vec) , vec );
            assertTrue( A.total() == (-1) + (-0) + (+0) + (+1) + (+2) + (+3) );
            assertTrue( 8 == A.cantidad() );
        }
        {   // vec[] en orden alocado
            long vec[] = { -1, -2, +1, +0, -0, +4, +3, +2 };
            A.borre();
            A.acumule( DIM(vec) , vec );
            assertTrue( A.total() == (-1) + (-0) + (+0) + (+1) + (+2) + (+3) );
            assertTrue( 8 == A.cantidad() );
        }
    }
}

/// Método base que ejecuta todas las pruebas de la clase.
void test_Acumulador::test_total_cantidad() {
    {{  // test::total_cantidad()
        Acumulador A;  //   2   3   4    5   6   7   8
        long vec[] = { -2, -1, -0, +0 , +1, +2, +3, +4  };
        A.acumule( DIM(vec) , vec );
        assertTrue( A.total() == (-1) + (-0) + (+0) + (+1) + (+2) + (+3) );
        assertTrue( 8 == A.cantidad() && 8 == DIM(vec) );
    }}
}

/// Corre varias pruebas específicas.
void test_Acumulador::test_Verifica_Suma() {
    {   assertTrue( 35 ==  2  + 3 + 4 + 5 + 6 + 7 + 8 );
        long vec[] = { 1 , 2 ,  3 , 4 , 5 , 6 , 7 , 8 , 9 };
        assertTrue( Verifica_Suma( 35, DIM(vec), vec ) );
    }

    {   long vec[] = { 1 };
        assertTrue( Verifica_Suma( 0, DIM(vec), vec ) );
    }

    {   long vec[] = { 1, 2 };
        assertTrue( Verifica_Suma( 0, DIM(vec), vec ) );
    }

    {   long vec[] = { 1, 2, 1 };
        assertTrue( Verifica_Suma( 1, DIM(vec), vec ) );
    }

    {   long vec[] = { 2, 2, 1 };
        assertTrue( Verifica_Suma( 2, DIM(vec), vec ) );
    }

    {   assertTrue( 12 ==  2 + 2 + 2 + 2 + 2 + 2  );
        long vec[] = { 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 };
        assertTrue( Verifica_Suma( 12, DIM(vec), vec ) );
    }

    {   // Esta es la que genera 1 error
        assertFalse(13 ==  2 + 2 + 2 + 2 + 2 + 2  );
        long vec[] = { 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 };
        assertTrue( Verifica_Suma( 13, DIM(vec), vec ) );
    }
}

#include <iostream> // cout

/** Este es el programa principal.
   - Primero crea la prueba \c Test de tipo \c test_Acumulador.
   - Luego hace la prueba, invocando \c test_Acumulador::run().
   - Por último graba en \c cout los resultados usando \c Report().
*/
int main() {
    test_Acumulador tester;       // crea la prueba
    tester.run();                 // la ejecuta
    std::cout << tester.report(); // graba en "cout" los resultados
    return 0;
}

// EOF: test_Acumulador.cpp
Figura 2: Datos de prueba para la clase Acumulador

Fuentes para

Doxygen
/** Calcula el Máximo Común Divisor de los números \c "x" y \c "y".
    - Se usa el algoritmo de Euclides para hacer el cálculo.
    - <code> mcd(x,y) >= 1 </code> siempre.
    - MCD <==> GCD: <em> Greatest Common Divisor </em>.

    \pre
    <code> (y != 0) </code>
*/
long mcd(long x, long y);

Documentación generada por

long mcd ( long x, long y )
Calcula el Máximo Común Divisor de los números "x" y "y".
  • Se usa el algoritmo de Euclides para hacer el cálculo.
  • mcd(x,y) >= 1 siempre.
  • MCD <==> GCD: Greatest Common Divisor .
Precondición:
(y != 0)

 

Entrega de la tarea

PROJECT_NAME          = "952809 Tarea Programada #1"
OUTPUT_LANGUAGE       = Spanish
OUTPUT_DIRECTORY      = .
GENERATE_LATEX        = NO
GENERATE_MAN          = NO
GENERATE_RTF          = NO
CASE_SENSE_NAMES      = YES
INPUT_ENCODING        = ISO-8859-1
INPUT                 = Acumulador.h Acumulador.cpp test_Acumulador.cpp
RECURSIVE             = NO
QUIET                 = YES
JAVADOC_AUTOBRIEF     = YES
EXTRACT_ALL           = YES
EXTRACT_PRIVATE       = YES
EXTRACT_STATIC        = YES
EXTRACT_LOCAL_CLASSES = YES
INLINE_INHERITED_MEMB = YES
SOURCE_BROWSER        = YES
INLINE_SOURCES        = NO
STRIP_CODE_COMMENTS   = NO
REFERENCED_BY_RELATION= NO
REFERENCES_RELATION   = NO
FULL_PATH_NAMES       = NO

SORT_MEMBER_DOCS      = NO
SORT_BRIEF_DOCS       = NO
CLASS_DIAGRAMS        = YES

ENABLE_PREPROCESSING  = YES
MACRO_EXPANSION       = YES
EXPAND_ONLY_PREDEF    = YES
PREDEFINED            = "DOXYGEN_COMMENT" \
                        "Spanish_dox" \
                        "__cplusplus" \
                        "_MSC_VER=1300"

EXAMPLE_PATH          = .

#--- TODOS ESTOS SON MENOS COMUNES ---
# DISTRIBUTE_GROUP_DOC = YES
# ENABLE_PREPROCESSING = YES
# FILE_PATTERNS        = diagrams_*.h
# GENERATE_TAGFILE     = example.tag
# HAVE_DOT             = YES
# PERL_PATH            = perl
# TAGFILES             = example.tag=../../example/html

# Manual ==> http://www.doxygen.org/manual.html

      Luego de escribir la documentación de su programa envíe su trabajo por correo electrónico. Para esto, haga un archivo empacado .zip cuyo nombre sea su número de carnet. Incluya en ese archivo lo siguiente:

  1. Un documento en formato HTML que describa el trabajo que realizó. Incluya el nombre del compilador que usó.
  2. La especificación de su programa.
  3. Archivo de configuración Doxygen (los asistentes usrarán este archivo de configuración para generar la documentación de su programa, por lo que sobra que usted incluya esa documentaciónen su archivo .zip).
  4. El código fuente de sus programas (archivos de implementación *.c, *.cpp, *.h, etc.).
  5. Los archivos y datos de prueba para su programa.
  6. Un archivo de enlace Internet, con extensión .url que permita abrir la página Internet en que está la documentación completa de su programa.

      Las cuentas de computador en la ECCI se asignan de acuerdo al número de carnet. Por ejemplo, si su carnet es el número 95-28-09, para entregar su tarea usted debe crear el archivo 952809.zip para enviarlo por correo electrónico. Si varios alumnos participaron en la confección de la tareas, sus carnets deben incluirse en el nombre del archivo .zip: 952809-952810-952811.zip.

      Luego use FTP para subir a la red todas sus páginas Internet. En la práctica, una forma simple de obtener la página es escribirla usando algún procesador de texto como OpenOffice writer y luego guardar el documento en formato HTML. Recuerde subir todos los archivos porque cada imagen usada en su documento está en un archivo aparte.

Inicio
   ==> Ejecutar ==> [ Notepad.exe ] ...
   ==> Guardar como ==> [ 952809.url ]
[InternetShortcut]
URL=http://www.di-mare.com/adolfo/p/Matrix.htm
952809.url

      Recuerde incluir en su archivo CARNET.zip un acceso directo para abrir su página. Para crearlo, puede jalarlo del hojeador cuando abra la página, o también puede usar un editor de texto como Notepad.exe para crear el archivo de texto como se muestra en el archivo 952809.url en esta figura.

      Después de la fecha de entrega del programa, puede usted instalar en su cuenta personal su solución (no instale antes su solución en Internet, pues en ese caso sería usted culpable de facilitar la copia de su trabajo, y en consecuencia se haría acreedor a la sanción respectiva).

      Por ejemplo, para entregar su tarea programada, el estudiante 952809 crea su archivo 952809.zip en el que aparece estos archivos:

Acumulador.h
Define el tipo "Acumulador" para sumar secuencias de números enteros
Acumulador.cpp
Implementaciones para "Acumulador.h"
test_Acumulador.cpp
Datos de prueba para la clase Acumulador
BUnit.h
Modulo [B]ásico para prueba [unit]aria de programas
 
952809.doc
Documentación, escrita con Word (incluye la portada)
952809.htm
Página Internet con toda la documentación
952809.dxg
Archivo de configuración Doxygen.
952809.url
Enlace para abrir la página Internet
 
test_Acumulador.cbp
Archivo para compilar el programa con CodeBlocks [GNU C++].
test_Acumulador.dsp
(Opcional) Archivo para compilar el programa con MSC++ v6.x
test_Acumulador.vcproj
(Opcional) Archivo para compilar el programa con MSC++ .NET
test_Acumulador.dev
(Opcional) Archivo para compilar el programa con GNU C++.

[mailto:] Entrega de Tareas

Tiempo de entrega: 7 días
Modalidad: Individual

 

Políticas de Corrección de Tareas

  1. La falta de cualquier especificación debe ser castigada fuertemente.
  2. Correcta indentación del código fuente.
  3. Correcto espaciado del código fuente.
  4. Código fuente escrito de manera que se legible y claro.
  5. Uso de indentificadores significativos.

Soluciones

[mailto:] Adolfo Di Mare <adolfo@di-mare.com>.
Copyright © 2011
Derechos de autor reservados © 2011
[home] <> [/\]