Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Fyrox en 21 Julio 2012, 02:05 am



Título: Reiniciar bucles C++
Publicado por: Fyrox en 21 Julio 2012, 02:05 am
Buenas a todos, finalmente me he lanzado con C++ después de estar en Python y tras un día aprendiendo cosillas basicas me he dispuesto a "traducir" un programa que tenía hecho en Python para descomponer números en factores primos, y me ha quedado esto:

Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main (void)
  5. {
  6.    int n, i, prime[5] = {2, 3, 5, 7, 11};
  7.    cout << "Numero? ";
  8.    cin >> n;
  9.    while (n != 1)
  10.    {
  11.        for (i=0; i<5; i++)
  12.        {
  13.            if (n%prime[i] == 0)
  14.            {
  15.                n = n / prime[i];
  16.                cout << prime [i] << endl;
  17.            }
  18.        }
  19.    }
  20.    cin.ignore();
  21.    cin.get();
  22.  
  23. }
  24.  

El programa funciona a la perfección (bueno, de momento solo tengo puestos 5 primos en el array, pero se cambia fácilmente eso), pero al pedirle que te descomponga ciertos números, como el 20, no muestra los factores ordenados, es decir, en lugar de 2 2 5, muestra 2 5 2. Es cierto que esto no importa en una multiplicación, pero me gusta tener las cosas ordenadas y bonitas xD.

En mi programa de Python esto lo solucionaba añadiendo los factores a una lista en lugar de mostrarlos y luego ordenar e mostrar la lista, pero no encuentro forma de hacer esto en C++, y si la hay sería bastante código que añadir.

Sin embargo, me puse a pensar, y simplemente con algo que me permitiese "reiniciar" el bucle for para que empezara de nuevo a comprobar todos los números funcionaría, pero no sé como hacer esto. Alguna idea? Gracias de antemano.

PD: Soy bastante nuevo en C++ y programando en general, si encontrais cosas que se puedan hacer mejor comentadlo sin problemas, estare agradecido :)


Título: Re: Reiniciar bucles C++
Publicado por: rir3760 en 21 Julio 2012, 02:47 am
Solo tienes que cambiar la lógica del programa para que repita la división entre el factor primo cuantas veces sea posible. Por ejemplo:
Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. int main()
  6. {
  7. int n, i, prime[] = {2, 3, 5, 7, 11};
  8.  
  9. cout << "Numero? ";
  10. cin >> n;
  11.  
  12. i = 0;
  13. while (n != 1){
  14. while (n % prime[i] == 0){
  15. n /= prime[i];
  16. cout << " " << prime [i];
  17. }
  18.  
  19. i++;
  20. }
  21. cout << endl;
  22.  
  23. return 0;
  24. }

En C++ puedes utilizar la clase "vector" y la función "sort" para realizar esa operación de una forma casi automática. Varios ejemplos los puedes revisar en C plus plus (http://www.cplusplus.com/reference/algorithm/sort/).

Un saludo


Título: Re: Reiniciar bucles C++
Publicado por: Fyrox en 21 Julio 2012, 02:57 am
Hola, en primer lugar, gracias por tu rapida respuesta. Mientras esperaba respuestas, me puse a buscar, y encontré una manera de reiniciar el bucle. El programa queda así:

Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main (void)
  5. {
  6.    int n, i, prime[5] = {2, 3, 5, 7, 11};
  7.    cout << "Numero? ";
  8.    cin >> n;
  9.    while (n != 1)
  10.    {
  11.        for (i=0; i<5; i++)
  12.        {
  13.            if (n%prime[i] == 0)
  14.            {
  15.                n = n / prime[i];
  16.                cout << prime[i] << " * ";
  17.                i = -1;
  18.            }
  19.        }
  20.    }
  21.    cin.ignore();
  22.    cin.get();
  23.  
  24. }

Sin embargo,  he leído que no es recomendable nunca cambiar el valor de la i, además de que el código que has hecho parece bastante mejor. De todas formas, me podrías explicar porqué no está bien reiniciar el bucle? Muchas gracias.


Título: Re: Reiniciar bucles C++
Publicado por: rir3760 en 21 Julio 2012, 03:19 am
Sin embargo,  he leído que no es recomendable nunca cambiar el valor de la i, además de que el código que has hecho parece bastante mejor. De todas formas, me podrías explicar porqué no está bien reiniciar el bucle?
Primero porque si te equivocas puedes terminar con un bucle infinito.

Segundo porque es un mala practica. Para explicarlo mejor dado un bucle como este:
Código
  1. int i;
  2.  
  3. for (i = 0; i != N; i++){
  4.   // Algun proceso ...
  5. }
  6.  
Sin revisarlo a detalle podemos concluir que el numero de iteraciones es N (salvo una salida anormal) y aun cuando el bucle termine de forma abrupta basta con revisar el valor del contador.

Pero si "tasajeamos" el contador dentro del bucle eso ya no lo podemos dar por sentado. Imagina que debes leer N lineas de un archivo, con el contador "tasajeado" debes utilizar una variable extra para llevar la cuenta (algo que, para empezar, no es necesario de hacerlo de la forma correcta).

Para una descripción mas técnica (y correcta) puedes buscar en la red paginas relacionadas con "Loop Invariants".

Un saludo


Título: Re: Reiniciar bucles C++
Publicado por: Fyrox en 21 Julio 2012, 03:23 am
Bueno pues muchas gracias por todo! También he estado leyendo lo del vector y el sort, pero no he entendido nada de nada, se me queda un poco grande aun. Creo que para ser el primer día de C++ esta bien, un saludo!