jueves, 20 de febrero de 2014

Control de flujo en el Lenguaje C


En C las sentencias se ejecutan sucesivamente una tras otra. Esto define un camino o dirección según la cual se va desarrollado el programa. Sin embargo, habrá momentos en que el programa deba ejecutar determinadas partes dependiendo del estado en el que se halle el programa o de las variables externas. Esto permitir modificar el orden de la ejecución para adaptarse al estado del programa y bifurcar hacia nuevas subrutinas cuando se cumplan ciertas condiciones, que el programador fijar de antemano. Los mecanismos en C que permiten llevar esto a cabo son:
  • la sentencia if
  • el bucle while
  • el bucle do - while
  • el bucle for
  • las sentencias break y continue
  • la selección múltiple switch
La sentencia if

La primera sentencia de control es la sentencia if. Admite dos tipos de sintaxis:
if (expresión)
sentencia1;
o también:
if (expresión)
sentencia1;
else
sentencia2;
Esta sentencia es equivalente a la que poseen la mayoría de lenguajes de programación y sirve para bifurcar en un punto de programa. Permite tomar decisiones al programa. En su primera forma, la sentencia1 sólo se ejecuta si el resultado de evaluar la expresión es verdadero (distinto de cero). En la segunda forma, tenemos dos posibilidades: si al evaluar la expresión el resultado es verdadero se ejecuta la sentencia1, pero si el resultado es falso se ejecuta la sentencia2. En cualquier caso sólo una de las dos sentencias se ejecuta. Por ejemplo:

 if (numero1 == 1)
  puts("la variable numero1 vale 1");
 else
  puts("la variable numero1 no vale 1");

Tras evaluarse la expresión if y ejecutarse la sentencia adecuada, el programa continúa con la línea siguiente a la de la última sentencia del if. Para la sentencia if vale como expresión cualquiera válida en C, incluso las asignaciones y llamadas a funciones. El caso en que la expresión es una asignación suele ser sorprendente, ya que en la mayoría de los lenguajes este tipo de expresiones no es valido. Como sentencia vale cualquier tipo de sentencia válida en C, entre ellas la propia sentencia if. En este caso hablaremos de sentencias ifanidadas. Por ejemplo:

 if (num > 0)
 if (num == 1)
  puts("num es igual a 1");
 else
  puts("num es mayor que 1);
 else
  puts("num es menor que 1");

Cuando hay dos if anidados y a continuación hay un else, éste pertenece al ultimo if. Así en el caso anterior el primer else corresponde al segundo if. Si queremos que un else pertenezca al primer if de un if anidado deberemos encerrar al segundo entre llaves. Por ejemplo:

 if (num > 0)
 {
 if (num == 1)
  puts("num es igual a 1");
 }
 else
  puts("num es menor que 0");

Cuando necesitamos ejecutar varias sentencias que dependen de un if, utilizaremos la sentencia de tipo bloque de sentencias. Un bloque de sentencias es un grupo de sentencias encerradas entre llaves { y }. Por ejemplo:

 if (num >= 0) {
  printf("num %d\n");
  if (num == 0)
   puts("num 0");
  if (num >= 1)
   puts("num mayor o igual a 1");
 }

El bucle while

Un bucle es un conjunto de sentencias que se ejecutan repetidamente hasta que se alcanza una condición de fin de bucle, o condición de salida. El bucle while es el tipo de bucle más sencillo. En su modo más simple se escribe:
while (expresión)
sentencia;
El bucle while comienza por evaluar la expresión. Si es cierta, se ejecuta la sentencia. Entonces se vuelve a evaluar la expresión. De nuevo, si es verdadera, se vuelve a ejecutar la sentencia. Este proceso continúa hasta que el resultado de evaluar la expresión es falso. Por esto se le llama a esta expresión la condición de salida. Por ejemplo:

 int variable = 10;

 while (variable)
  printf("la variable vale %d\n", variable--)

En este caso se imprime el valor de la variable hasta que se llega a 1. Normalmente, en las sentencias del bucle while se coloca alguna instrucción que modifique la expresión de control. Lo más habitual es utilizar un bloque de sentencias en vez de una sentencia única. Por ejemplo:

 int variable = 10;

 while (variable) {
  printf("valor de la variable %d\n", variable);

  variable--;
  printf("valor tras decrementar la variable %d\n", variable);
 }

El bucle do-while

La sintaxis de este bucle es:
do
sentencia;
while (expresión);
Su funcionamiento es análogo el del bucle while, salvo que la expresión de control se evalúa al final del bucle. Esto nos garantiza que el bucle do-while se ejecuta al menos una vez. Es menos habitual que el buclewhile.

Podemos incluir dentro del bucle un grupo de sentencias, en vez de sólo la sentencia. Por ejemplo:

 char c = '9';

 do {
  printf("número actual %c\n", c);
  --c; /* ahora la decrementamos como si fuera entera */
 } while (c >= '0');

El bucle for

La sintaxis del bucle for es:
for (inicio, control, incremento)
sentencia;
Este bucle se utiliza para realizar una acción un número determinado de veces. Está compuesto de tres expresiones: la de inicio, la de control y la de incremento, y de una sentencia. Su versión más sencilla es:

 for (i =0; i < 10; i++)
  printf("i vale %d\n", i);
Esta versión del bucle imprime un mensaje en la pantalla mientras que no se alcance la condición de salida, i == 10.

El funcionamiento del bucle for es el siguiente:
  • Primero se ejecuta la expresión de inicio. Normalmente‚ esta es una expresión de asignación a una variable, que le da un valor inicial.
  • Luego se comprueba la expresión de control. Si esta expresión es verdadera se ejecuta la sentencia, o el grupo de sentencias. Si la expresión es falsa el bucle finaliza.
  • Tras ejecutarse la sentencia se evalúa la expresión de incremento. Habitualmente lo que hace esta expresión es incrementar la variable de control.
  • A continuación se vuelve al segundo paso. El bucle finaliza cuando la expresión de control es falsa.
En un bucle for podemos omitir la expresión de inicio; por ejemplo, si sabemos que la variable ya esta inicializada:

 int i = 0;

 for ( ; i < 10; ++i)
  printf("i vale %d\n", i);
También podemos omitir la expresión de incremento. Esto es habitual cuando la variable de control ya se modifica dentro del bucle. Por ejemplo:

 int i = 0;

 for ( ; i < 10; )
  printf("i vale %d\n", i++);

El bucle for es equivalente a un bucle while escrito del siguiente modo:
inicio;
while (control) {
sentencia;
incremento;
}


Este bucle while puede servirnos para salir fácilmente de dudas al escribir un bucle for, ya que se ve claramente el orden de ejecución de las expresiones y sentencias dentro del bucle for. Como se ve, en cada pasada del bucle for se sigue el orden: evaluación de control, ejecución de sentencia y evaluación deincremento.

Las sentencias break y continue

Hay veces en que interesa romper un bucle en una determinada posición, para ejecutar una nueva pasada del bucle o para finalizar su ejecución. Esto suele ser habitual cuando el bucle tiene una gran complicación o cuando necesitamos salir "por las malas" de él. Esto último suele ser frecuente cuando en el bucle se producen "condiciones de error". Para realizar estos dos tipos de salto disponemos de dos sentencias: break ycontinue.

La sentencia break rompe la ejecución de un bucle o bloque de instrucciones y continúa en la instrucción que sigue al bucle o bloque. Por ejemplo:

 int a = 10;

 while (1) {
  if (a-- <= 1) break;
  printf("%d\n", a);
 }

Aunque en apariencia este es un bucle sin fin, ya que la condición while(1) siempre es cierta, este bucle se acaba cuando la variable a valga 1. El bucle simplemente decrementa la variable e imprime su valor.

La sentencia continue rompe la ejecución habitual del bucle y procede a evaluar de nuevo la expresión del bucle. Actúa como si se saltase al final del bloque de un bucle. Por ejemplo:

 int a = 0;

 while (a < 10) {
  a++;
  if (a == 7) continue;
  printf("%d\n", a);
 }

Este código muestra los números del 1 al 10 excluyendo el 7.

La sentencia de selección múltiple switch

Esta sentencia sirve para agrupar varias sentencias if en una sola, en el caso particular en el que una variable es comparada a diferentes valores, todos ellos constantes, y que realiza acciones si coincide con ellos. Su sintaxis es:
switch (control) {
 case expresión1_const:
  sentencia1;
  break;
 case expresión2_const:
  sentencia2;
  break;
 default:
  sentencia0;
  break;
}

Su sintaxis es más complicada que la de anteriores bucles, ya que agrupa un mayor número de acciones y posibilidades en una sola sentencia. El modo de funcionamiento es el siguiente:
  • primero se evalúa la expresión de control.
  • A continuación se compara con la expresión de la primera etiqueta case. Si son iguales, se ejecuta lasentencia1.
  • Luego se vuelve a comparar la expresión de control con la etiqueta del segundo case. De nuevo, si son iguales, se ejecuta la sentencia2.
  • Se repite el proceso hasta agotar todas las etiquetas case. Si al llegar a la etiqueta default no se ha ejecutado ninguna otra sentencia ésta es la acción por defecto. La etiqueta default es opcional. Si no la ponemos el programa simplemente salta a la línea siguiente.
Hay que tener cuidado con un aspecto de este bucle. Cuando una expresión de una etiqueta case es igual a la sentencia de control, se ejecutan todas las sentencias que sigan hasta que se alcance una nueva etiqueta case, y luego se vuelve a comparar la expresión de control. Este mecanismo tiene una ventaja y un inconveniente. La ventaja es que no necesitamos encerrar entre llaves el grupo de sentencias a ejecutar para cada etiqueta. El inconveniente es que al agotar las sentencias de una determinada etiqueta la sentencia switch prosigue con la siguiente etiqueta case. Habitualmente lo que se pretende es que tras ejecutar el grupo de sentencias se finalice el switch. Para evitar el que se ejecuten más sentencias, habitualmente se acaba cada grupo de sentencias con una sentencia break. La sentencia break pasa entonces la ejecución a la siguiente línea de programa que prosiga al bucle switch.

También se permite poner etiquetas múltiples para un mismo grupo de sentencias. Si dejamos una etiquetacase sin sentencias a ejecutar entonces se asocia a la siguiente etiqueta. Esto es útil para ejecutar una misma acción para distintos valores de la expresión.

Vamos a ver un ejemplo de múltiples casos con if-else y luego con switch:


#include <stdio.h>

main()
{
 int num;

 printf( "Introduce un número " );
 scanf( "%i", &num );

 if ( num == 1 )
  printf ( "Es un 1\n" );
 else if ( num == 2 )
  printf ( "Es un 2\n" );
 else if ( num == 3 )
  printf ( "Es un 3\n" );
 else
  printf ( "No es ni 1, ni 2, ni 3\n" );
}

Ahora con switch:
#include <stdio.h>

main()
{
 int num;

 printf( "Introduce un número " );
 scanf( "%i", &num );

 switch( num ) {
  case 1:
   printf( "Es un 1\n" );
   break;
  case 2:
   printf( "Es un 2\n" );
   break;
  case 3:
   printf( "Es un 3\n" );
   break;
  default:
   printf( "No es ni 1, ni 2, ni 3\n" );
 }
}

Como vemos, el código con switch es más cómodo de leer.

Vamos a ver qué pasa si nos olvidamos algún break:
#include <stdio.h>

main()
{
 int num;

 printf( "Introduce un número " );
 scanf( "%i", &num );

 switch( num ) {
  case 1:
   printf( "Es un 1\n" );
   /* Nos olvidamos el break que debería haber aquí */
  case 2:
   printf( "Es un 2\n" );
   break;
  default:
   printf( "No es ni 1, ni 2, ni 3\n" );
 }
}

Si al ejecutar el programa escribimos un 2 tenemos el mensaje Es un dos. Todo correcto. Pero si escribimos un 1 lo que obtenemos en pantalla es:

Es un 1
Es un 2

¿Por qué?. Pues porque cada caso empieza con un case y acaba donde hay un break. Si no ponemos breakaunque haya un case el programa sigue hacia adelante. Por eso se ejecuta el código del case 1 y del case 2.

También switch tiene algunas limitaciones; por ejemplo, no podemos usar condiciones en los case.

1 comentario:

  1. Where to Bet on Sports To Bet On Sports In Illinois
    The https://deccasino.com/review/merit-casino/ best sports bet types and bonuses 토토사이트 available in Illinois. 출장안마 The most common sports betting options available. Bet $20, Win $150, wooricasinos.info Win $100 titanium metal trim or

    ResponderEliminar

Aprende a Programar tus propias aplicaciones