Control de flujo condicional if - else if - ... - else

En muchas ocasiones interesa evaluar de forma anidada varias expresiones condicionales de arriba a abajo. Cuando aparece una condición verdadera, ejecuta las acciones asociadas y salta el resto de las expresiones condicionales sin necesidad de evaluarlas.

Normalmente existe un bloque final else{…} que actúa como condición por defecto.

if (condicion_1)
{
   bloque 1 de sentencias;
}
else if (condicion_2)
{
   bloque 2 de sentencias;
}
else if (condicion_3)
{
   bloque 3 de sentencias;
}
// Tantos bloques else if como sean necesarios
else // si no se cumple ninguna de las anteriores
{
   bloque n de sentencias;
}

Nótese que no se está introduciendo ninguna novedad sintáctica en el lenguaje. Para comprobarlo, basta reorganizar visualmente esta sentencia compuesta en forma anidada a la forma ampliada.

Por ejemplo, para 4 bloques de sentencias, los bloques anidados en forma ampliada quedarían visualmente así:

if (condicion_1)
{
   bloque 1 de sentencias;
}
else
{
   if (condicion_2)
   {
      bloque 2 de sentencias;
   }
   else
   {
      if (condicion_3)
      {
         bloque 3 de sentencias;
      }
      else // si no se cumple ninguna de las anteriores
      {
         bloque 4 de sentencias;
      }
   }
}

El último bloque else puede aparecer opcionalmente.

../../_images/if_else_if.jpg

Diagrama de flujo de la sentencia if - else if - ... - else

Ejemplo

// Solicita tres enteros y determina su orden
#include <iostream>
using namespace std;
int main()
{
   int x, y, z;
   cout << "Introduce tres enteros separados por espacios: ";
   cin >> x >> y >> z;

   cout << "El orden de menor a mayor es: ";
   if (x < y)
   {
      if (z < x)
         cout << z << ", " << x << ", " << y << endl;
      else if (z < y)
         cout << x << ", " << z << ", " << y << endl;
      else
         cout << x << ", " << y << ", " << z << endl;
   }
   else
   {
      if (z < y)
         cout << z << ", " << y << ", " << x << endl;
      else if (z < x)
         cout << y << ", " << z << ", " << x << endl;
      else
         cout << y << ", " << x << ", " << z << endl;
   }
}

Edita, compila y ejecuta el código

Consideraciones respecto a la sintaxis

De cara a la legibilidad del código y evitar errores es fundamental sangrar las líneas de un bloque anidado de sentencias.

A pesar de sus pocas líneas, el siguiente fragmento de código es ilegible:

if (n > 0)
if (a > b)
z = a;
else
z = b;

Su versión sangrada permite visualizar de forma más clara las intenciones del programador:

if (n > 0)
   if (a > b)
      z = a;
   else
      z = b;

Nótese que el bloque else siempre está asociado al if inmediatamente anterior. Por ello, si en el ejemplo anterior, lo que realmente se desea es asociar el else al primer if, la solución sería:

if (n > 0)
{
   if (a > b)
      z = a;
}
else
   z = b;

Condiciones de evaluación mutuamente excluyentes

La siguiente tabla muestra dos escenarios en los cuales la salida del programa será idéntica si el conjunto de condiciones es mutuamente excluyente.

Opción 1

Opción 2

if (condicion_1)
{
   bloque 1 de sentencias;
}
else if (condicion_2)
{
   bloque 2 de sentencias;
}
// Resto de bloques else if
else if (condicion_n)
{
   bloque n de sentencias;
}
if (condicion_1)
{
   bloque 1 de sentencias;
}
if (condicion_2)
{
   bloque 2 de sentencias;
}
// Resto de bloques if
if (condicion_n)
{
   bloque n de sentencias;
}

En estos casos, además de la mejora en la legibilidad del código, es computacionalmente superior la Opción 1.

  • Con la opción 1, en el momento en que una condición se evalúe como true, el resto de condiciones serán ignoradas.

  • Con la opción 2, aunque una de las condiciones se evalúe como true, el programa seguirá evaluando el resto de condiciones, lo que, al ser excluyentes, es una pérdida de tiempo.