AnteriorPosterior

4. Bucles

  Curso: Introducción a C++

4. Bucles

Hemos visto cómo comprobar condiciones , pero no cómo hacer que una cierta parte de un programa se repita un cierto número de veces o mientras se cumpla una condición (lo que llamaremos un “bucle”). En C y en C++ tenemos varias formas de conseguirlo.

4.1. while

Si queremos hacer que una sección de nuestro programa se repita mientras se cumpla una cierta condición, usaremos la orden “while”. Esta orden tiene dos formatos distintos, según comprobemos la condición al principio o al final.

En el primer caso, su sintaxis es

while (condición)
    sentencia;

Es decir, la sentencia se repetirá mientras la condición sea cierta. Si la condición es falsa ya desde un principio, la sentencia no se ejecuta nunca. Si queremos que se repita más de una sentencia, basta agruparlas entre { y }. Como ocurria con "if", puede ser recomendable incluir siempre las llaves, aunque sea una única sentencia, para evitar errores posteriores difíciles de localizar.

Un ejemplo que nos diga si cada número que tecleemos es positivo o negativo, y que pare cuando tecleemos el número 0, podría ser:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.01:
// La orden "while"
 
#include <iostream>
using namespace std;
 
int main()
{
    int numero;
 
    cout << "Teclea un numero (0 para salir): ";
    cin >> numero;
    while (numero!=0)
    {
        if (numero > 0) 
            cout << "Es positivo" << endl;
        else 
            cout << "Es negativo" << endl;
        cout << "Teclea otro numero (0 para salir): ";
        cin >> numero;
    }
 
    return 0;
}
 

En este ejemplo, si se introduce 0 la primera vez, la condición es falsa y ni siquiera se entra al bloque del “while”, terminando el programa inmediatamente.

Nota: si recordamos que una condición falsa se evalúa como el valor 0 y una condición verdadera como una valor distinto de cero, veremos que ese “while (numero != 0)” se podría abreviar como “while (numero)”.

Ejercicios propuestos:

  • (4.1.1) Crear un programa que pida al usuario su contraseña (numérica). Deberá terminar cuando introduzca como contraseña el número 4567, pero volvérsela a pedir tantas veces como sea necesario.
  • (4.1.2) Crea un programa que escriba en pantalla los números del 1 al 10, usando “while”.
  • (4.1.3) Crea un programa que escriba en pantalla los números pares del 26 al 10 (descen­diendo), usando “while”.
  • (4.1.4) Crear un programa calcule cuantas cifras tiene un número entero positivo (pista: se puede hacer dividiendo varias veces entre 10).

4.2. do ... while

Este es el otro formato que puede tener la orden “while”: la condición se comprueba al final. El punto en que comienza a repetirse se indica con la orden “do”, así:

do
    sentencia;
while (condición);

Al igual que en el caso anterior, si queremos que se repitan varias órdenes (es lo habitual), deberemos encerrarlas entre llaves. Nuevamente, puede ser recomendable incluir siempre las llaves, como costumbre.

Como ejemplo, vamos a ver cómo sería el típico programa que nos pide una clave de acceso y nos nos deja entrar hasta que tecleemos la clave correcta. Eso sí, como todavía no sabemos manejar cadenas de texto, la clave será un número:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.02:
// La orden "do..while"
 
#include <iostream>
using namespace std;
 
int main()
{
    int valida = 711;
    int clave;
 
    do
    {
        cout << "Introduzca su clave numérica: ";
        cin >> clave;
        if (clave != valida) 
            cout << "No válida!" << endl;
    }
    while (clave != valida);
 
    cout << "Aceptada." << endl;
    return 0;
}
 

En este caso, se comprueba la condición al final, de modo que se nos preguntará la clave al menos una vez. Mientras que la respuesta que demos no sea la correcta, se nos vuelve a preguntar. Finalmente, cuando tecleamos la clave correcta, el ordenador escribe “Aceptada” y termina el programa.

Ejercicios propuestos:

  • (4.2.1) Crear un programa que pida números positivos al usuario, y vaya calculando la suma de todos ellos (terminará cuando se teclea un número negativo o cero).
  • (4.2.2) Crea un programa que escriba en pantalla los números del 1 al 10, usando "do..while".
  • (4.2.3) Crea un programa que escriba en pantalla los números pares del 26 al 10 (descen­diendo), usando "do..while".
  • (4.2.4) Crea un programa que pida al usuario su código de usuario (un número entero) y su contraseña numérica (otro número entero), y no le permita seguir hasta que introduzca como código 1024 y como contraseña 4567.

4.3. for

Ésta es la orden que usaremos habitualmente para crear partes del programa que se repitan un cierto número de veces. El formato de “for” es

for (valorInicial; CondiciónRepetición; Incremento)
    sentencia;

Así, para contar del 1 al 10, tendríamos 1 como valor inicial, <=10 como condición de repetición, y el incremento sería de 1 en 1. Por tanto, el programa quedaría:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.03:
// Uso básico de "for" 
 
#include <iostream>
using namespace std;
 
int main()
{
    int contador;
 
    for (contador=1; contador<=10; contador++)
        cout << contador << " ";
 
    return 0;
}
 

Recordemos que “contador++” es una forma abreviada de escribir “contador=contador+1”, de modo que en este ejemplo aumentamos la variable de uno en uno.

Ejercicios propuestos:

  • (4.3.1) Crear un programa que muestre los números del 15 al 5, descendiendo (pista: en cada pasada habrá que descontar 1, por ejemplo haciendo i--).
  • (4.3.2) Crear un programa que muestre los primeros ocho números pares (pista: en cada pasada habrá que aumentar de 2 en 2, o bien mostrar el doble del valor que hace de contador).

En un “for”, realmente, la parte que hemos llamado “Incremento” no tiene por qué incrementar la variable, aunque ése es su uso más habitual. Es simplemente una orden que se ejecuta cuando se termine la “Sentencia” y antes de volver a comprobar si todavía se cumple la condición de repetición.

Por eso, si escribimos la siguiente línea:

for (contador=1; contador<=10; )

la variable “contador” no se incrementa nunca, por lo que nunca se cumplirá la condición de salida: nos quedamos encerrados dando vueltas dentro de la orden que siga al “for”.

Un caso todavía más exagerado de algo a lo que se entra y de lo que no se sale sería la siguiente orden:

for ( ; ; )

Los bucles “for” se pueden anidar (incluir uno dentro de otro), de modo que podríamos escribir las tablas de multiplicar del 1 al 5 con:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.04:
// "for" anidados - tablas de multiplicar
 
#include <iostream>
using namespace std;
 
int main()
{
    int tabla, numero;
 
    for (tabla=1; tabla<=5; tabla++)
        for (numero=1; numero<=10; numero++)
            cout << tabla <<  " por " <<  numero
                << " es " << tabla*numero << endl;
 
    return 0;
}
 

En estos ejemplos que hemos visto, después de “for” había una única sentencia. Si queremos que se hagan varias cosas, basta definirlas como un bloque (una sentencia compuesta) encerrándolas entre llaves. Por ejemplo, si queremos mejorar el ejemplo anterior haciendo que deje una línea en blanco entre tabla y tabla, sería:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.05:
// "for" anidados (2) - tablas de multiplicar separadas
 
#include <iostream>
using namespace std;
 
int main()
{
    int tabla, numero;
 
    for (tabla=1; tabla<=5; tabla++)
    {
        for (numero=1; numero<=10; numero++)
            cout << tabla <<  " por " <<  numero
                << " es " << tabla*numero << endl;
        cout << endl;
    }
 
  return 0;
}
 

Al igual que ocurría con "if" y con "while", suele ser buena costumbre incluir siempre las llaves, aunque haya una única orden que se repita en el "for", para evitar funcionamientos incorrectos si después hay que añadir más sentencias que deban repetirse y se olvida incluir las llaves en ese momento.

 

Para “contar” no necesariamente hay que usar números. Por ejemplo, podemos contar con letras así:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.06:
// "for" que usa "char"
 
#include <iostream>
using namespace std;
 
int main()
{
    char letra;
 
    for (letra='a'; letra<='z'; letra++)
        cout << letra;
 
    return 0;
}
 

Como se ve en este ejemplo, el tipo de datos que se utiliza para almacenar una letra es el tipo "char" (carácter). Los valores de un carácter se indican entre comillas simples.

En este caso, empezamos en la “a” y terminamos en la “z”, aumentando de uno en uno.


Si queremos contar de forma decreciente, o de dos en dos, o como nos interese, basta indicarlo en la condición de finalización del “for” y en la parte que lo incrementa:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.07:
// "for" que descuenta
 
#include <iostream>
using namespace std;
 
int main()
{
    char letra;
 
    for (letra='z'; letra>='a'; letra-=2)
        cout << letra;
 
    return 0;
}
 

Ejercicios propuestos:

  • (4.3.3) Crear un programa que muestre las letras de la Z (mayúscula) a la A (mayúscula, descendiendo).
  • (4.3.4) Crear un programa que escriba en pantalla la tabla de multiplicar del 6.
  • (4.3.5) Crear un programa que escriba en pantalla los números del 1 al 50 que sean múltiplos de 3 (pista: habrá que recorrer todos esos números y ver si el resto de la división entre 3 resulta 0).

4.4. Sentencia break: termina el bucle

Podemos salir de un bucle “for” antes de tiempo con la orden “break”:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.08:
// "for" interrumpido con "break" 
 
#include <iostream>
using namespace std;
 
int main()
{
    int i;
 
    for (i=0; i<=10; i++)
    {
        if (i==5) break;
        cout << i << " ";
    }
 
    return 0;
}
 

El resultado de este programa es:

0 1 2 3 4

(en cuanto se llega al valor 5, se interrumpe el “for”, por lo que no se alcanza el valor 10).

Ejercicio propuesto:

  • (4.4.1) Crear un programa que pida un número al usuario (entre 1 y 100) y muestre tantas letras A como indique ese número, usando "break" para terminar.

4.5. Sentencia continue: fuerza la siguiente iteración

Podemos saltar alguna repetición de un bucle con la orden “continue”:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.09:
// "for" interrumpido con "continue"
 
#include <iostream>
using namespace std;
 
int main()
{
    int i;
 
    for (i=0; i<=10; i++)
    {
        if (i==5) continue;
        cout << i << " ";
    }
 
    return 0;
}
 

El resultado de este programa es:

0 1 2 3 4 6 7 8 9 10

En él podemos observar que no aparece el valor 5.

 

Ejercicio propuesto:

  • (4.5.1) Crear un programa que pida un número al usuario (entre 1 y 20) y muestre los números el 1 al 20, excepto el indicado por el usuario, usando "continue" para evitar ese valor.

Ejercicios resueltos:

> ¿Qué escribiría en pantalla este fragmento de código?

for (i=1; i<4; i++) cout << i << " ";

Respuesta: los números del 1 al 3 (se empieza en 1 y se repite mientras sea menor que 4).

> ¿Qué escribiría en pantalla este fragmento de código?

for (i=1; i>4; i++) cout << i << " ";

Respuesta: no escribiría nada, porque la condición es falsa desde el principio ("i" vale 1, que no es mayor que 4).

> ¿Qué escribiría en pantalla este fragmento de código?

for (i=1; i<=4; i++); cout << i << " ";

Respuesta: escribe un 5, porque hay un punto y coma después del “for”, de modo que repite cuatro veces una orden vacía, y cuando termina, “i” ya tiene el valor 5.

> ¿Qué escribiría en pantalla este fragmento de código?

for (i=1; i<4; ) cout << i << " ";

Respuesta: escribe “1” continuamente, porque no aumentamos el valor de “i”, luego nunca se llegará a cumplir la condición de salida.

> ¿Qué escribiría en pantalla este fragmento de código?

for (i=1; ; i++) cout << i << " ";

Respuesta: escribe números continuamente, comenzando en uno y aumentando una unidad en cada pasada, pero si terminar nunca.

> ¿Qué escribiría en pantalla este fragmento de código?

for ( i= 0 ; i<= 4 ; i++) 
{
    if ( i == 2 ) continue ; 
    cout << i << " ";
}

Respuesta: escribe los números del 0 al 4, excepto el 2.

> ¿Qué escribiría en pantalla este fragmento de código?

for ( i= 0 ; i<= 4 ; i++) 
{
    if ( i == 2 ) break ; 
    cout << i << " ";
}

Respuesta: escribe los números 0 y 1 (interrumpe en el 2).

> ¿Qué escribiría en pantalla este fragmento de código?

for ( i= 0 ; i<= 4 ; i++) 
{
    if ( i == 10 ) continue ; 
    cout << i << " ";
}

Respuesta: escribe los números del 0 al 4, porque la condición del “continue” nunca se llega a dar.

> ¿Qué escribiría en pantalla este fragmento de código?

for ( i= 0 ; i<= 4 ; i++) 
    if ( i == 2 ) continue ; 
    cout << i << " ";

Respuesta: escribe 5, porque no hay llaves tras el “for”, luego sólo se repite la orden “if”.

 

4.6. Sentencia goto

Los lenguajes C y C++ también permiten usar la orden “goto”, para hacer saltos incondicionales. Su uso indisciplinado está muy mal visto, porque puede ayudar a hacer programas llenos de saltos, difíciles de seguir. Pero en casos concretos puede ser muy útil, por ejemplo, para salir de un bucle muy anidado (un “for” dentro de otro “for” que a su vez está dentro de otro “for”: en este caso, “break” sólo saldría del “for” más interno).

El formato de “goto” es

  goto donde;

y la posición de salto se indica con su nombre seguido de dos puntos (:)

  donde:

como en el siguiente ejemplo:

// Introducción a C++, Nacho Cabanes
// Ejemplo 04.10:
// "for" y "goto"
 
#include <iostream>
using namespace std;
 
int main()
{
    int i, j;
 
    for (i=0; i<=5; i++)
        for (j=0; j<=20; j+=2)
        {
            if ((i==1) && (j>=7)) 
                goto salida;
            cout << "i vale " << i << " y j vale "
                << j << endl;
        }
    salida:
    cout << "Fin del programa" << endl;
 
    return 0;
}
 

El resultado de este programa es:

i vale 0 y j vale 0.
i vale 0 y j vale 2.
i vale 0 y j vale 4.
i vale 0 y j vale 6.
i vale 0 y j vale 8.
i vale 0 y j vale 10.
i vale 0 y j vale 12.
i vale 0 y j vale 14.
i vale 0 y j vale 16.
i vale 0 y j vale 18.
i vale 0 y j vale 20.
i vale 1 y j vale 0.
i vale 1 y j vale 2.
i vale 1 y j vale 4.
i vale 1 y j vale 6.
Fin del programa

Vemos que cuando i=1 y j>=7, se sale de los dos “for” a la vez, tal y como indicaba la orden "goto".

4.7. Recomendación de uso de los distintos tipos de bucle

  • En general, nos interesará usar “while” cuando puede que la parte repetitiva no se llegue a repetir nunca (por ejemplo: cuando leemos un fichero, si el fichero está vacío, no habrá datos que leer).
  • De igual modo, “do...while” será lo adecuado cuando debamos repetir al menos una vez (por ejemplo, para pedir una clave de acceso, se le debe preguntar al menos una vez al usuario, o quizá más veces, si la teclea correctamente).
  • En cuanto a “for”, es equivalente a un “while”, pero la sintaxis habitual de la oren “for” hace que sea especialmente útil cuando sabemos exactamente cuantas veces queremos que se repita (por ejemplo: 10 veces sería “for (i=1; i<=10; i++)”).

Ejercicios propuestos:

  • (4.7.1) Crear un programa que dé al usuario la oportunidad de adivinar un número del 1 al 100 (prefijado en el programa) en un máximo de 6 intentos. En cada pasada deberá avisar de si se ha pasado o se ha quedado corto.
  • (4.7.2) Crear un programa que descomponga un número (que teclee el usuario) como producto de su factores primos. Por ejemplo, 60 = 2 · 2 · 3 · 5


Actualizado el: 30-08-2013 10:28

AnteriorPosterior