C Language
Iteraciones / bucles de repetición: for, while, do-while
Buscar..
Sintaxis
- /* Todas las versiones */
- para ([expresión]; [expresión]; [expresión]) una declaración
- para ([expresión]; [expresión]; [expresión]) {cero o varias declaraciones}
- while (expresión) one_statement
- while (expresión) {cero o varias declaraciones}
- do one_statement while (expresión);
- hacer {una o más declaraciones} while (expresión);
- // desde C99 además del formulario anterior
- para (declaración; [expresión]; [expresión]) one_statement;
- para (declaración; [expresión]; [expresión]) {cero o varias declaraciones}
Observaciones
Iteración Declaración / Loops se dividen en dos categorías:
- instrucción de iteración controlada / bucles
- iteración controlada por el pie / bucles
Declaración de iteración controlada por la cabeza / Bucles
for ([<expression>]; [<expression>]; [<expression>]) <statement>
while (<expression>) <statement>
for ([declaration expression]; [expression] [; [expression]]) statement
Declaración de iteración controlada por el pie / bucles
do <statement> while (<expression>);
En bucle
Para ejecutar un bloque de código a lo largo de una vez más, los bucles entran en la imagen. El bucle for
se utiliza cuando un bloque de código se ejecuta un número fijo de veces. Por ejemplo, para llenar una matriz de tamaño n
con las entradas del usuario, necesitamos ejecutar scanf()
por n
veces.
#include <stddef.h> // for size_t
int array[10]; // array of 10 int
for (size_t i = 0; i < 10; i++) // i starts at 0 and finishes with 9
{
scanf("%d", &array[i]);
}
De esta manera, la llamada a la función scanf()
se ejecuta n
veces (10 veces en nuestro ejemplo), pero se escribe solo una vez.
Aquí, la variable i
es el índice de bucle, y se declara mejor tal como se presenta. El tipo size_t
( tamaño ) debe usarse para todo lo que cuenta o recorre los objetos de datos.
Esta forma de declarar variables dentro de for
solo está disponible para compiladores que se han actualizado al estándar C99. Si, por algún motivo, aún está atascado con un compilador anterior, puede declarar el índice de bucle antes del bucle for
:
#include <stddef.h> /* for size_t */
size_t i;
int array[10]; /* array of 10 int */
for (i = 0; i < 10; i++) /* i starts at 0 and finishes at 9 */
{
scanf("%d", &array[i]);
}
Mientras bucle
A while
bucle se utiliza para ejecutar una parte de código, mientras que una condición es verdadera. El while
de bucle se va a utilizar cuando un bloque de código se va a ejecutar un número variable de veces. Por ejemplo, el código que se muestra obtiene la entrada del usuario, siempre que el usuario inserte números que no sean 0
. Si el usuario inserta 0
, la condición while ya no es verdadera, por lo que la ejecución saldrá del bucle y continuará con cualquier código posterior:
int num = 1;
while (num != 0)
{
scanf("%d", &num);
}
Bucle Do-While
A diferencia de for
y while
bucles, do-while
bucles comprobar la verdad de la condición al final del bucle, lo que significa la do
bloque se ejecutará una vez, y a continuación, comprobar la condición de la while
en la parte inferior del bloque. Lo que significa que un bucle do-while
while siempre se ejecutará al menos una vez.
Por ejemplo, este bucle do-while
while obtendrá números del usuario, hasta que la suma de estos valores sea mayor o igual a 50
:
int num, sum;
num = sum = 0;
do
{
scanf("%d", &num);
sum += num;
} while (sum < 50);
do-while
bucles do-while
while son relativamente raros en la mayoría de los estilos de programación.
Estructura y flujo de control en un bucle for.
for ([declaration-or-expression]; [expression2]; [expression3])
{
/* body of the loop */
}
En un bucle for
, la condición de bucle tiene tres expresiones, todas opcionales.
- La primera expresión,
declaration-or-expression
, inicializa el bucle. Se ejecuta exactamente una vez al principio del bucle.
Puede ser una declaración e inicialización de una variable de bucle o una expresión general. Si es una declaración, el alcance de la variable declarada está restringido por la declaración for
.
Las versiones históricas de C solo permitían una expresión, aquí, y la declaración de una variable de bucle tenía que colocarse antes de la for
.
- La segunda expresión,
expression2
, es la condición de prueba . Primero se ejecuta después de la inicialización. Si la condición estrue
, entonces el control entra en el cuerpo del bucle. Si no, se desplaza al exterior del cuerpo del bucle al final del bucle. Posteriormente, esta condición se verifica después de cada ejecución del cuerpo, así como la instrucción de actualización. Cuando estrue
, el control vuelve al principio del cuerpo del bucle. La condición generalmente pretende ser una verificación del número de veces que se ejecuta el cuerpo del bucle. Esta es la forma principal de salir de un bucle, la otra forma es usar sentencias de salto . - La tercera expresión,
expression3
, es la instrucción de actualización . Se ejecuta después de cada ejecución del cuerpo del bucle. A menudo se usa para incrementar el número de veces que se ha ejecutado el bucle, y esta variable se denomina iterador .
Cada instancia de ejecución del cuerpo del bucle se llama una iteración .
Ejemplo:
for(int i = 0; i < 10 ; i++)
{
printf("%d", i);
}
La salida es:
0123456789
En el ejemplo anterior, primero se ejecuta i = 0
, inicializando i
. Luego, se comprueba la condición i < 10
, que se evalúa como true
. El control entra en el cuerpo del bucle y se imprime el valor de i
. Luego, el control cambia a i++
, actualizando el valor de i
de 0 a 1. Luego, la condición se verifica nuevamente y el proceso continúa. Esto continúa hasta que el valor de i
convierte en 10. Luego, la condición i < 10
evalúa como false
, después de lo cual el control sale del bucle.
Bucles infinitos
Se dice que un bucle es un bucle infinito si el control ingresa pero nunca abandona el cuerpo del bucle. Esto sucede cuando la condición de prueba del bucle nunca se evalúa como false
.
Ejemplo:
for (int i = 0; i >= 0; )
{
/* body of the loop where i is not changed*/
}
En el ejemplo anterior, la variable i
, el iterador, se inicializa a 0. La condición de prueba es inicialmente true
. Sin embargo, i
no se modifica en cualquier parte del cuerpo y la expresión de actualización está vacía. Por lo tanto, i
seguiré siendo 0, y la condición de prueba nunca será evaluada como false
, lo que lleva a un bucle infinito.
Suponiendo que no hay declaraciones de salto, otra forma en que se podría formar un bucle infinito es manteniendo explícitamente la condición verdadera:
while (true)
{
/* body of the loop */
}
En un bucle for
, la declaración de condición opcional. En este caso, la condición siempre se true
vacía, lo que lleva a un bucle infinito.
for (;;)
{
/* body of the loop */
}
Sin embargo, en ciertos casos, la condición podría mantenerse true
intencionalmente, con la intención de salir del bucle utilizando una instrucción de salto como break
.
while (true)
{
/* statements */
if (condition)
{
/* more statements */
break;
}
}
Loop desenrollado y dispositivo de Duff
A veces, el bucle directo no puede estar completamente contenido dentro del cuerpo del bucle. Esto se debe a que el bucle debe estar cebado por algunas instrucciones B. Luego, la iteración comienza con algunas declaraciones A , que luego son seguidas por B nuevamente antes de hacer un bucle.
do_B();
while (condition) {
do_A();
do_B();
}
Para evitar posibles problemas de cortar / pegar con la repetición de B dos veces en el código, dispositivo de Duff podría ser aplicada para iniciar el bucle desde el medio del while
del cuerpo, utilizando una sentencia switch y caer a través del comportamiento.
switch (true) while (condition) {
case false: do_A(); /* FALL THROUGH */
default: do_B(); /* FALL THROUGH */
}
El dispositivo de Duff fue realmente inventado para implementar el desenrollado de bucles. Imagínese aplicando una máscara a un bloque de memoria, donde n
es un tipo integral con signo con un valor positivo.
do {
*ptr++ ^= mask;
} while (--n > 0);
Si n
siempre fuera divisible por 4, podría desenrollar esto fácilmente como:
do {
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
*ptr++ ^= mask;
} while ((n -= 4) > 0);
Pero, con el Dispositivo de Duff, el código puede seguir este lenguaje desenrollado que salta al lugar correcto en el medio del bucle si n
no es divisible por 4.
switch (n % 4) do {
case 0: *ptr++ ^= mask; /* FALL THROUGH */
case 3: *ptr++ ^= mask; /* FALL THROUGH */
case 2: *ptr++ ^= mask; /* FALL THROUGH */
case 1: *ptr++ ^= mask; /* FALL THROUGH */
} while ((n -= 4) > 0);
Este tipo de desenrollado manual rara vez se requiere con compiladores modernos, ya que el motor de optimización del compilador puede desenrollar bucles en nombre del programador.