Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.10.3  Sentencias de iteración

§1  Sinopsis

Las sentencias de iteración permiten repetir una sentencia o conjunto de ellas. Es lo que se denomina ejecutar un bucle. En C++ existen tres formas de iteraciones: los bucles while; do…while y for.

Observe que en todos los casos el bucle puede estar constituido por una sola sentencia o por varias. En cuyo caso se trata de un bloque de código delimitado por un par de corchetes { } ( 3.2.6). Si se trata de una sola sentencia, los corchetes no son necesarios.

§2  Bucle   while

La sentencia while permite ejecutar repetidamente un bloque de código mientras se cumpla una determinada condición que es chequeada antes de cada iteración.

§2.1  Sintaxis

while ( <condicion> ) <sentencia> ;

§2.2  Descripción

La sentencia while ejecuta iterativamente el bucle definido por el bloque de código <sentencia> siempre que el valor devuelto por la expresión <condición> (que debe estar entre paréntesis) sea cierto.

Nota: recordemos que cierto (true) equivale numéricamente a distinto de cero ( 3.2.1b), mientras que falso (false) equivale al valor cero.

Puesto que la condición se evalúa antes que cada ejecución del bucle, si al comienzo <condicion> devuelve falso, <sentencia> no se ejecuta ninguna vez, y el control pasa a la siguiente sentencia. Si <condición> devuelve cierto se ejecuta el bucle <sentencia>, y a continuación se vuelve a evaluar <condicion> con lo que se repite el ciclo.

§2.3  Ejemplos

while (*p == ' ') p++;
while ( i <= j) i++;

La sentencia puede estar vacía, realizándose entonces toda la computación requerida en la cláusula <condición>. Ejemplo:

while ( getchar() != 'Z' );

Aunque lo normal es que la <sentencia> sea un bloque de código entre corchetes:

while (i < n) {

  cout << i << endl;

  ++i;

}


Intente por sí mismo la explicación de las salidas del programa adjunto antes de leer el comentario final (esta disposición es muy utilizada en bucles que deben repetirse un número n de veces).

#include <iostream>
using namespace std;

int main() {   // ==========
  int x = 5, y = 5;

  while ( x-- ) {
    cout << "x = " << x << endl;
  }

  while ( --y ) {
    cout << " y = " << y << endl;
  }

  cout << "Terminado!!" << endl;
}

Salida:

x = 4
x = 3
x = 2
x = 1
x = 0
y = 4
y = 3
y = 2
y = 1
Terminado!!

Comentario

En ambas iteraciones, la condición indicada en el paréntesis es chequeada antes de ejecutar la iteración (la salida en pantalla).  La diferencia entre ambos es que el postdecremento (x--) se realiza después de la evaluación del paréntesis (comprobación de que su contenido es cierto). En consecuencia, el ciclo del primer bucle es como sigue:

  1. comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
  2. decremento unitario de x
  3. dos posibilidades:
    1. R == true  →  ejecutar el bucle (salida en pantalla) →  volver al punto 1.
    2. R == false  →  abandonar el bucle.

En cambio, en el segundo bucle, el predecremento (--x) se realiza antes de la evaluación del paréntesis (comprobación de la condición del bucle). En consecuencia, el ciclo del segundo bucle puede resumirse así:

  1. decremento unitario de x
  2. comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
  3. dos posibilidades:
    1. R == true  →  ejecutar el bucle (salida en pantalla) →  volver al punto 1.
    2. R == false  →  abandonar el bucle.
§3  Bucle  do...while

La sentencia do ...  while permite ejecutar repetidamente un bloque de código mientras se cumpla una determinada condición que es chequeada después de cada iteración.

§3.1  Sintaxis

do <sentencia> while ( <condición> );

§3.2  Descripción

La sentencia do ejecuta repetidamente el bucle definido por el bloque de código <sentencia> hasta que la sentencia de control <condición> devuelve el valor falso.

Puesto que el control se evalúa después de cada ejecución del bucle, resulta que este se ejecuta al menos una vez, aunque <condición> devuelva el valor falso desde el principio (si requiere que el bucle no se ejecute ninguna vez, es mejor utilizar while).

La forma más genérica de la expresión suele ser:

do {
   <sentencia> ;
}  while ( <condición> );

§3.3  Ejemplo

Este programa solicita una clave de acceso indefinidamente hasta que el usuario proporciona una que coincide con el valor almacenado en la matriz checkword.

#include <stdio.h>
#include <string.h>
 
int main () {        // ===================
   char checkword[80] = "password";
   char password[80]  = "";
   do {
      printf ("Introducir clave: ");
      scanf("%s", password);
   } while (strcmp(password, checkword));
   return 0;
}

Nota: C++ no dispone en ninguna de sus sentencias de bucle de la opción loop (o similar), como la ofrecida por otros lenguajes para saltar al principio desde cualquier punto de la iteración. No obstante, ofrece alternativas que pueden servir para el caso. Ver las sentencias goto y continue en el siguiente capítulo ( 4.10.4).


A continuación se muestra un caso simétrico al presentado para los bucles while , que utiliza los operadores unitarios de decremento. Intente explicar por sí mismo las salidas obtenidas antes de leer el comentario:

#include <iostream>
using namespace std;

int main() {    // ========
  int x = 5, y = 5;

  do {
    cout << "x = " << x << endl;
  } while ( x-- );

  do {
    cout << "y = " << y << endl;
  } while ( --y );

  cout << "Terminado!!" << endl;
}

Salida:

x = 5
x = 4
x = 3
x = 2
x = 1
x = 0
y = 5
y = 4
y = 3
y = 2
y = 1
Terminado OK!!

Comentario

En este caso, las el bloque de código (salida en pantalla) es ejecutado antes del chequeo de la condición expresada en el paréntesis. La diferencia entre ambos bucles es que en el primero, el postdecremento (x--) se realiza después de la evaluación del paréntesis (comprobación de que su contenido es cierto). En consecuencia, el ciclo es como sigue:

  1. ejecutar el bloque de código (salida en pantalla)
  2. comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
  3. decremento unitario de x
  4. dos posibilidades:
    1. R == true  →  volver al punto 1.
    2. R == false  →  abandonar el bucle.

En cambio, en el segundo bucle, el predecremento (--x) se realiza antes de la evaluación del paréntesis (comprobación de la condición del bucle). En consecuencia, su ciclo puede resumirse así:

  1. ejecutar el bloque de código (salida en pantalla)
  2. decremento unitario de x
  3. comprobación de que x es cierto (distinto de cero).  El resultado, que denominaremos R, es un bool.
  4. dos posibilidades:
    1. R == true  →  volver al punto 1.
    2. R == false  →  abandonar el bucle.
§4  Bucle  for

Esta sentencia permite realizar un bucle repetidamente en base a una condición, la cual suele estar basada en el valor de un contador que se actualiza después de cada ejecución del bucle.

§4.1  Sintaxis

for ( [<inicio>] ; [<condicion>] ; [<incremento>] ) <sentencia>

§4.2  Descripción

La sentencia for realiza un bucle iterativo, es equivalente al:

for <inicio> to <condición> step <incremento>
   <sentencia>
next

de otros lenguajes. <inicio> e <incremento> pueden ser llamadas a funciones o sentencias de asignación. <sentencia> es del cuerpo del bucle, y puede ser cualquier bloque de código.

La utilización más común suele adoptar la forma:

for ( <inicio> ; <condición> ; <incremento> ) {
   <sentencia>;
}

Ejemplo

for(i=0; i<n; i++) { /* sentencias del bucle */ }

  <inicio> inicia las variables para el bucle antes de la primera iteración. Puede ser una expresión o una declaración. El ejemplo que sigue sería correcto en C++:

for (int i=0; i<10; i++)  printf("i =%5.0d\n", i);

En cambio, para compilarlo en C sería necesario declarar i en una expresión anterior:

int i;
for (i=0; i<10; i++)  printf("i =%5.0d\n", i);

El ámbito de una variable definida en la expresión <inicio> es variable, depende del interruptor -Vd del compilador .

  <condición> Debe ser una expresión relacional (devuelva un valor lógico). Es comprobada antes de la primera ejecución del bloque <sentencia>, que es ejecutado repetidamente hasta que <condición> sea falso, por lo que si <condición> devuelve falso desde el principio, el bucle no se ejecuta nunca.

  <incremento>. Después de cada iteración del bucle, <incremento> incrementa un contador de bucle; en consecuencia j++ es funcionalmente equivalente a ++j.

  <sentencia> es el bucle de for; sentencia o bloque de código que se ejecuta iterativamente. El ámbito de cualquier identificador declarado dentro él se limita al final de la sentencia de control.

  Todas las expresiones son opcionales, pero los separadores ; no pueden faltar. Si falta <condición>, se supone que es siempre cierta, por lo que se trata de un bucle indefinido del que se saldrá por otro mecanismo externo al propio for, que pueden ser un break ( 4.10.4) o un return ( 4.10.4). Es típico utilizar este tipo de construcciones para construir bucles con una o más condiciones de salida:

for ( ; ; ) {     // bucle infinito del que se sale con varias
                  // condiciones mediante diversas técnicas
   ...
   if ( C == 'f' )  break;
   ...
   if ( C == 'd' )  break;
   ...
   if ( C == 'x' )  return;
   ...
   if ( C == 'z' )  throw (false);
}

§4.3  Ejemplos

Función que lee una línea (por teclado) y devuelve su longitud. Utiliza una expresión <condición> del for compuesta; lim es la longitud máxima que puede ser leída.

int getLine (char s[], int lim) {
   int c, i;
   for (i = 0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; i++) s[i]=c;
   if (c == '\n') {
      ++i;
      ...
   }
  ...
}


Bucle indefinido (de una sola sentencia) que espera la pulsación de una tecla:

for( ; ; ) if(getch()!=0) break;     // break sale del bucle

equivale a:

for( ; ; ) {
   if(getch()!=0) break;
}

  Tema relacionado
  • Sentencias de salto: break, continue, goto y return     4.10.4 
  • Tener presente la advertencia señalada en 4.9.12.
§5  Opción de compilación -Vd

El compilador C++Builder dispone de una opción -Vd ( 1.4.3), que permite alterar el ámbito de las variables declaradas en la expresión <inicio>. Si está desconectado (por defecto), él ámbito se limita solo al interior del bloque <sentencia>. Si está activada (se compila con -Vd), el ámbito se extiende al interior del bloque que contiene al for.

Al compilar el ejemplo que sigue con las opciones por defecto, se obtiene un error: Símbolo indefinido para el identificador i por la sentencia que está fuera del bucle. Si se compila con -Vd, la compilación se realiza sin problema.

int main(void) {
 {         // comienzo del bloque que contiene al for.
   for(int i=0; i<10; i++) {
      cout << "Dentro del bucle, i = " << i << endl;
   }       //final del bloque <sentencia>
   cout << "Fuera del bucle, i = " << i << endl;  //error sin -Vd
 }         //final del bloque que contiene el for
}