martes, 19 de enero de 2021

El selector Case.

El selector Case.

El poder de Case of en Pascal es muy grande, especialmente si se lo compara con cierto lenguaje. Por ejemplo permite rangos, valores separados por comas y una vez encontrada la coincidencia se sale del case, es decir, no se escribe un Break para finalizar cada sentencia.
Case trabaja con tipos de datos ordinales: enteros, enumerados, caracteres y cadenas. Los selectores deben ser todos del mismo tipo y literales (constantes) ya que se evalúan en tiempo de compilación.

Ejemplos:

const
  num1=10;
var
  num2:integer;
  i:integer;
...
i:=20;
Case i of
  num1 : writeLn('Es el número 10'); // Si i vale 10 se ejecuta esta sentencia y se sale del Case.
  num2 : writeLn('Es un entero'); // Error
  num1+10 : writeLn('Es el número 20');
else
   writeLn('Es otro número');
   writeLn('Pero no es el 10');
end;

Num2 es inválido porque no puede determinarse el valor de Num2 durante la compilación.
Num1 + 10 sí es válido ya que 10 + 10 = 20 es una expresión que se determina durante la compilación.
Else: también puede usarse Otherwise, es lo mismo, pero suele utilizarse Else. Nótese que no requiere begin .. end, no obstante se puede utilizar. Especificar Else no es obligatorio, si no encuentra el valor, simplemente se continúa con la siguiente sentencia del programa.

var
  c:Char;
...
case c of
  'a' : WriteLn('c es a');
  'b' : WriteLn('c es a');
  'c' : WriteLn('c es a');
  'a' : WriteLn('c es a'); // Error
end;

Error: no se pueden duplicar los selectores, aunque es algo más que obvio.

var
 s:String;
...
case s of
  'azul', 'rojo' : WriteLn('Son colores');
  'Debian', 'Linux Mint', 'Ubuntu' : WriteLn('Son sistemas operativos');
else
  WriteLn('Es otra cosa.');
end;

Este ejemplo no tiene errores.

var
  i,a:integer;
...
Case i of
  0 : begin
        WriteLn('El número es cero');
        a:=i+1;
      end;
  1..99 : WriteLn('Es un número de 2 dígitos');
  100, 101, 102..999 : WriteLn('Número de 3 dígitos');
else
  WriteLn('Mayor o igual a 1000');
end;

Desde ya, se pueden usar rangos y como vemos, en un mismo selector se pueden especificar varios valores. No es obligatorio que los valores estén ordenados, pero es una buena práctica al tratarse de enteros, pues facilita la lectura del código.

Otro ejemplo con Char:

var
  c:Char;
...
Case c of
  'A..Z', 'a..z' : WriteLn('Es una letra');
  '0..9' : WriteLn('Es un número');
  1..2 : WriteLn('E'); //Error
else
  WriteLn('No es ni letra ni número');
end;

Como vemos los rangos también se pueden utilizar con caracteres. El error se daría en 1..2 porque son enteros, no caracteres.

Para finalizar, un ejemplo con enumerados:

type
 TDia=(Lunes, Martes, Miercoles, Jueves, Viernes, Sabado, Domingo);
var
  Dia:TDia;
...
Case Dia of
  Lunes..Viernes : WriteLn('Es un día laborable');
  Sabado         : WriteLn('A veces los sábados se trabaja');
  Domingo        : WriteLn('Es feriado o no laborable');
end;

El siguiente código lo utilizo en el programa Marcadores:

type
  TBuscar=(Duplicados,Errores,Error0,Error400,Error500,Redirect,OK200,Todos);
...
var
  QueBuscar:TBuscar;
...
function TFSeleccionar.CargarGrid: Boolean;
var
  i,f:Integer;
begin
  f:=0;
  for i:=Low(aReg) to High(aReg) do
  begin
    case QueBuscar of
      Todos : begin
                if ((aReg[i].chequear) and (not(aReg[i].Eliminar))) then
                 begin
                   Inc(f);
                   SGrid.InsertRowWithValues(f,['','','','']);
                   if aReg[i].borrar then SGrid.Cells[0,f]:='1' else SGrid.Cells[0,f]:='0';
                   SGrid.Cells[1,f]:=IntToStr(aReg[i].indice);
                   SGrid.Cells[2,f]:=aReg[i].URL;
                   SGrid.Cells[3,f]:=IntToStr(aReg[i].statuscode);
                   SGrid.Cells[4,f]:=IntToStr(aReg[i].Redirect);
                   SGrid.Cells[5,f]:=IntToStr(i);
                 end;
              end;
      Errores : begin
                  if ((aReg[i].chequear)  and (not(aReg[i].Eliminar)) and ((aReg[i].statuscode=0) or (aReg[i].statuscode>=400))) then
                  begin
                    Inc(f);
                    SGrid.InsertRowWithValues(f,['','','','']);
                    if aReg[i].borrar then SGrid.Cells[0,f]:='1' else SGrid.Cells[0,f]:='0';
                    SGrid.Cells[1,f]:=IntToStr(aReg[i].indice);
                    SGrid.Cells[2,f]:=aReg[i].URL;
                    SGrid.Cells[3,f]:=IntToStr(aReg[i].statuscode);
                    SGrid.Cells[4,f]:=IntToStr(aReg[i].Redirect);
                    SGrid.Cells[5,f]:=IntToStr(i);
                  end;
                end;
      Duplicados : begin
                     if ((aReg[i].chequear) and (not(aReg[i].Eliminar))) then
                       begin
                         Inc(f);
                         SGrid.InsertRowWithValues(f,['','','','']);
                         SGrid.Cells[0,f]:='0';
                         SGrid.Cells[1,f]:=IntToStr(aReg[i].indice);
                         SGrid.Cells[2,f]:=aReg[i].URL;
                         SGrid.Cells[3,f]:=IntToStr(aReg[i].statuscode);
                         SGrid.Cells[4,f]:=IntToStr(aReg[i].Redirect);
                         SGrid.Cells[5,f]:=IntToStr(i);
                       end;
                     end;
    end;
  end;
  Result:=SGrid.RowCount>0;
end;

No hay comentarios:

Publicar un comentario