Estructuras de control

if, else, while, do-while, for...

Estructuras de control


if, else, while, do-while, for...

« Volver al inicio

Operaciones relacionales

Hemos visto ya que en C#, al igual que en muchos lenguajes de programación, se puede trabajar con operadores matemáticos. Ahora toca ver otros tipos de operadores diferentes que no realizan operaciones aritméticas. Esto es importante conocerlo antes de empezar a aprender las instrucciones más básicas de control que existen en C#.

También recordarás haber visto en el colegio que cuando un número es mayor que otro, utilizamos el símbolo >, o bien el símbolo < si el miembro de la izquierda es menor que el de la derecha.

1 < 2
6 > 3
203 < 406
110 = 110

En programación estos símbolos se conocen como operadores relacionales y es muy importante tenerlos en cuenta, sobre todo a la hora de evaluar condiciones en las instrucciones de control que veremos más adelante.

Estos son los operadores relacionales que soporta C#:

OperadorOperación
<Menor que
>Mayor que
<=Menor o igual que
>=Mayor o igual que
==Igual a
!=No es igual a

A la hora de realizar una operación relacional, esta siempre nos devolverá un valor lógico: verdadero o falso. En C# esto se traduce a true si es cierto o false si es falso.

Vamos a ver unos cuantos ejemplos:

OperaciónResultado
1 < 2true
3 > 0true
4 >= 2true
8 <= 2false
5 >= 5true
8 < 2false
10 == 10true
7 != 7false
3 != 2true

El resultado se devuelve en un tipo de datos que no hemos visto aún que se llama bool, donde sólo hay dos valores posibles: verdadero o falso.

Es importante no confundir el operador relacional de doble igual (==) con el símbolo de asignación (=). Si nos confundimos, el programa nos puede dar error u otros resultados no esperados.

int numero;

numero == 1; // Dará error aquí, porque estamos comparando
             // una variable sin asignar con un número.

El uso correcto sería:

int numero;

numero = 1;

Asimismo, si nos confundimos de símbolo en un if:

int numero = 1;

if(numero = 1) // Nos puede dar error aquí, porque en lugar de comparar,
               // estamos asignando a numero un valor.
  System.Console.WriteLine("El número es uno.");

Operaciones lógicas

Hemos visto los operadores aritméticos, los operadores relacionales, y ahora nos queda conocer los operadores lógicos. Los operadores lógicos sirven para juntar varias condiciones a la vez. Estas se pueden juntar de varias maneras, en función de lo que necesitemos programar.

Como se trata de algo que no se da antes de los ciclos de grado superior (quizá sí en grado medio), vamos a entender primero cómo funcionan los operadores lógicos más básicos. De hecho, aparte de los que se verán aquí, hay más, pero de momento no las hemos visto en clase, por lo que no voy a anotarlas por aquí todavía para no liar la perdiz.

AND (&&)

Por ejemplo, imaginémonos que queremos ir al cine, pero para eso necesitamos haber comprado la entrada y no tiene que llover. Es decir, se tiene que cumplir que haga sol y que tenga la entrada si queremos ir al cine. Si no se cumple cualquiera de esas dos condiciones, no podremos ir al cine (con posibilidad de devolver la entrada).

Condición 1Condición 2Resultado
Tengo la entradaHace solVoy al cine
No tengo la entradaHace solNo voy al cine
Tengo la entradaNo hace solNo voy al cine
No tengo la entradaNo hace solNo voy al cine

 

Si esto lo traducimos a variables y operadores lógicos de C#:

Condición 1Condición 2Voy al cine?
!entrada!hace_solfalse
!entradahace_solfalse
entrada!hace_solfalse
entradahace_soltrue

 

Aquí estamos aplicando una operación lógica llamada AND, que se traduce como Y, y en C# se representa con && (doble ampersand). Para que sea cierta una premisa con el operador &&, ambas condiciones tienen que ser ciertas y ninguna puede quedar como falsa.

Vamos a traducir el caso anterior en lo que se llama tabla de verdad:

aba && b
falsefalsefalse
falsetruefalse
truefalsefalse
truetruetrue

 

OR (||)

Vamos a ver otro caso. Al final vamos al cine, pero resulta que existe una promoción en el que te pueden hacer descuento si tienes hasta 25 años o si eres estudiante. Puede cumplirse cualquiera de las dos condiciones para que se te aplique el descuento, pero no si eres mayor de 25 y además no eres estudiante.

Condición 1Condición 2Resultado
No tengo <= 25 añosNo soy estudianteNo tengo descuento
No tengo <= 25 añosSoy estudianteTengo descuento
Tengo <= 25 añosNo soy estudianteTengo descuento
Tengo <= 25 añosSoy estudianteTengo descuento

 

Condición 1Condición 2Voy al cine?
!hasta_25!estudiantefalse
!hasta_25estudiantetrue
hasta_25estudiantetrue
hasta_25estudiantetrue

 

Aquí estamos aplicando una operación lógica llamada OR, que se traduce como O, y en C# se representa con || (doble tubería). Para que sea cierta una premisa con dicho operador, se tiene que cumplir al menos una de las condiciones. Sólo si ambas no son ciertas, el resultado será falso.

aba || b
falsefalsefalse
falsetruetrue
truefalsetrue
truetruetrue

 

NOT (!)

Habréis observado que estamos usando la exclamación (!) para marcar las condiciones negativas. En C# resulta que ! es un operador lógico de negación (NOT) y ya la hemos observado en el apartado anterior con el operador relacional !=, que es equivalente a negar el operador ==:

a != b

// Es igual a:

!(a == b)

Sin embargo, para estos casos es preferible emplear la primera forma a != b siempre que sea posible para facilitar la legibilidad y para gastar menos caracteres.

La tabla de verdad del operador ! sería:

a!a
falsetrue
truefalse

 

También podemos negar dos, tres o infinitas veces una variable o condición.

a!a!!a!!!a
falsetruefalsetrue
truefalsetruefalse
!a

// Es igual a:
!!!a               //3 exclamaciones

// O igual a:
!!!!!!!!!!!!!!!!!a //17 exclamaciones

Es algo que en la práctica se tiene que evitar, pero sin embargo tenemos que tener en cuenta a la hora de solucionar problemas. Al final cuando una variable true se niega un número par de veces, siempre resulta true, mientras que un número impar de ! equivale a negarlo una sola vez.

Condicionales

Vistos ya los operadores relacionales y los operadores lógicos fundamentales, estamos ya listos para empezar a trabajar con estructuras de control. En esta sección en particular le daremos una vuelta a las instrucciones condicionales if y switch.

if

Se traduce como “si” (sin acento, condicional, no “sí” de afirmación). Tiene la siguiente estructura:

if(condición) {
	código;
}

O bien así, aunque es menos recomendable:

if(condición)
	código;  // Podemos prescindir de llaves si nuestro
	         // código dentro del if sólo ocupará una línea.

Traducido a nuestro lenguaje, esto sería:

//Empiezo aquí
si(se cumple esta condición) {
	ejecuto
	estas
	líneas
	de código
}
//Si no se cumple, continúo aquí

Podemos añadir un “anti-if”, es decir, un bloque de código que se ejecute sólo si no se cumple lo que había en el if, y esto se hace con else.

if(condición) {
	código si condición es verdadero;
}
else {
	código si condición es negativa;
}

… que traducido en nuestro lenguaje, sería algo así:

si(se cumple esta condición) {
	ejecuto
	estas
	líneas
	de código
}
si no {
	ejecuto
	estas
	líneas
	de aquí
	en su lugar
}

Además, podemos encadenar varios if usando else if de la siguiente forma:

if(condición1) {
	código;
}
else if(condición2) {
	otro código;
}
else if(condición3) {
	otro código;
}
else {
	código si ninguno se cumple ninguna de las anteriores;
}

Podemos entender mejor cómo funciona if e if-else si emulamos el comportamiento interno del programa marcando qué hace el programa paso por paso: Simulación de if-else Si nos fijamos bien, no entramos en ningún sub-bloque de if hasta llegar al else if de la línea 14, ya que es el único donde se cumple la condición. Así que, la salida por consola de ese programa será: Tres.

switch

El código del gif anterior se podría reescribir perfectamente con switch:

using System;

class a {
	static void Main() {
		
		int num = 3;
		
		switch(num) {		
		case 1:
			Console.WriteLine("Uno");
			break;
		case 2:
			Console.WriteLine("Dos");
			break;
		case 3:
			Console.WriteLine("Tres");
			break;
		}
		//Fin del programa
	}
}

La estructura básica de un switch sería:

switch(variable) {
	case valor:
		código;
		break;
	case otro_valor:
		otro_código;
		break;
	default:	// equivale a else
		otro_código;
		break;
}

Y en nuestro idioma:

//Empiezo aquí
dada(esta_variable) {
	en caso de que valga X:
		ejecutar este código;
		interrumpir;
	en caso de que valga Y:
		ejecutar este otro código;
		interrumpir;
	si no se da ningún caso:
		finalmente ejecutar este código;
		interrumpir;
}
//Al final de switch o a la orden de interrumpir, continúo por aquí

Lo que hace break, que hemos traducido como interrumpir, es salirse de todo el bloque switch cuando hayamos ejecutado el código perteneciente a cada caso. Si no colocamos el break, el programa seguirá leyendo las instrucciones del siguiente case hasta llegar al siguiente break o hasta que se llegue al final del bloque switch.

Vamos a ver cómo se comporta un switch de forma más gráfica con el mismo ejemplo de antes (ignorad la mala indentación del código): Simulación de switch

Aquí nos encontramos con que switch seleccionará automáticamente el primer caso que tenga el mismo valor que tiene la variable dentro de los paréntesis (variable num). Si añadimos una etiqueta default dentro del switch, actuará exactamente igual que un else a secas: se ejecutará en caso de que num no tenga ninguno de los demás valores. Como num vale 3, se ejecutará el bloque de código que hay dentro de case 3 y la orden break hará que salte hasta el final del bloque switch.

Bucles

¿Qué es un bucle? Vamos a recordar este gag chanante:

— Correcto, me llaman Bucle.
— ¿Y nos puede explicar por qué?
— Pronto se dará cuenta.
— ¿Me daré cuenta de que le llaman Bucle?
— Correcto, me llaman Bucle.
— ¿Y nos puede explicar por qué?
— Pronto se dará cuenta.

Bucle es, por ejemplo, ponerte tu playlist favorita de Spotify una y otra vez. Cada vez que se repita esa playlist entera, estás haciendo una iteración. Te la has puesto tantas veces en bucle, que cuando termina una canción, sabes cuál será la siguiente que viene a continuación.

Pero un bucle no tiene por qué ser algo que se repita de forma indefinida. También es un bucle querer ver un vídeo en YouTube, y que antes de ello te obligue a ver un anuncio. Y luego otro anuncio. Y después, un tercer anuncio, ya llevamos tres iteraciones. Pero ahora puedes salirte del bucle al pulsar “Saltar” para así por fin poder ver el vídeo que deseabas ver hace cinco minutos y poner fin a ese bucle de anuncios.

Con esto debe quedarnos claro que existen los bucles con infinitas iteraciones y los bucles con un número limitado de iteraciones. Los bucles van acompañadas de una condición lógica que confirme si se va a realizar la siguiente iteración o no. Si escribimos una condición lógica que siempre sea cierta, nos quedará un bucle indefinido.

En esta sección vamos a repasar los distintos bucles que existen, por si no te ha quedado claro con lo que se da en los apuntes.

while

La estructura básica de un while (mientras) es la siguiente:

while(condición) {
	sentencia1;
	sentencia2;
	sentencia3;
	...
	sentenciaN;
}

O bien la siguiente si queremos definirla en una línea (sin llaves):

while(condición)
	sentencia;

Hablando en cristiano:

//Empiezo aquí
mientras que se cumpla (esta condición) {
	repetiré este bloque de código;
}
// Si no se cumple, continúo aquí

Cuando se ejecute un bucle while, lo que hará será:

  1. Evaluar que la condición lógica sea correcta (el resultado sea true).
  2. Si lo primero se cumple, ejecutar cada una de las líneas dentro del bucle ordenadamente. Si no se cumple, saltar al paso 4.
  3. Repetir el paso 1.
  4. Fin del bucle.

Lo que queremos decir con el punto 1 y 2 es que la expresión lógica que escribas en condición se comparará con true (verdadero). Si tu expresión lógica es igual a true, el paso 2 hará que entremos en el bucle. Si en cambio la condición es falsa (false), el paso 2 hará que el programa se salte el código de todo el bloque del bucle y seguirá ejecutándose por debajo de ese bloque while.

Visto de una forma gráfica, así funciona internamente un bucle while: Simulación de while

Si la condición se evalúa siempre como verdadera y no se hace nada para gestionar su salida, estaremos creando un bucle infinito. Por ejemplo, si creamos un bucle while(true), internamente se evaluará como: mientras que (true) sea igual a true, repetir el código. Como no hay condición de salida y la condición es una constante, creamos un bucle indefinido.

while(true) {
	Console.WriteLine("Hola");
}

La salida por consola de este comando, por tanto, será:

Hola
Hola
Hola
Hola
Hola
Hola
Hola
Hola

… y así continuamente hasta que matemos el proceso o se apague el ordenador.

do-while

Un do-while (hacer-mientras) tiene esta estructura:

do {
	sentencia1;
	sentencia2;
	sentencia3;
	...
	sentenciaN;
}
while(condición);

Traducido a pseudocódigo:

hacer {
	este bloque de código;
}
y repetir mientras se cumpla (esta condición);
  1. Se ejecutará primero el código que hay en el bloque.
  2. Cuando finalice el bloque, se evaluará si se sigue cumpliendo la condición.
  3. Si se cumple la condición anterior (resulta true), vuelve al paso 1. Si no, se sale del bucle.

Si queremos visualizar los pasos de ejecución para ver cómo se comporta este bucle: Simulación de do-while

¿Observamos las diferencias entre while y do-while?

  • while evalúa primero la condición y luego ejecuta el bloque de código.
    • Esto significa que el bloque de código puede que no se llegue a ejecutar nunca (si no se cumple la condición).
  • do-while ejecuta primero el bloque de código y luego evalúa la condición.
    • Esto significa que el bloque de código se ejecutará al menos una vez, pues estamos indicando al compilador que nos ejecute primero el código, pase lo que pase.

El do-while nos puede servir por ejemplo para pedirle una contraseña a un usuario, puesto que primero queremos primero imprimir un texto que pida la contraseña al usuario y que a continuación la valide:

 1using System;
 2
 3class a {
 4  static void Main() {
 5    string  password, // Contraseña introducida
 6            passCorrecta = "déjame entrar"; // Contraseña correcta
 7		
 8    do {
 9      // Pregunta al menos una vez por la contraseña.
10      Console.Write("Introduce la contraseña: ");
11      password = Console.ReadLine();
12      
13      // Si la contraseña no es correcta, muestra error.
14      if(password != passCorrecta) {
15      Console.WriteLine("Acceso denegado");
16      }
17    }
18    // Si la contraseña NO es correcta, seguir preguntando
19    //(hasta que se introduzca la correcta).
20    while(password != passCorrecta); 
21    
22    // El programa seguirá por aquí si se ha introducido bien.
23    Console.Write("Acceso concedido");
24  }
25}

Salida:

Introduce la contraseña: 1234
Acceso denegado
Introduce la contraseña: qazwsx123
Acceso denegado
Introduce la contraseña: déjame entrar
Acceso concedido

Si esto lo transformamos a while, vamos a tener que hacer algunos cambios en el código anterior:

  • Tenemos que asignar la variable password antes del bucle porque si la dejamos sin asignar, a la hora de evaluarse al comienzo del bucle, el compilador nos devolverá error. Con dejarlo preasignado con una cadena vacía, bastaría.
 1using System;
 2
 3class a {
 4  static void Main() {
 5    string  password = "", // Contraseña introducida
 6    passCorrecta = "déjame entrar"; // Contraseña correcta
 7    
 8    // Primero evalúa si la contraseña es correcta, luego hace el código de dentro
 9    while (password != passCorrecta) {
10      Console.Write("Introduce la contraseña: ");
11      password = Console.ReadLine();
12      
13      if(password != passCorrecta) {
14        Console.WriteLine("Acceso denegado");
15      }
16    }
17    
18    Console.Write("Acceso concedido");
19  }
20}

for

Si queremos que una parte del programa se repita X veces, el bucle for será una buena herramienta para ello.

for tiene una estructura un poco más compleja que los anteriores tipos de bucle. A diferencia de while y do-while, for tiene tres campos. Se estructura así:

for(campo1; campo2; campo3) {
	código;
}
  • campo1 será un valor contador que se ejecutará una sola vez al principio del bucle.
  • campo2 será donde escribiremos qué condición queremos que se cumpla en cada iteración (lo mismo que en while).
  • campo3 será donde tendrá lugar un incremento del valor contador.
for(contador = n; condición; incremento) {
	sentencia1;
	sentencia2;
	sentencia3;
	...
	sentenciaN;
}

En pseudocódigo:

Partiendo de contador = n;
Mientras se cumpla la condición {
	ejecutar el bloque;
	
	...
} incrementando en cada iteración

Por ejemplo, si queremos hacer un bucle con contador para mostrar por pantalla los números del 1 al 5 en cada línea:

 1using System;
 2
 3class a {
 4	static void Main() {
 5		int contador;
 6
 7		for(contador = 1; contador <= 5; contador = contador + 1) {
 8			Console.WriteLine(contador);
 9		}
10		
11		//Fin del programa
12	}
13}

Nos devolverá esta salida:

1
2
3
4
5

Simulándolo gráficamente, se ejecutará el código así: Simulación de for

Tenemos que meternos en la cabeza que:

  1. Lo primero que se ejecutará será siempre el primer campo de contador, y sólo se ejecutará una vez.
  2. Lo siguiente que hará será comprobar que la condición especificada en el campo 2 se cumple.
  3. Ejecutar el código del for si el paso 2 es cierto, o bien continuar por debajo del bucle for si el paso 2 resulta falso.
  4. Al final de cada iteración, se ejecuta el campo 3 para incrementar el valor del contador y se vuelve al paso 2.

Al final, el bucle for es equivalente a un while, y de hecho el código anterior se puede reescribir de la siguiente forma:

 1using System;
 2
 3class a {
 4	static void Main() {
 5		int contador = 1;
 6
 7		while(contador <= 5) {
 8			Console.WriteLine(contador);
 9			
10			contador = contador + 1;
11		}
12		
13		//Fin del programa
14	}
15}

… pero nos ocuparía más líneas, porque tenemos que declarar e inicializar la variable contador fuera del bucle, y tenemos que hacer el incremento después de la última línea de código dentro del bucle.

Más cosas a tener en cuenta de los bucles for:

  1. En el campo de inicialización (el primero), podemos declarar y asignar la variable a la vez. Esto es útil si queremos usar una variable i que sólo tenga uso dentro del bucle for:
for(int i = 0; i <= 10; i = i + 1) {
	Console.WriteLine(i);
}

En esta situación, la variable i será exclusiva de ese bucle for y sólo podrá usarse dentro. De lo contrario, nos devolverá error de compilación:

for(int i = 0; i <= 10; i = i + 1) {
	Console.WriteLine(i);
}
i = 0; // Esto nos dará error porque i no existe fuera del for.

Si queremos usar i fuera, tendríamos que al menos declararlo fuera del for y dejar el primer campo del for únicamente para inicializarlo:

int i; // Declaramos fuera

// Inicializamos i a 0 cuando entremos en el for
for(i = 0; i <= 10; i = i + 1) {
	Console.WriteLine(i);
}

// Se sale del bucle con i == 11
i = 0; // Esto funcionará.
  1. En el campo de incremento, que es el tercero, en realidad podemos hacer que un valor sume, reste, se multiplique, se divida, o se pueda realizar cualquier operación sobre el contador. Por ejemplo, podemos mostrar los números pares del 2 al 10 de esta forma:
for(int i = 2; i <= 10; i = i + 2) {
	Console.WriteLine(i);
}

Por cierto, también tienes que saber ya que podemos abreviar el i = i + 1 como i++, así como también podemos abreviar el i = i - 1 con i--.

  1. Si no escribimos nada en el campo 1 ni 2, se convierte automáticamente en un bucle while:
int i = 1;
for(; i <= 10;) {
	Console.WriteLine(i);
	i++;
}

Equivale a:

int i = 1;
while(i <= 10) {
	Console.WriteLine(i);
	i++;
}

Bucles for anidados

A veces nos podemos encontrar con bucles anidados como este:

for (int i = 0; i < 5; i++) {
	for (int j = 0; j < 5; j++) {
		Console.WriteLine("{0} {1}", i, j);
	}
	Console.WriteLine();
}

Este código devolverá esta salida:

0 0
0 1
0 2
0 3
0 4

1 0
1 1
1 2
1 3
1 4

2 0
2 1
2 2
2 3
2 4

3 0
3 1
3 2
3 3
3 4

4 0
4 1
4 2
4 3
4 4

Aquí ya nos solemos hacer un lío, sobre todo a la hora de intentar seguir los pasos de ejecución, lo cual será imprescindible para solucionar problemas donde necesitemos usar un for dentro de otro. Vamos a simplificar un poco el código para leer mejor cómo se comporta un if dentro de otro, y en nuestro lenguaje:

Partiendo de i = 0, mientras i sea menor que 5:
   Partiendo de j = 0, mientras que j sea menor que 5:
      Imprimir por consola el valor de i y de j
   Incrementar j y fin del bucle
   Imprimir un salto de línea
Incrementar i y fin del bucle

Básicamente, tenemos un for bidimensional.

  1. Inicio del programa.
  2. Primero nos metemos en el bucle con contador i
  3. Ejecutamos todo el código que hay dentro del bucle del contador i
  4. Resulta que dentro de ese bloque de código hay otro bucle for con contador en j
  5. Ejecutamos todo el código que hay dentro del bucle del contador j
  6. Cuando finalicemos la iteración actual de j, incrementamos el valor de j y volvemos al paso 4 si se verifica que j < 5.
  7. Cuando j llegue a 5, salimos del bucle j y continuamos por debajo.
  8. Imprimimos una línea nueva.
  9. Cuando finalicemos la iteración actual de i, incrementamos el valor de i y volvemos al paso 2 si se verifica que i < 5.
  10. Cuando i llegue a 5, salimos del bucle i y continuamos por debajo.
  11. Fin del programa.

Si esto sigue siendo un lío, no te preocupes, que también me he tomado la molestia de hacer un gráfico de estos chulos para que lo visualices más claramente: Simulación de for anidado

La clave para entenderlo mejor es la siguiente:

  • Una iteración de i no finalizará hasta que finalice primero el bucle j que tiene dentro.

Es decir, por cada pasada que hagamos en i, hacemos cinco pasadas del bucle j (contando desde 0). Cuando finalice el bucle que está más adentro (j), continuará o finalizará el bucle inmediato que lo contenga (i).

Entendiendo esto, ya podemos hacer un cuadrado con asteriscos cambiando tan sólo una línea del código anterior:

for (int i = 0; i < 5; i++) {
	for (int j = 0; j < 5; j++) {
		Console.Write("*"); // Cambiamos las coordenadas por un asterisco
                            // y hacemos que imprima sin saltar de línea
	}
	Console.WriteLine();
}

Se ejecutará así (pero mucho más rápido): Simulación de ejecución

foreach

Sabemos que el string es un conjunto de caracteres (varios char seguidos en una misma variable):

char letra1 = 'H',
     letra2 = 'o',
     letra3 = 'l',
     letra4 = 'a';
     
string frase = letra1.ToString()
             + letra2.ToString()
             + letra3.ToString()
             + letra4.ToString();
             
Console.WriteLine(frase);

Este código devolverá por consola: Hola porque hemos concatenado cada uno de los chars en un solo string.

Sabiendo esto, sabremos que la función foreach lo que hará es recorrer cada uno de los elementos del string, carácter por carácter, y guardarlo en una variable auxiliar. Por ejemplo:

string frase = "Hola";

foreach(char letra in frase) {
	Console.WriteLine(letra);
}

Traducido a nuestro lenguaje, esto es:

Inicializamos la variable frase: "Hola";

Para cada (carácter en la frase) {
	Imprimimos por pantalla una línea con cada letra;
}

Lo que hacemos cuando entremos en esa estructura foreach básicamente es, paso por paso:

  1. Declarar una variable letra de tipo char, que se usará como una variable auxiliar.
  2. Almacenar en esa variable auxiliar la letra que esté en la posición de frase correspondiente a la iteración actual. Tenemos que tener en cuenta de que los caracteres de este string se cuentan así, elemento por elemento:
    0123
    Hola

  3. Por cada letra de frase, imprimir una línea por pantalla.

La salida por consola será:

H
o
l
a

También podemos tener exactamente la misma salida con un bucle for, pero cambiando algunas cosas:

using System;

class a {
	static void Main() {
		string frase = "Hola";

		for(int i = 0; i < frase.Length; i++) {
			Console.WriteLine(frase[i]);
		}
	}
}

… pero esto sería adelantarnos un poco de temario, porque se supone que aún no hemos dado cómo acceder a un elemento de una variable. Más adelante lo veremos, igual que veremos más usos de foreach.

break en los bucles

El break dentro de los bucles (for, while, do-while, foreach…) es una instrucción para ordenar salir del bucle en el que se encuentre. Mientras que con el break que hemos visto en el switch interrumpimos la instrucción switch en la que nos encontremos, el break lo hace en un bucle sin repetir el resto de iteraciones.

Por ejemplo, tenemos este código:

using System;

class a {
	static void Main() {
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				if(j == 2) {
					break;
				}
				Console.Write("{0}", j);
			}
			Console.WriteLine();
		}
	}
}

La salida por consola será:

01
01
01

¿Por qué ocurre esto? Porque break se sale del bucle j y únicamente de ese bucle en el momento en el que esta variable vale 2. Luego el bucle i sigue su curso porque no hemos colocado ningún break en él.

Vamos a verlo paso por paso.

Demostración de break en un bucle anidado

Lo que nos tiene que quedar claro aquí es que break sólo se saldrá del bucle en el que se encuentre, aunque esté metido en un if, y no afectará a otros bucles exteriores.

Ahora bien, es muy importante saber también que, si el código anterior lo intentamos convertir a switch de la siguiente manera:

using System;

class a {
	static void Main() {
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				switch(j) {
					case 2:
						break;
				}
				Console.Write("{0}", j);
			}
			Console.WriteLine();
		}
	}
}

Obtendremos la salida:

012
012
012

¿Por qué sucede esto? Porque es importante saber que si colocamos un break dentro de un switch, aunque este switch esté contenido en un bucle, el break primero hará que nos salgamos solamente de la instrucción switch que lo contenga, por lo que switch no se puede utilizar en este contexto si queremos interrumpir el bucle j con break, y reitero que esto es importante tenerlo presente a la hora de depurar posibles errores en nuestro código en un futuro.

continue y diferencias con break

continue es otra herramienta que nos puede ser muy útil si lo sabemos utilizar correctamente. Por ahora, sólo tenemos que tener en cuenta la diferencia que hay con break en un bucle:

  • break fuerza la salida del bucle actual.
  • continue fuerza la salida de la iteración actual, y continúa a la siguiente iteración.

Por ejemplo, con este código:

using System;

class a {
	static void Main() {
		for(int i = 0; i < 5; i++) {
			for(int j = 0; j < 5; j++) {
				if(j == 2) {
					// Pasar a la siguiente cuando j valga 2
					continue;
				}
				Console.Write("{0}", j);
			}
			Console.WriteLine();
		}
	}
}

Obtendremos la salida:

0134
0134
0134
0134
0134

… porque estamos interrumpiendo la iteración en el momento que entramos en el if cuando j vale 2, y estamos forzando a continuar en la siguiente iteración, cuando j vale 3, hasta el final del bucle.

comments powered by Disqus