Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: DamnSystem en 5 Noviembre 2017, 23:27 pm



Título: Dos dudas para mejorar el código
Publicado por: DamnSystem en 5 Noviembre 2017, 23:27 pm
Bueno estaba realizando ejercicios y ahora que acabo de terminarlo y antes de seguir con los demás quiero saber como mejorarlo ( voy a mirar la forma de hacerlo con un bucle en vez de tanto if, y la otra duda es cuando meto mas dígitos en el entero de que lo que soporta ejemplo 99999999999999999, el programa ( al menos a mi ) entra en bucle y se queda bloqueado alguna forma de solucionarlo ( no tendría por que hacerlo pero así voy aprendiendo).

Paso código:

//  21. Un número entero n se dice que es desgarrable (torn) si al dividirlo en dos partes
//  cualesquiera izda y dcha, el cuadrado de la suma de ambas partes es igual a n. Por ejemplo,
//  88209 es desgarrable ya que (88 + 209)2 = 88209; 81 también lo es ya que 81 =
//  (8+1)2.Cread un programa que lea un entero ne indique si es ono desgarrable.
//  Finalidad: Ejercitar los bucles. Dificultad Baja.

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    //  Variables y constantes
    int numero_introducido = 0, contador = 1, cifra1 = 0, cifra2 = 0, cifra3 = 0, cifra4 = 0, cifra5 = 0, cifra6 = 0, numero_backup = 0, operado = 0, cifra_total = 0, concatenacion1 = 0, concatenacion2 = 0;
   
    //  Entrada del programa
    do{
    cout << "Introduzca un numero para comprobar si es desgarrable: " << endl;
    cin >> numero_introducido;
    }while(numero_introducido > 999999);
    numero_backup = numero_introducido;
   
    //  Resolucion del programa
    while (numero_introducido / 10 > 0){
        numero_introducido = numero_introducido / 10;
        contador++;
    }
    cout << "Cifras del numero introducido son: " << contador << endl;
    if(contador == 1){
        cout << "El numero no es desgarrable: " << numero_introducido << endl;
    }
    else if (contador == 2){
        //  Con el algoritmo de la division a = b+c + r
        //  Cociente y resto
        cifra1 = numero_backup / 10;
        cifra2 = numero_backup % 10;
        cifra_total = cifra1 + cifra2;
        operado = pow(cifra_total, 2);
        if(numero_backup == operado){
            cout << "El numero: " << numero_backup << " es un numero desgarrable. " << endl;
        }
        else{
            cout << "No es un numero desgarrable" << endl;
        }
    }
    else if (contador == 3){
        cifra1 = numero_backup / 100;
        cifra2 = (numero_backup % 100) / 10;
        cifra3 = numero_backup % 10;
        concatenacion1 = (cifra1 * 10) + cifra2;
        cout << concatenacion1 << endl;
        concatenacion2 = cifra3;
        cout << concatenacion2 << endl;
        cifra_total = concatenacion1 + concatenacion2;
        operado = pow(cifra_total,2);
        if (numero_backup == operado){
            cout << "El numero: " << numero_backup << " es un numero desgarrable. " << endl;
        }
        else{
            cout << "No es un numero desgarrable." << endl;
        }
    }
    else if (contador == 4){
        cifra1 = numero_backup / 1000;
        cifra2 = (numero_backup % 1000) / 100;
        cifra3 = (numero_backup % 100) / 10;
        cifra4 = (numero_backup % 10);
        concatenacion1 = (cifra1 * 10) + cifra2;
        concatenacion2 = (cifra3 * 10) + cifra4;
        cifra_total = (concatenacion1) + (concatenacion2);
        operado = pow(cifra_total, 2);
        if (numero_backup == operado){
            cout << "El numero: " << numero_backup << " es un numero desgarrable. " << endl;
        }
        else{
            cout << "No es un numero desgarrable." << endl;
        }
    }
    else if (contador == 5){
        cifra1 = numero_backup / 10000;
        cifra2 = (numero_backup % 10000) / 1000;
        cifra3 = (numero_backup % 1000) / 100;
        cifra4 = (numero_backup % 100) / 10;
        cifra5 = (numero_backup % 10);
        concatenacion1 = (cifra1 * 10) + cifra2;
        concatenacion2 = (cifra3 * 100) + (cifra4 * 10) + cifra5;
        cifra_total = concatenacion1 + concatenacion2;
        operado = pow(cifra_total, 2);
        if (numero_backup == operado){
            cout << "El numero: " << numero_backup << " es un numero desgarrable. " << endl;
        }
        else{
            cout << "No es un numero desgarrable. " << endl;
        }
    }
    else if (contador == 6){
        cifra1 = numero_backup / 100000;
        cifra2 = (numero_backup % 100000) / 10000;
        cifra3 = (numero_backup % 10000) / 1000;
        cifra4 = (numero_backup % 1000) / 100;
        cifra5 = (numero_backup % 100) / 10;
        cifra6 = (numero_backup % 10);
        concatenacion1 = (cifra1 * 100) + (cifra2 * 10) + cifra3;
        concatenacion2 = (cifra4 * 100) + (cifra5 * 10) + cifra6;
        cifra_total = concatenacion1 + concatenacion2;
        operado = pow(cifra_total, 2);
        if (numero_backup == operado){
            cout << "El numero: " << numero_backup << " es un numero desgarrable. " << endl;
        }
        else{
            cout << "No es un numero desgarrable.  " << endl;
        }
    }
    return 0;
}


Título: Re: Dos dudas para mejorar el código
Publicado por: ivancea96 en 5 Noviembre 2017, 23:41 pm
Respuesta rápida:
Cuando el número está fuera del rango o no se introduce un número, "cin" pone su flag "fail" a true. Con esta flag a true, cualquier próxima lectura va a fallar (por tanto, no vuelve a pedir input y no sale del while).
Para limpiar esa bandera, basta llamar a "cin.clear();".
Para comprobar si la banderá está puesta, puedes llamar a "cin.fail()" (retorna true si está, false si no).


Título: Re: Dos dudas para mejorar el código
Publicado por: DamnSystem en 6 Noviembre 2017, 11:48 am
Mil gracias voy a probarlo ahora mismo :) y algún consejo para que el código que he puesto sea menos o alguna forma de hacerlo mas eficiente?


Título: Re: Dos dudas para mejorar el código
Publicado por: Serapis en 6 Noviembre 2017, 14:21 pm
Como bien se señala, la idea es ejercitar los bucles. Usando bucles, surge la necesidad de usar también arrays o bien variables reutilizables, y no tantas variables para 'componentes individuales'.

La idea es algo así como usar una llave inglesa en vez de 30 llaves fijas de distinto tamaño.

En pseudocodigo de una manera clara, a base de más líneas de código,
podría ser más o menos así (fíjate que las funciones las pongo en orden inverso a como son llamadas, sólo para que veas desde el final hacia el principio):

Esta función, verifica que dados dos valores son o no entre sí desgarrables (en el orden introducido).
Código:
Buleano = Funcion EsDesgarrable(entero valor, entero valor1, entero valor2)
    string v1 = ((valor1 + valor2)^2).ToString
  
    devolver (v1 = valor.ToString)
Fin funcion


Esta función toma un valor de entrada y genera para el todos los posibles despieces y con cada uno verifica si cumple lo esperado.
Código:
buleano = Funcion DesgarrarValor(entero valor)
    string numeroStr = valor.ToString
    entero digitos = caracteresen(numerostr)
    entero k, n1, n2
    string s1, s2

    bucle para k desde 1 a digitos-1
        s1 = TomarCaracteresDesdeIzquierda(numeroStr, k)
        s2 = TomarCaracteresDesdeDerecha(numeroStr, digitosStr-k)
        n1 = ConvertirAEntero(s1)
        n2 = ConvertirAEntero(s2)
      
        Si EsDesgarrable(valor, n1, n2) = TRUE luego
            devolver TRUE
        fin si    
    fin bucle

    devolver FALSE
fin funcion

La función principal se compone de  1 petición de entrada al usuario (aquí dos, pero puede señalarse un "Introduzca 0 para terminar") y luego una llamada a la función que verifica el asunto y devuelve el resultado, que luego se muestra al usuario... Todo ello encerrado en un bucle hasta que el usuario 'se canse'...
Código:
funcion Problema21
    entero numero
    buleano resultado
    string masPreguntas

    Hacer    
          numero = pedirNumeroAlUsuario
          resultado = Desgarrar(numero)
          Si (resultado = TRUE) luego
              mostrarMensaje "El número introducido es desgarrable."
          sino
              mostrarMensaje "el número introducido no es desgarrable."
          fin si

          // en la peición de arriba puede aceptarse un valor 0, como fin de operaciones, en vez de solicitarlo explícitamente aquí.
          masPreguntas = PedirAlUsusario("desea proceder con otro número (s/n) ?."
    Repetir mientras masPreguntas = "s" //"yes", "si", "y", >0, etc....
fin funcion

Como puedes ver, con solo 3 funciones y aún no simplificándolas el código resultante es muy breve. Bastan 2 bucles y unas pocas variables, que incluso podrían ser menos... el caso presente, no precisa ningún array.

Nota que básicamente al desguazar el número hemos operado convirtiendo en número en una cadena de texto, de la que hemos partido en dos trozos (en un bucle, según lo largo del mismo) y luego a conveniencia volver a convertir en número para hacer las operaciones... siempre es más eficiente operar con números que con cadenas, pero el objetivo del ejecrcicio es plantear la solución al problema para operar con bucles, el objetivo aquí no es lograr una eficiencia óptima. ...es importante que entiendas ambas cosas.

Queda a tu esfuerzo convertir el pseudocódigo a C, para lo que te será necesario entenderlo.

p.d.: Nota, que no he considerado el caso de números negativos... la respuesta es buien fácil, pero tú como lo solucionarías?