Bucle for

El bucle for está concebido fundamentalmente para ejecutar sus sentencias asociadas un número fijo de veces.

Por tanto, cuando el número de iteraciones necesarias para realizar una tarea en una parte del programa se conoce de antemano, lo más lógico es el empleo de una estructura tipo for, que controla automáticamente el número de repeticiones.

El diseño sintáctico de la sentencia compuesta for es la de integrar un contador, con su valor inicial, su valor final y un valor fijo de incremento.

for (inicializacion; condicion; incremento)
{
   bloque de sentencias;
}
../../_images/for.jpg

Diagrama de flujo de la sentencia for

El siguiente fragmento de código imprime por pantalla los números del 1 al 10.

int i;
for (i = 1; i <= 10; ++i)
{
   cout << i << endl;
}

Esta figura muestra el diagrama de flujo del anterior fragmento de código.

../../_images/for2.jpg

Diagrama de flujo para el ejemplo anterior

Observe el uso del operador ++ por la izquierda para incrementar la variable. En lugar de ++x podría haberse optado por cualquiera de sus alternativas menos eficientes x++, x += 1 o x = x + 1.

Nota

Se conoce en informática con el término pesimización prematura el hecho de utilizar una determinada expresión teniendo a nuestra disposición otra similar más eficiente.

Respecto al incremento en el bucle for:

  • puede ser tanto positivo como negativo.

    for (i = 10; i >= 0; --i)
    {
        cout << i << endl;
    }
    
  • no tiene que ser necesariamente de uno en uno.

    for (i = 0; i <= 20; i += 2)
    {
        cout << i << endl;
    }
    
  • como en el bucle while, en el bucle for se comprueba la condición al inicio del bucle, lo que significa que el código asociado puede que no se ejecute ni una sola vez.

    for (i = 10; i <= 0; --i)
    {
        cout << i << endl;
    }
    

Ejemplo 1

#include <iostream>
using namespace std;

int main()
{
   int i;
   cout << "Bucle 0 al 10\n" << endl;
   for (i = 0; i <= 10; ++i)
   {
      cout << i << endl;
   }

   cout << "\nBucle 10 al 0\n" << endl;
   for (i = 10; i >= 0; --i)
   {
      cout << i << endl;
   }

   cout << "\nBucle con pares del 0 al 20\n" << endl;
   for (i = 0; i <= 20; i += 2)
   {
      cout << i << endl;
   }

   cout << "\nBucle con potencias de 3 del 1 al 100\n" << endl;
   for (i = 1; i <= 100; i *= 3)
   {
      cout << i << endl;
   }

   //Este bucle no se ejecuta
   for (i = 10; i <=0; --i)
   {
      cout << i << endl;
   }
}

Edita, compila y ejecuta el código

Ejemplo 2

// Imprime los valores de menor a mayor entre dos
// solicitados al usuario, ambos incluidos

#include <iostream>
using namespace std;

int main()
{
   int n1, n2;
   cout << "Introduce el primer número: ";
   cin >> n1;
   cout << "Introduce el segundo número: ";
   cin >> n2;

   if (n1 <= n2)
   {
      for (int i = n1; i <= n2; ++i)
            cout << i << endl;
   }
   else
   {
      for (int i = n2; i <= n1; ++i)
            cout << i << endl;
   }
}

Edita, compila y ejecuta el código

Observe como en este ejemplo, la definición de la variable que actúa como contador en la sentencia for se realiza dentro de la propia sentencia, for (int i = n1; i <= n2; ++i). Es una excelente práctica de programación pues satisface simultáneamente dos buenas reglas de estilo:

  1. Define las variables lo más cerca posible de su uso.

  2. Limita el alcance de las variables al ámbito más pequeño posible.

Por otro lado, nótese que las sentencias iterativas constituyen una única sentencia, por lo que el código anterior podría reescribirse como:

...

int main()
{
   ...

   if (n1 <= n2)
      for (int i = n1; i <= n2; ++i)
            cout << i << endl;
   else
      for (int i = n2; i <= n1; ++i)
            cout << i << endl;
}

Ejemplo 3

// Programa que calcula la media de una serie de números

#include <iostream>
using namespace std;

int main()
{
   int num;
   cout << "Introduce el número de valores: ";
   cin >> num;

   double acumulador = 0;
   for (int i = 0; i < num; ++i)
   {
      double valor;
      cout << "Introduce número: ";
      cin >> valor;
      acumulador += valor;
   }
   double media = acumulador/num;
   cout << "La media de los números es "<< media << endl;
}

Edita, compila y ejecuta el código

Nótese en este ejemplo como se ha declarado la variable valor dentro del bucle. Es una buena práctica de programación pues es una variable local a la sentencia for.

En el ejemplo anterior hemos inicializado el contador del bucle for a 0.

...
   for (int i = 0; i < num; ++i)
   {
      double valor;
      cout << "Introduce número: ";
      cin >> valor;
      acumulador += valor;
   }
...

Otra posibilidad hubiese sido:

...
   for (int i = 1; i <= num; ++i)
   {
      double valor;
      cout << "Introduce número: ";
      cin >> valor;
      acumulador += valor;
   }
...

Ambas opciones son válidas, pero lo habitual en C++ es que cuando el bucle for se limita a su uso básico de contar:

  • el contador se inicializa a 0

  • para la condición de salida se usa una comparación <

Cuando veamos vectores se entenderá alguna de las ventajas de la primera fórmula.

Ejemplo 4

// Programa que calcula el factorial de un número

#include <iostream>

using namespace std;

int main()
{
   int numero;
   do
   {
      cout << "Introduce el número entero no negativo: ";
      cin >> numero;
      if (numero < 0)
         cout << "El factorial de un número negativo no existe.\n";
   }
   while (numero < 0);

   int factorial = 1;
   for (int i = numero; i >= 1; --i)
      factorial *= i;
   cout << "El factorial de " << numero << " es " << factorial << endl;
}

Edita, compila y ejecuta el código

En el ejemplo, la variable factorial actúa como acumulador, en este caso respecto de la multiplicación. Por ello, se inicializa a 1, que es el valor neutro para esta operación.