[C con Clase] Hijo, comprueba tu división con esto.

Armando B. VERA rdlmat en gmail.com
Jue Oct 9 03:57:52 CEST 2014


Para crear un programa "a prueba de balas", es decir, que solo acepte
determinados tipos de valores se utiliza un bucle, que puede ser while y
algunos métodos de la clase istream. Me parece que te serviría un poco de
lectura para no desaprovechar esta posibilidad de aprender que tienes. Por
lo demás,

¡Felcitaciones! solo llegan los que perseveran. La inteligencia no es algo
exclusivo de algunos, sino de aquellos que saben lo que quieren.


El 7 de octubre de 2014, 17:26, marcelinux <marcelinator en gmail.com>
escribió:

> Hola a todos.
> Ya os habréis dado cuenta de que vervose es un "gazapo", pero cumplió su
> misión.
> He implementado una nueva versión de la división.
> Esta vez he creado una clase que simula una hoja cuadriculada donde se
> "pintará" la división.
> Para eso ya he usado dos archivos (definición y declaración), más el
> archivo con el main().
> Para la próxima versión, controlaré que sólo se permita introducir números.
> La siguiente, admitirá las cantidades como argumentos del programa.
> Más adelante, usaré la función ldiv(num,denom) en lugar de las de la clase
> Division, GetCociente y GetResto.
> La última debería ser con una interfaz gráfica.
> Ni que decir tiene que agradeceré cualquier crítica o referencia para
> mejorar, tanto el código como los conceptos que he manejado.
>
> Os pego los tres archivos y el resultado del ejemplo.
> Como lo he hecho en ubuntu, el comando de compilación ha sido:
> g++ -odividete_v3 dividete_v3.cpp division_v3.cpp
>
> [Archivo division_v3.h]
> /* Clase Division
>  * Versión 3
>  * Declaración
>  */
> #ifndef DIVISION_V3_H
> #define DIVISION_V3_H
>
> #define MAX_CIFRAS 9
> #define NUM_FILAS 15
> #define NUM_COLUMNAS 20
>
> class Division
> {
>         public:
>                 Division(long numerador, long denominador);
>                 long BajaLaCifraSiguiente();
>                 long GetCociente(long num);
>                 long GetResto(long num);
>                 void DibujaLaDivision();        // Dibuja el enunciado de
> la división en la hoja
>                 void Pinta();                           // Muestra la hoja
> con la división completa
>                 int GetNumeroDeCifras(long numero);
>         private:
>                 // miembros
>                 // Son char para simular la colocación de cada cifra en su
> posición
>                 char m_dividendoChar[MAX_CIFRAS];
>                 long m_divisor;
>                 char m_divisorChar[MAX_CIFRAS];
>                 char m_cocienteChar[MAX_CIFRAS];
>                 char m_restoChar[MAX_CIFRAS];
>                 int m_cifra;
>                 int m_fila;
>                 char m_cuadricula[NUM_FILAS][NUM_COLUMNAS];     // Simula
> una página cuadriculada
> };
>
> #endif  // DIVISION_V3_H
>
>
> [Archivo division_v3.cpp]
> /* Clase Division
>  * Versión 3
>  * Definición
>  */
> #include "division_v3.h"
>
> #include <cstdio>
> #include <cstdlib>
> #include <cstring>
> #include <iostream>
> #include <math.h>
>
> using namespace std;
>
> #undef verbose
>
> Division::Division(long numerador, long denominador)
> {
>         for(int i = 0; i < MAX_CIFRAS; i++)
>         {
>                 m_dividendoChar[i] = ' ';
>                 m_divisorChar[i] = ' ';
>                 m_cocienteChar[i] = ' ';
>                 m_restoChar[i] = ' ';
>         }
>         m_dividendoChar[MAX_CIFRAS] = 0;
>         m_divisorChar[MAX_CIFRAS] = 0;
>         m_cocienteChar[MAX_CIFRAS] = 0;
>         m_restoChar[MAX_CIFRAS] = 0;
>         m_divisor = denominador;
>         sprintf(m_dividendoChar, "%ld", numerador);
>         sprintf(m_divisorChar, "%ld", denominador);
>         m_cifra = 0;
>         m_fila = 0;
>         for(int f = 0; f < NUM_FILAS; f++)
>                 for(int c = 0; c < NUM_COLUMNAS; c++)
>                         m_cuadricula[f][c] = ' ';
> }
>
> long Division::BajaLaCifraSiguiente()
> {
>         char c[MAX_CIFRAS];
>         sprintf(c, "%c", m_dividendoChar[m_cifra]);
>         #ifdef verbose
>                 cout << "\nBajaLaCifraSiguiente obtiene '" <<
> m_dividendoChar[m_cifra] << "'";
>         #endif
>         #ifdef verbose
>                 cout << "\nBajaLaCifraSiguiente añade   '" << c << "'";
>         #endif
>         strncat(m_restoChar, c, 1);
>         #ifdef verbose
>                 cout << "\nBajaLaCifraSiguiente y queda '" << m_restoChar
> << "'";
>         #endif
>         long restoTemp = atol(m_restoChar);
>         #ifdef verbose
>                 cout << "\nBajaLaCifraSiguiente convertida a long " <<
> restoTemp;
>         #endif
>         m_fila++;
>         #ifdef verbose
>                 cout << "\nBajaLaCifraSiguiente va a la fila " << m_fila;
>         #endif
>         for(int col = 0; col <= m_cifra; col++)
>                 m_cuadricula[m_fila][col] = m_restoChar[col];
>         #ifdef verbose
>                 Pinta();
>         #endif
>         return restoTemp;
> }
>
> long Division::GetCociente(long numerador)
> {
>         long cocienteTemporal = numerador / m_divisor;
>         #ifdef verbose
>                 cout << '\n' << numerador << " entre " << m_divisor << "
> es " << cocienteTemporal;
>         #endif
>         char s[MAX_CIFRAS];
>         sprintf(s, "%ld", cocienteTemporal);
>         strncat(m_cocienteChar, s, 1);
>         #ifdef verbose
>                 cout << "\nCociente combinado:" << m_cocienteChar;
>         #endif
>         long cociente = atol(m_cocienteChar);
>         return cociente;
> }
>
> long Division::GetResto(long numerador)
> {
>         long resto = numerador % m_divisor;
>         int cifrasResto = GetNumeroDeCifras(resto);
>         #ifdef verbose
>                 cout << "\nEstoy en la cifra " << m_cifra;
>         #endif
>         sprintf(m_restoChar, "%*ld", m_cifra + 1, resto);
>         #ifdef verbose
>                 cout << "\nrestoChar queda: '" << m_restoChar << "'";
>         #endif
>         m_cifra++;
>         return resto;
> }
>
> void Division::DibujaLaDivision()
> {
>         #ifdef verbose
>                 cout << "Dibuja divisorChar:" << m_divisorChar;
>         #endif
>         int posicion = NUM_COLUMNAS - MAX_CIFRAS;
>         for(int c = 0; c < posicion; c++)
>                 if(m_dividendoChar[c] >= '0')
>                         m_cuadricula[0][c] = m_dividendoChar[c];
>         m_cuadricula[0][posicion] = '|';
>         for(int c = 0; c < posicion; c++)
>                 if(m_divisorChar[c] >= '0')
>                         m_cuadricula[0][posicion+2+c] = m_divisorChar[c];
>         m_cuadricula[1][posicion] = 'L';
>         for(int c = posicion+1; c < NUM_COLUMNAS; c++)
>                 m_cuadricula[1][c] = '_';
>         m_fila = 1;
> }
>
> void Division::Pinta()
> {
>         int posicion = 2 + (NUM_COLUMNAS - MAX_CIFRAS);
>         for(int c = 0; c < MAX_CIFRAS; c++)
>                 if( (m_cocienteChar[c] >= '0') && (m_cocienteChar[c]
> <='9') )
>                         m_cuadricula[2][c + posicion] = m_cocienteChar[c];
>
>         for(int f = 0; f < NUM_FILAS; f++)
>         {
>                 cout << endl;
>                 for(int c = 0; c < NUM_COLUMNAS; c++)
>                         cout << m_cuadricula[f][c];
>         }
>         cout << endl << endl;
> }
>
> int Division::GetNumeroDeCifras(long numero)
> {
>         int cifras = int(log10(numero)) + 1;
>         /* Gracias Steven
>          * Definitivamente, las matemáticas no son mi fuerte.
>          */
>         return cifras;
> }
>
>
>
> [Archivo dividete_v3.cpp]
> /* Proyecto: dividete. Comprobar una división en modo texto.
>  * Versión 3
>  * Autor   : Marcelino Gisbert
>  * Objetivo: El alumno introducirá el dividendo y el divisor.
>  *           La aplicación calculará el número de cifras del dividendo y
> las del denominador.
>  *           Se repetirán tantas divisiones enteras con las cifras del
> denominador
>  *           para ir construyendo la división tal y como se haría a mano.
>  *           Se mostrará en una rejilla a modo de papel cuadriculado.
>  * TODO
>  *           Debo resolver el inconveniente de introducir letras en lugar
> de números.
>  *           Para probar, me ceñiré al ejemplo.
>  *           En la versión 3, probaré el formateo de la entrada.
>  *           También se implementará una versión que acepte las cantidades
> como parámetros
>  *           de main.
>  *
>  * Ejemplo:
>  *           Dado el dividendo: 35437
>  *           Y el divisor.....: 283
>  *           El proceso sería :
>  *           Se escribe el dividendo (hasta 19 cifras)
>  *           A continuación, el divisor tras su "separador"
>  *           En la siguiente línea cerramos el operador de división.
>  *           Quedaría así:
>  *           35473              | 283
>  *                              L____________________
>
>  *           Obtener el número de cifras de 35437: 5
>  *           Se baja una cifra hasta que se pueda dividir.
>  *           Primero el 3
>  *           Se divide y se obtiene el resto de la división entera: 3
>  *           Se baja la cifra siguiente: el 5.
>  *           Se añade al resto anterior: 35.
>  *           Se divide y se obtiene el resto: 35.
>  *           Se baja la cifra siguiente: el 4.
>  *           Se añade al resto anterior: 354.
>  *           Se divide y se obtiene cociente (1) y el resto (71).
>  *           Se baja la cifra siguiente: el 3.
>  *           Se añade al resto anterior: 713.
>  *           Se divide y se obtiene el cociente (2) y el resto (147).
>  *           Se baja la cifra siguiente: el 7.
>  *           Se añade al resto anterior: 1477.
>  *           Se divide y se obtiene el cociente (5) y el resto (62).
>  *           Acabaron las cifras del dividendo.
>  *           El resultado se ve escalonado: cociente 125, resto 62.
>  */
>
> #include <iostream>
>
> #include "division_v3.h"
>
> using namespace std;
>
> void MuestraAyuda()
> {
>         cout << "\n\nHijo, comprueba tu división." << endl;
>         cout << "Lo ha hecho papá para que ganes tiempo en tus deberes."
> << endl;
>         cout << "No para que hagas trampa ;-)" << endl;
>         cout << "Funciona así:" << endl;
>         cout << "Primero te pediré el dividendo." << endl;
>         cout << "\tDebes escribir un número mayor o igual a 0." << endl;
>         cout << "\tSi escribes un cero, se termina." << endl;
>         cout << "Después te pediré el divisor." << endl;
>         cout << "Entonces iré escribiendo la división como lo harías tú en
> papel." << endl;
>         cout << "Bueno, más o menos :-)" << endl;
>         cout << "Vale. ¡Vamos allá!" << endl;
> }
>
> long GetDividendo()
> {
>         long numerador = 0;
>         cout << "Dame el dividendo (Recuerda que 0 es para terminar)" <<
> endl;
>         cin >> numerador;
>         return(numerador);
> }
>
> long GetDivisor()
> {
>         long denominador = 0;
>         cout << "Dame el divisor (no puede ser 0)" << endl;
>         cin >> denominador;
>         return(denominador);
> }
>
> int main()
> {
>         MuestraAyuda();
>         long numerador = 1, denominador = 1;
>         while( numerador = GetDividendo() )
>         {
>                 if(numerador)
>                 {
>                         if( denominador = GetDivisor() )
>                         {
>                                 Division *pagina = new Division(numerador,
> denominador);
>                                 pagina->DibujaLaDivision();
>                                 #ifdef verbose
>                                         pagina->Pinta();
>                                 #endif
>                                 int cifrasNumerador =
> pagina->GetNumeroDeCifras(numerador);
>                                 for(int cifra = 0; cifra <
> cifrasNumerador; cifra++)
>                                 {
>                                         long numSiguiente =
> pagina->BajaLaCifraSiguiente();
>                                         long cocParcial =
> pagina->GetCociente(numSiguiente);
>                                         long resParcial =
> pagina->GetResto(numSiguiente);
>                                 }
>                                 // Al bajar la cifra siguiente a la última
> es
>                                 // cuando se coloca en la cuadrícula.
>                                 pagina->BajaLaCifraSiguiente();
>                                 pagina->Pinta();
>                                 delete pagina;
>                         }
>                 }
>                 cout << endl ;
>         }
>         return 0;
> }
>
>
> [Resultado]
> marcelinux en HP:~/ds$ g++ -odividete_v3 dividete_v3.cpp division_v3.cpp
> marcelinux en HP:~/ds$ ./dividete_v3
>
>
> Hijo, comprueba tu división.
> Lo ha hecho papá para que ganes tiempo en tus deberes.
> No para que hagas trampa ;-)
> Funciona así:
> Primero te pediré el dividendo.
>         Debes escribir un número mayor o igual a 0.
>         Si escribes un cero, se termina.
> Después te pediré el divisor.
> Entonces iré escribiendo la división como lo harías tú en papel.
> Bueno, más o menos :-)
> Vale. ¡Vamos allá!
> Dame el dividendo (Recuerda que 0 es para terminar)
> 35437
> Dame el divisor (no puede ser 0)
> 283
>
> 35437      | 283
>            L________
> 3            00125
> 35
> 354
>  713
>  1477
>    62
>
> __________________________________________________________________
> Programador, ávido de conocimiento y algo testarudo.
> Gracias a todos los que comparten. Espero poder devolver el favor.
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20141008/2fc829c4/attachment.html>


Más información sobre la lista de distribución Cconclase