while()
. Equivalencia con
for()
.
do-while()
.
while()
.
for()
en las que hay un número elevado de componentes en las cláusulas de iniciación y actualización. Y también es frecuente hallar sentencias
for()
que se reducen a una cláusula de control: las cláusulas de iniciación y actualización adoptan la forma de sentencias independientes, situadas adecuadamente antes de la sentencia
for()
y dentro del bloque. En tales circunstancias es cómodo emplear una sentencia reducida a la cláusula de control: esta es precisamente la sentencia
while()
, cuya sintaxis es la que se ve a continuación:
while(condición) { Bloque; }
condición
denota una expresión que se evaluará lógicamente: si su valor es nulo, se entenderá que es falsa; y si su valor es no nulo se entenderá que es verdadera. La palabra reservada
while
significa mientras; mientras
condición
sea verdadera, la sentencia
while()
seguirá iterando (ejecutando las sentencias contenidas en el bloque).
while()
, se evalúa condición. Si su valor es verdadero, se efectúa una iteración, y vuelve a evaluarse condición. Si su valor es falso, se ignora el bucle sin haber efectuado ni siquiera una iteración. No se impone restricción alguna sobre las sentencias contenidas en el bloque. Consiguientemente, se admiten las sentencias de control, y en particular la sentencia
while()
. Por tanto, se admite explícitamente el anidamiento de sentencias
while()
.for()
,
while()
es de comprobación anterior (se evalúa la cláusula de control antes de efectuar la primera iteración). Esto sugiere que todo lo que pueda hacerse con una sentencia
for()
será realizable con una sentencia
while()
, y viceversa. Así es. Basta anteponer la cláusula de iniciación de la sentencia
for()
a la sentencia
while()
, e insertar al final del bloque de la sentencia
while()
la cláusula de actualización de la sentencia
for()
. Estas dos sentencias son equivalentes, y la utilización de una u otra será cuestión de comodidad. Es preciso prestar especial atención a la ubicación de las sentencias de actualización dentro del bloque: una situación incorrecta producirá resultados no deseados, y el compilador no detecta este tipo de errores lógicos. La forma segura de utilizar una sentencia
while()
consiste en insertar las sentencias de actualización al final del bloque. Véase un
ejemplo
de utilización de la sentencia
while()
.
do-while()
.
do-while()
, representada gráficamente a la izquierda de estas líneas. La sintaxis de esta sentencia es de la forma:
do { Bloque; } while (condición);Al llegar a esta sentencia, se efectúa una iteración (se ejecuta el contenido del bloque) y se evalúa después la condición de iteración. Si esta condición es verdadera, se efectúa una nueva iteración . En caso contrario, finaliza la ejecución de esta sentencia. Dicho de otra manera, seguiremos iterando mientas se verifique la condición.
do
. Las sentencias de actualización pueden situarse al principio del bloque o al final del mismo, según convenga. La posición inicial dará lugar a que el resto del bloque se ejecute después de la actualización; esto puede ser correcto o incorrecto dependiendo de la iniciación efectuada antes de entrar en el bloque. La posición final hará que se evalúe la sentencia de control antes de efectuar la iteración correspondiente a la última actualización; esto puede ser lo deseado o quizá no, dependiendo del caso concreto. En todo caso habrá que prestar especial atención a las actualizaciones. La sentencia
do-while()
resulta de especial utilidad, como decimos, para imponer al usuario unos ciertos límites al insertar datos en un programa. Si el valor insertado está fuera de los límites especificados, se efectúa una nueva iteración que solicita un valor correcto. Como
ejemplo
, véase una nueva versión del juego Mastermind, que se ha utilizado anteriormente como ejemplo en las sentencias
for()
y
while()
.
while()
, en lugar de emplear una sentencia
for()
. El juego permitirá un número ilimitado de intentos, y comunicará al usuario el número de intentos que ha necesitado para adivinar el número.
/* Otra implementación de MASTERMIND. Este ejercicio muestra el uso de sentencias while() */ #include<stdio.h> #include<time.h> #include<math.h> #define maximo 512 void main(void) { int numero_buscado = clock() % maximo,numero_dado = 0; int numero_pregunta = 0; printf("M A S T E R M I N D\n\n"); printf("He pensado un numero entre 1 y %d.\n\n", maximo); printf("¿Cuántos intentos necesitas para averiguarlo?\n"); while( numero_dado != numero_buscado) { printf("\nIntento número %d : ",++numero_pregunta); scanf("%d",&numero_dado); if (numero_dado < numero_buscado) printf("\nNo, %d es menor que el número que he pensado.\n", numero_dado); else if (numero_dado > numero_buscado) printf("\nNo, %d es mayor que el número que he pensado.\n", numero_dado); } printf("\n\nEnhorabuena! Has necesitado %d intentos.",numero_pregunta); printf("\n\nTerminación normal del programa.\n"); } /* RESULTADO M A S T E R M I N D He pensado un numero entre 1 y 512. ¿Cuántos intentos necesitas para averiguarlo? Intento número 1 : 256 No, 256 es menor que el número que he pensado. Intento número 2 : 384 No, 384 es menor que el número que he pensado. Intento número 3 : 448 No, 448 es menor que el número que he pensado. Intento número 4 : 480 No, 480 es mayor que el número que he pensado. Intento número 5 : 464 No, 464 es menor que el número que he pensado. Intento número 6 : 472 Enhorabuena! Has necesitado 6 intentos. Terminación normal del programa. COMENTARIOS Obsérvese la simplificación con respecto al programa anterior. Sería sencillo volver a introducir el límite de intentos. Con todo, la estructura de comprobación anterior while() no es especialmente adecuada para un juego, en el cual comprobación de corrección deberá hacerse después de haber pedido un valor. Utilizaremos, por tanto, una sentencia do-while(). */
/* Otra implementación de MASTERMIND. Este ejercicio muestra la utilización de sentencias do-while(). */ #include<stdio.h> #include<time.h> #include<math.h> #define MAX_ADMISIBLE 4096 void main(void) { int maximo, numero_pregunta; int numero_buscado, numero_dado, max_preguntas; printf("M A S T E R M I N D\n\n"); do { printf("Indique el alcance máximo (1 < alcance <= %d) : ", MAX_ADMISIBLE); scanf("%d", &maximo); } while (maximo < 1 || maximo > MAX_ADMISIBLE); numero_buscado = clock() % maximo; max_preguntas = (int)(ceil(log(maximo)/log(2))); printf("\nHe pensado un numero entre 1 y %d.¿Sabrás cual es en %d intentos?\n\n", maximo,max_preguntas); numero_pregunta=1; do { printf("Intento número %d : ",numero_pregunta); scanf("%d",&numero_dado); // Si el pringaíllo lo ha encontrado, salimos del bucle! if (numero_dado == numero_buscado) break; // En caso contrario, damos la pista correspondiente y seguimos if (numero_dado < numero_buscado) printf("\nNo, %d es menor que el número que he pensado.\n", numero_dado); else printf("\nNo, %d es mayor que el número que he pensado.\n", numero_dado); numero_pregunta ++; } while (numero_pregunta<max_preguntas); if (numero_dado != numero_buscado) printf("\n\nJa! Había pensado el %d\n\n", numero_buscado); else { printf("\n\nEnhorabuena! Era el %d!\n\n>Fin<\n\n",numero_buscado); printf("Has necesitado %d intentos.\n", numero_pregunta); } printf("\nTerminación normal del programa.\n"); } /* RESULTADO M A S T E R M I N D Indique el alcance máximo (1 < alcance <= 4096) : 4096 He pensado un numero entre 1 y 4096.¿Sabrás cual es en 12 intentos? Intento número 1 : 2048 No, 2048 es mayor que el número que he pensado. Intento número 2 : 1024 No, 1024 es menor que el número que he pensado. Intento número 3 : 1536 No, 1536 es menor que el número que he pensado. Intento número 4 : 1768 No, 1768 es menor que el número que he pensado. Intento número 5 : 1920 No, 1920 es mayor que el número que he pensado. Intento número 6 : 1856 No, 1856 es menor que el número que he pensado. Intento número 7 : 1888 No, 1888 es mayor que el número que he pensado. Intento número 8 : 1876 No, 1876 es mayor que el número que he pensado. Intento número 9 : 1866 No, 1866 es menor que el número que he pensado. Intento número 10 : 1871 No, 1871 es menor que el número que he pensado. Intento número 11 : 1874 Enhorabuena! Era el 1874! >Fin< COMENTARIOS Recuérdese que hay que respetar las convenciones del código fuente en lo tocante a sangrados, espacios etc. ¿Sería tan comprensible el código si estuviera alineado a la izquierda, sin sangrados? El operador || (q. v.) denota la disyunción lógica, OR. */