Instrucciones condicionales

Por
Ilustración de la instrucción condicional If… then.

En nuestra rutina diaria, a veces nos vemos obligados a tomar una determinada decisión, en la cual tenemos que elegir una entre varias acciones posibles, según la situación que más nos convenga. De manera similar, podemos hacer que un programa ejecute selectivamente sólo una de varias acciones (o ninguna de ellas) según una condición determinada. En el lenguaje Pascal, esto es posible gracias a las instrucciones condicionales que estudiaremos a continuación.

La instrucción if

La instrucción if (condicional simple) tiene una composición lógica de dos ramas de instrucciones alternativas; la cual ejecuta sólo una de sus ramas, según el valor de una expresión. La sintaxis para esta instrucción es la siguiente:

If {expresión} then 

   {Instrucción 1}

else

   {Instrucción 2};

Donde: {expresión} debe ser una variable o una expresión de tipo boolean. Si {expresión} devuelve el valor verdadero, entonces se ejecutará la instrucción siguiente a la rama then; en caso que devuelva falso, se ejecutará la instrucción siguiente a la rama else.

Note como toda la estructura if corresponde a una sola unidad de instrucción; la cual debe separarse de otras instrucciones mediante punto y coma al final (éste no se permite antes de su rama else).

A continuación, un ejemplo de un segmento de programa que utiliza la instrucción if:

Begin

    Clrscr;
    Write ('Digite un número: ');
    Read (x);
    Write ('Digite otro número: ');
    Read (y);

    If x > y then
       m := x   {Se ejecuta si x > y = verdadero}
    else
       m := y;  {Se ejecuta si x > y = falso}

    Writeln ('El mayor es: ', m);

End.

Cuando la estructura de la instrucción if sea muy corta, conviene escribirla toda en una misma línea (respetando los espacios en blanco); así la instrucción if del ejemplo anterior podría reescribirse de la siguiente manera:

If x > y then m := x else m := y;

Aunque la instrucción if solamente puede contener una instrucción por rama, esto no nos impide incluir instrucciones compuestas en lugar de instrucciones simples. Recuerde que una instrucción compuesta es un bloque de instrucciones acotadas entre las palabras begin y end, tal como se expuso en el artículo anterior. Por ejemplo:

If x > y then

   Begin
      r := x - y;
      Writeln ('La diferencia es: ', r);
   End

Else

   Begin
      r := x + y;
      Writeln ('La suma total es: ', r);
   End;

Una particularidad de la instrucción if es que su rama else es opcional; en caso de no ser incluida, si la expresión evaluada resulta ser falsa, entonces no se ejecutará ninguna acción. La omisión de dicha rama corresponde a la forma simplificada de la instrucción if, la cual resulta muy útil para controlar excepciones que pudieran afectar algunos procesos posteriores.

Por ejemplo, en el siguiente segmento de instrucciones se utiliza la forma if simplificada como sentencia de control.

Readln (num);
n := num - 1;     {Se espera que num sea par}

If num mod 2 = 1 then 
   n :=  num - 2; {Pero, num a veces será impar}

Writeln ('El número impar más próximo es ', n);

Mediante el segmento de código anterior podemos hallar el número impar más próximo al número ingresado por el usuario; al que normalmente se le resta 1 salvo cuando es impar, que se le restan 2.

Anidamiento de instrucciones If

Hasta ahora, hemos visto que la instrucción if sólo permite la ejecución de una de dos alternativas; sin embargo, es posible utilizarla para realizar la ejecución selectiva múltiple: la idea consiste en anidar una instrucción if dentro de una de las ramas then o else de otra instrucción if. Por ejemplo, suponga que necesita un programa que asigne a una persona un atributo en función de su estatura, entonces necesitará el código a continuación, el cual realiza una selección entre tres sentencias que indican si la persona es de estatura baja, media o alta.

Write ('Digite su estatura (en cm)');
Readln (altura);

If altura <= 150 then

    Writeln ('Estatura Baja')

Else 

   If altura <= 170 then

       Writeln ('Estatura Media')

   Else 

       Writeln ('Estatura Alta');

Es importante sangrar adecuadamente el código de las instrucciones para mantener la legibilidad, ya que en el anidamiento de instrucciones if, suele surgir cierta ambigüedad al emparejar cada rama else con su respectiva instrucción if. Para evitar ambigüedades, la regla es que cada rama else se empareje con la instrucción if solitaria más próxima (buscando siempre hacia atrás).

Por ejemplo, el anidamiento de instrucciones if podría dar lugar a estructuras como:

If expr1 then

   If expr2 then 
      a:=b+c 
Else
   a:=b-c;

La ambigüedad sintáctica en la estructura anterior es solo aparente, y podría resolverse reescribiendo esa misma estructura como se indica a continuación:

If expr1 then

   Begin
   
      If expr2 then	  
         a:=b+c		 
      Else	  
         a:=b-c
		 
   End;

En los dos bloques de instrucciones anteriores ¿a cual de las dos instrucciones if pertenece la rama else?, a pesar de su apariencia, esos dos bloque son sintácticamente equivalentes; en ambos casos, la rama else corresponde la segunda sentencia if.

Si desea forzar a que esta estructura sea interpretada en contra la regla, entonces se pueden usar las palabras begin y end para aislar la segunda instrucción if del siguiente modo:

If expr1 then
   Begin
      If expr2 then
         a:=b+c
   End
Else
   a:=b-c;

La instrucción Case

La instrucción case (condicional múltiple) se basa en una estructura lógica consistente de una expresión (llamada selector), y una lista de instrucciones prefijadas por uno o varios valores constantes (llamados constantes case); también, puede incluir una rama opcional else. La sintaxis para la instrucción case es la siguiente:

Case {expresión} of

   C1: {instrucción 1};
   C2, C3, C4: {instrucción 2};
   C5..Cn: {instrucción 3};
   
   ...
   
   Else {instrucción n};

End;

Donde {expresión} es una variable o expresión que funciona como selector de instrucciones, mientras que C1 a Cn son las constantes case usadas como prefijos de la lista de instrucciones.

La instrucción case permite la selección entre múltiples acciones, es decir, solo ejecutará aquella instrucción prefijada por las constantes, o rangos de constantes, que coincidan en al menos un valor con el valor del selector.

Si el valor del selector no coincide con ninguna constante, y está presente la rama else, entonces se ejecutará la instrucción de la rama else; pero, si esta rama no está presente, el flujo de ejecución continúa en la instrucción subsiguiente a la palabra end.

Observe los siguientes ejemplos de instrucciones case:

{Utilizando constantes literales como prefijo:}

Case num of

    0, 2, 4, 6, 8: Writeln ('Es un número par');
    1, 3, 5, 7, 9: Writeln ('Es un número impar');
    10..100: Writeln ('Es un número entre 10 y 100');

    Else

    Writeln ('Es negativo o mayor que 100');

End;

{Utilizando constantes declaradas como prefijo:}

Case Operador of

   Suma: X := X + Y;
   Rest: X := X - Y;
   Mult: X := X * Y;

End;

La instrucción case puede evitarnos un engorroso anidamiento instrucciones para elegir entre más de dos opciones, ya que permite elegir entre múltiples acciones con una sintaxis mucho más clara que la que se obtiene al anidar instrucciones if.

Notas sobre la instrucción case

El selector debe retornar un valor de tipo ordinal como byte, word, longint, o char; los selectores de tipo string no son válidos en Turbo Pascal. Cada constante case debe ser única y del mismo tipo del valor retornado por el selector.

Las instrucciones case también pueden contener instrucciones compuestas (es decir, bloques Begin... end) en lugar de instrucciones simples.

En Free Pascal se permite el uso de cadenas como prefijos, en este caso el selector debe devolver valores de tipo string. Al utilizar el tipo string, se compara el selector y las constantes case teniendo en cuenta las mayúsculas y minúsculas. Por ejemplo:

Case lowercase(browser) of

   'iexplorer': WriteLn (’Internet Explorer');
   'chrome': Writeln ('Google Chrome');
   'firefox': Writeln ('Mozilla Firefox');

   Else

   WriteLn ('Otro Navegador');

end;

A diferencia de Turbo Pascal, las constantes case duplicadas no son permitidas en Free Pascal, por tanto, el siguiente el código generará un error de compilación:

Case i of
   3: instrucción1;
   1..5: instrucción2;
end;

Al compilar el código anterior, se producirá un error por constantes duplicadas, puesto que el valor 3 también aparece implícitamente dentro del rango [1..5].

Usos de la instrucción case

La instrucción case puede tener muchos usos; sin embargo, su uso más frecuente es el control de programas mediante menús, es decir, se muestra en pantalla las diferentes acciones que pueden ejecutarse dentro del programa y el usuario elige, mediante un numero o una letra, aquella acción que quiere realizar. Por ejemplo, supongamos un programa de gestión de una biblioteca. Tal programa deberá proporcionar un menú en pantalla con las siguientes opciones:

C. Consulta bibliográfica.
P. Préstamo de libros.
D. Devolución de libros.
S. Salir.

Si las opciones son muy complejas, pueden mostrarse submenús donde se seleccionen otras características de la opción elegida. Por ejemplo, al elegir la opción de "consulta bibliográfica" puede mostrarse un submenú con sus distintas opciones disponibles:

A. Consultar por autores.
T. Consultar por temática.
I. Consultar por ISBN.
R. Volver atrás.

En una primera versión, un fragmento del programa aquí descrito podría tener la siguiente forma:

Read (opcion) {opción del menú}

Case opcion of

   'b': Writeln ('Búsqueda.');
   'p': Writeln ('Solicitud de Préstamo.');
   'd': Writeln ('Devolución de libros.');
   's': Writeln ('Salir.');

   Else 

   Writeln ('Opción no válida.');

End;

Otro ejemplo práctico y muy sencillo donde se utiliza la instrucción case, como menú de opciones, es el programa a continuación, cuyo código puede ejecutarse en un compilador Pascal compatible:

Program E13_Calculadora;

{Funciona en: Free Pascal 3.0.4 y Turbo Pascal 7.0}
{Nota: observe cada instrucción de la lista Case.. of}

Uses  crt;

Label Menu, L1, L2;   {Etiquetas de salto}

Var   op: longint;    {Operaciones}
      a, b: integer;  {Operandos}
      s: string;      {Signo de operador}
      r: real;        {Resultado}

Begin

{Menú principal}

Menu: Clrscr;
      Writeln ('***** CALCULOS SIMPLES *****', #13#10);
      Writeln ('1. Suma');
      Writeln ('2. Resta');
      Writeln ('3. Multiplicación');
      Writeln ('4. División');
      Writeln ('5. Salir');
      Write (#10#13, 'Elija una opción: ');
L1:   Readln (op);

{Validación de la opción elegida}

      If (op < 1) or (op > 5) then

         Begin
           Write ('elija una opción válida: ');
           Goto L1
         End

      Else if op = 5 then

           Goto L2;

{Entrada de datos}

      Write (#10#13, 'Digite un número: ');
      Read (a);
      Write ('Digite otro número: ');
      Read (b);

{Procesos}

      Case op of

         1: Begin {Suma}
              r := a + b; s := ' + '
            End;

         2: Begin {Resta}
              r := a - b; s := ' - '
            End;

         3: Begin {Multiplicación}
              r := a * b; s := ' * '
            End;

         4: If (b <> 0) then {División}

                Begin
                  r := a / b; s := ' / ';
                End

            Else

                Begin
                  Write ('Imposible dividir por cero');
                  Goto L2;
                End;

      End;

{Salida de datos}

      Writeln (#10#13, a, s, b, ' = ', r:0:2);

{Cierre del programa}

L2:  Write (#10#13, 'Pulse una tecla para salir');
      Readkey;

End.