Con la tecnología de Blogger.
RSS

Estructuras de control

Hay dos maneras de cambiar el rumbo de ejecución de un programa, estos pueden ser saltos incondicionales y saltos condicionales. En este capítulo se describen algunas de estas sentencias. Algunas son muy similares a las existentes en otros lenguajes, como las sentencias if, for, while, etc. y otras, como foreach, throw o continue, son algo más específicas.

Saltos incondicionales

Las instrucciones de un programa se ejecutan sentencia por sentencia empezando desde el método o función principal llamado Main() hasta terminar con el programa. El programa sin embargo, tomará otros rumbos incondicionalmente en dos oportunidades: 1. Cuando encuentre la llamada a otros métodos (Ejemplo 4.1) y 2. Con el uso de las palabras claves como goto, break, continue, return y throw las cuales se discutirán más adelante.

Saltos condicionales

Los saltos condicionales sirven para ejecutar cierto código solamente si se cumple con alguna condición. Entre otros tenemos:

Instrucción if

Esta sentencia sirve para ejecutar unas instrucciones en caso de que se cumpla determinada condición. La forma completa de la instrucción if es
 if( condición ) {
   instrucciones; 
   ...
 }
 else {
   instrucciones;
   ...
 }
donde la cláusula else es opcional. Si la condición es verdadera, se ejecutarán las instrucciones dentro del bloque if, mientras que si es falsa, se ejecutará el bloque else. El valor que controla la sentencia if debe ser de tipo bool.

Instrucción switch

La instrucción switch es muy parecida a la estructura if-else-if, sólo que permite seleccionar entre varias alternativas de una manera más cómoda. Funciona de la siguiente manera: el valor de una expresión se prueba sucesivamente con una lista de constantes. Cuando se encuentra una coincidencia, se ejecuta la secuencia de instrucciones asociada con esa coincidencia. La forma general de la instrucción switch es la siguiente:
        switch( expresión ){
            case constante1:
                instrucciones;
                break;
            case constante2:
                instrucciones;
                break;
            ...
            default:
                instrucciones;
                break;
        }
La sentencia default se ejecutará sólo si ninguna constante de las que siguen a case coincide con expresión. Es algo similar al else final de la instrucción if-else-if.
Sin más, vamos a por un ejemplo
    using System;
 
    class InstruccionSwitch{
        public static void Main()
        {
            string s;
 
            Console.WriteLine( "Elige hacer algo con los números 2 y 3");
            Console.WriteLine( "    + para sumarlos" );
            Console.WriteLine( "    - para restarlos" );
            Console.WriteLine( "    * para multiplicarlos" );
            Console.WriteLine( "    / para dividirlos (division entera)" );
 
            s = Console.ReadLine();
 
            switch(s){
                case "+":
                    Console.WriteLine("El resultado es {0}", 2+3);
                    break;
                case "-":
                    Console.WriteLine("El resultado es {0}", 2-3);
                    break;
                case "*":
                    Console.WriteLine("El resultado es {0}", 2*3);
                    break;
                case "/":
                    Console.WriteLine("El resultado es {0}", 2/3);
                    break;
                default:
                    Console.WriteLine("No te entiendo");
                    break;
            }
        }
    }
El cual solicita al usuario que inserte uno de los símbolos +-*/ , y con un switch compara los resultados para hacer diferentes acciones dependiendo del valor de s, que es la cadena de caracteres que almacena la elección del usuario. El resultado debería ser algo parecido a esto:
Elige hacer algo con los números 2 y 3
    + para sumarlos
    - para restarlos
    * para multiplicarlos
    / para dividirlos (division entera)
*
El resultado es 6
Como habrá notado, al final de todo case siempre hay una sentencia break. Esto no es obligatorio, puede haber en su lugar otra sentencia de salto como un goto inclusive en el caso default.
Siempre se deberá tener un break o un goto en cada caso a menos que la sentencia esté vacía. En esta situación se ejecutará el siguiente caso que viene en la lista. Si no se toma en cuenta ésto se obtiene un error en tiempo de compilación. Otros lenguajes, como C/C++ o Java no tienen esta restricción. La razón de adoptarla en C# es doble: por un lado, elimina muchos errores comunes y en segundo lugar permite al compilador reorganizar las sentencias de los case, y así permitir su optimización.
Ejemplo:
    using System;
  
    class InstruccionSwitch{
        public static void Main()
        {
            int voto;
            Console.WriteLine( "Qué tipo de musica te gusta más");
            Console.WriteLine( "1 - Rock" );
            Console.WriteLine( "2 - Clásica  (clasica cuenta como instrumental)" );
            Console.WriteLine( "3 - Instrumental" );
            Console.WriteLine( "4 - Alternativa (alternativo cuenta como Rock)" );
  
            voto = Int32.Parse(Console.ReadLine());
  
            switch(voto){
                case 1:
                    Console.WriteLine("Has votado por Rock o Alternativo");
                    break;
                case 2: //Debido a que no tiene ni un goto ni break y está vacía va al siguiente caso 
                case 3:
                    Console.WriteLine("Has votado por Clásica o Instrumental");
                    break;
                case 4:
                    goto case 1;
                default:
                    Console.WriteLine("No te entiendo");
                    break;
            }
        }
    }
Como bien se puede notar en el ejemplo, en el case 4, se utiliza la instrucción goto, indicando que se vaya al case 1, ya que según la lógica del ejemplo, es igual elegir 1 o 4. Nótese que no es necesario usar break; en el case 4 ya que se utilizó goto.

Bucle for

El bucle for de C# es idéntico al encontrado en los lenguajes C/C++ y Java. El formato general es
        for( inicialización; condición; iteración )
        {
            instrucciones;
        }
Las sentencias de inicialización se ejecutan una vez al principio y sirven principalmente para asignar valores a las variables que servirán de contador. Las sentencias de condición, por su parte, se ejecutan cada vez que el bucle vuelve al principio y sirven para controlar el bucle: éste seguirá realizándose siempre y cuando estas condiciones sean true. Las sentencias de iteración se ejecutan también cada vez que se realiza una nuevo ciclo en el bucle, y sirven para cambiar el estado de las variables que gobiernan las sentencias de condición. Pero todo esto se entiende mejor con un ejemplo
    using System;
 
    class BucleFor{
        public static void Main()
        {
            int i;  //el contador
 
            for( i = 0; i < 10; i++)
            {
                Console.WriteLine( i );
            }
        }
    }
Este ejemplo imprime por pantalla los 10 primero enteros positivos. Es un caso muy simple del bucle for. Por cierto, el operador ++ lo que hace es que añade una unidad a la variable a la que acompaña, de forma que, por ejemplo, 9++ es 10. De esta forma, la variable i se incrementa a cada vuelta.
En el ejemplo anterior, las sentencias de inicialización y de iteración eran únicas, pero esto no tiene por qué ser así, de hecho se pueden utilizar varias sentencias separadas por comas. Por ejemplo, se pueden usar dos variables para controlar el bucle
   using System;
   
   class BucleFor2{
       public static void Main()
       {
            int i;
            int j;
 
            for( i=0, j=10; i<j; i++, j--)
            {
                Console.WriteLine("( {0} , {1} )", i, j);
            }
       }
   }            
Por su parte, la expresión condicional del bucle for puede ser cualquier expresión que genere un valor booleano. En este caso se ha usado "i<j", pero también hubiera sido válida "i==5", "true" (el bucle se realizará indefinidamente) o "false" (el bucle no se realizará).

Bucle while

El bucle while es un bucle que se realiza mientras se cumpla determinada condición. Tiene la forma
            while( condición )
            {
                instrucciones;
            }
Donde la condición tiene que ser un valor booleano. Tiene una estructura muy sencilla, así que vamos a ver directamente un ejemplo.
    using System;
 
    class BucleWhile{
        public static void Main()
        {
            int i = 0;
            while( i<10)
            {
                Console.WriteLine( i );
                i = i+1;
            }
        }
    }
En el que se realiza lo mismo que en el ejemplo anterior, sólo que ahora con un bucle while.

Bucle do-while

Se trata de una ligera variante del bucle anterior, con la diferencia de que ahora primero se ejecutan las instrucciones y luego se evalúa la condición, de forma que tiene tiene una estructura:
            do{
                instrucciones;
            }
            while( condición );
El siguiente ejemplo
    
    using System;
 
    class BucleDoWhile{
        public static void Main()
        {
            string s = "";
 
            do
            {
                Console.WriteLine( "Introduce si para salir del bucle" );
                s = Console.ReadLine();
            }
            while( s != "si" );
        }
    }            
muestra un programa que ejecuta un bucle hasta que el usuario introduce "si". Por cierto, != es lo contrario de ==, es decir, != devuelve true cuando los valores comparados son distintos.

Bucle foreach

El bucle foreach se utiliza para hacer iteraciones sobre elementos de una colección, como pueden ser los enteros dentro de un arreglo de enteros. La sintaxis sigue la siguiente estructura:

           foreach( tipo in coleccion )
           {
                instrucciones;
           }
Como hemos comentado, el uso más inmediato es iterar sobre un arreglo de números:
    using System;
 
    class BucleForeach{
        public static void Main()
        {
            int[,] arr =  {{1,2},{2,3}};
 
            foreach( int elem in arr )
            {
                Console.WriteLine( elem );
            }
        }
    }
Este ejemplo sólo imprime los valores de una matriz, pero como se puede comprobar mejora mucho la claridad del código comparándolo con una implementación con bucles for como esta
    using System;
 
    class BucleForeach{
        public static void Main()
        {
            int i, j;   //seran los indexadores de la matriz
            
            int[,] arr =  {{1,2},{2,3}};
 
            for(i = 0; i<2; i++ )
            {
                for( j = 0; j<2; j++ )
                {
                    Console.WriteLine( arr[i,j] );
                }
            }
        }
    }
Además, es posible utilizar el bucle foreach con cualquier tipo que sea una colección, no solo con arreglos, como veremos más adelante.

Usando continue y break

continue y break son dos palabras clave que nos permiten saltar incondicionalmente al inicio de un bucle (continue) o fuera de un bucle (break) cuando se necesite. Por ejemplo:
 using System;
 
 class continueBreak
 {
    public static void Main()
    {
       for(int i = 0; i<10; i++ )
       {
          if (i==5)
             continue;
          if (i==9)
             break;
          Console.Write("{0},",i);
       }
    }
 }


  • Digg
  • Del.icio.us
  • StumbleUpon
  • Reddit
  • RSS

0 comentarios:

Publicar un comentario