AnteriorPosterior

Tema 8b. Funciones matemáticas y de cadena

  Curso: Curso de Pascal, por Nacho Cabanes

Curso de Pascal. Tema 8.10. Funciones matemáticas: abs, sin, cos, arctan, round, trunc, sqr, sqrt, exp, ln, odd, potencias.

La mayoría de las que vamos a ver son funciones matemáticas que están ya predefinidas en Pascal.  Muchas de ellas son muy evidentes, pero precisamente por eso no podía dejarlas sin mencionar al menos:
  • Abs: valor absoluto de un número.
  • Sin: seno de un cierto ángulo dado en radianes.
  • Cos: coseno, análogo.
  • ArcTan: arco tangente.  No existe función para la tangente, que podemos calcular como sin(x)/cos(x).
  • Round: redondea un número real al entero más cercano.
  • Trunc: trunca los decimales de un número real para convertirlo en entero.
  • Int: igual que trunc, pero el resultado sigue siendo un número real.
  • Sqr: eleva un número al cuadrado.
  • Sqrt: halla la raíz cuadrada de un número.
  • Exp: exponencial en base e, es decir, eleva un número a e.
  • Ln: calcula el logaritmo neperiano (base e) de un número.
  • Odd: devuelve TRUE si un número es impar.
  • Potencias: no hay forma directa de elevar un número cualquiera a otro en pascal, pero podemos imitarlo con "exp" y "ln", así:

{--------------------------} 
{  Ejemplo en Pascal:      } 
{                          } 
{    Elevar un número real } 
{    a otro                } 
{    ELEVAR.PAS            } 
{                          } 
{  Este fuente procede de  } 
{  CUPAS, curso de Pascal  } 
{  por Nacho Cabanes       } 
{                          } 
{  Comprobado con:         } 
{    - Free Pascal 2.2.0w  }
{    - Turbo Pascal 7.0    } 
{--------------------------}

program elevar;

function elevado(a,b: real): real; 
begin 
  elevado := exp(b *ln(a) ); 
end;

begin 
  writeln(elevado(2,3)); 
end. 


 

La deducción de esta fórmula es fácil, conociendo las propiedades de los logaritmos y las exponenciales

  a^b = exp ( ln ( a^b )) = exp ( b * ln ( a ))
 


Curso de Pascal. Tema 8.11. Cadenas de texto.

En Turbo Pascal tenemos facilidades para trabajar con cadenas de texto, y desde luego, con más comodidad que desde otros lenguajes como C.

Las funciones incorporadas para el manejo de cadenas son:
 

  • copy.  Devuelve una subcadena.  Su formato es  function copy(cad: string; posic: integer; cuantos: integer): string;  Es decir, le indicamos en qué cadena nos queremos basar, desde qué posición queremos empezar a tomar las letras y cuántas queremos leer.  Así, copy('JUAN PEREZ', 1, 4)  daría 'JUAN'
  • concat.  Concatena varias cadenas.  Su formato es function concat(cad1 [, cad2,..., cadN]: string): string; (lo que hay entre corchetes es opcional). Lo que hace es crear una cadena de texto a partir de varias que va concatenando.    cadena := concat(cad1, cad2, cad3)  es lo mismo que si tecleásemos:  cadena := cad1 + cad2 + cad3
  • delete.  Borra parte de una cadena.  El formato es procedure delete(var cad: string; posic: integer; cuantos: integer): string;  y lo que hace es eliminar "cuantos" letras a partir de la posición "posic":  si TEXTO es 'JUAN PEREZ', delete(texto, 2, 5) haría que TEXTO pasase a ser 'JEREZ'.
  • insert.  Inserta una subcadena dentro  de una cadena. Su formato es  procedure Insert(texto: string; var donde: string; posic: integer);  donde "texto" es la cadena que queremos insertar, "donde" es la cadena inicial en la que queremos que se inserte, y "posic" es la posición de "donde" en la que se insertará "texto".
  •  length.  Dice la longitud de una cadena de texto:  function length(cad: string): integer;
  • pos.  Indica la posición de una subcadena dentro de una cadena: function pos(subcadena: string; cadena: string): byte; Por ejemplo, pos('Pérez', 'Juan Pérez') devolvería un 6.  Si la subcadena no es parte de la cadena, devuelve 0.

Vamos a ver un ejemplo que las use:

 {--------------------------}
 {  Ejemplo en Pascal:      }
 {                          }
 {    Ejemplo de funciones  }
 {    de cadenas            }
 {    CADENAS.PAS           }
 {                          }
 {  Este fuente procede de  }
 {  CUPAS, curso de Pascal  }
 {  por Nacho Cabanes       }
 {                          }
 {  Comprobado con:         }
 {    - Free Pascal 2.2.0w  }
 {--------------------------}

 program cadenas;

 var
   frase: string;

 begin
   frase := 'Esta es una frase de ejemplo';
   writeln('La primera palabra (letras 1 a 4) es: ', copy(frase, 1, 4) );
   writeln('Si añadimos más texto: ', concat(frase, ' facilito') );

   delete(frase, 6, 2);
   writeln('Si borramos la segunda palabra (letras 5 a 7) es: ', frase );

   insert('si es', frase, 6);
   writeln('Y si insertamos una nueva segunda (y tercera) palabra: ',  frase);
   writeln('La longitud de la frase es: ', length(frase) );
   writeln('Y la primera a parece en la posición: ', pos('a', frase) );
 end. 

Que daría como resultado


La primera palabra (letras 1 a 4) es: Esta
Si añadimos más texto: Esta es una frase de ejemplo facilito
Si borramos la segunda palabra (letras 5 a 7) es: Esta  una frase de ejemplo
Y si insertamos una nueva segunda (y tercera) palabra: Esta si es una frase de ejemplo
La longitud de la frase es: 31
Y la primera a parece en la posición: 4

Pero esto tampoco es perfecto, y quien venga de programar en Basic echará de menos construcciones como Left$ (extraer varias letras de la izquierda) o Rigth$ (varias letras de la derecha).  También podríamos hacernos alguna funcioncita para convertir a hexadecimal, o de texto a número y al revés, o para manejar la fecha, etc.

La mayoría no son difíciles, así que allá vamos...
 

(Nota: estas rutinas las hice allá por el 93, y en su momento me sirvieron, aunque posiblemente muchas de ellas no estén programadas de la forma más eficiente).


Vamos a crear una Unit y a hacer un ejemplo que la use:

{--------------------------} 
{  Ejemplo en Pascal:      } 
{                          } 
{    Unidad con funciones  } 
{    mejoradas para mane-  } 
{    jar cadenas           } 
{    NSTR.PAS              } 
{                          } 
{  Este fuente procede de  } 
{  CUPAS, curso de Pascal  } 
{  por Nacho Cabanes       } 
{                          } 
{  Comprobado con:         }
{    - Free Pascal 2.2.0w  } 
{    - Turbo Pascal 7.0    } 
{    - Tmt Pascal Lt 1.20  } 
{--------------------------} 

unit nSTR; 

{=====================} 
{                     } 
{    Unidad nSTR      } 
{  Manejo de cadenas  } 
{                     } 
{  Nacho Cabanes, 93  } 
{                     } 
{=====================}

interface

  type 
    TipoFecha = string[8];
  FUNCTION CADENA(const carc:char;             {Cadena de caracteres repetidos} 
    const veces:byte):string; 
  FUNCTION COMAS(var s:string): string;        {Cambia , por . para hallar valor} 
  FUNCTION CONPUNTO(const num:longint):string; {Nº como cadena con puntos: x.xxx.xxx} 
  FUNCTION FECHA(const separ:char):tipofecha;  {Fecha, indicando el separador} 
  FUNCTION HEX(const a:byte):string;           {Pasa byte a hexadecimal} 
  FUNCTION LEFT(const cad:string;              {Letras de la izquierda} 
    const n:byte):string; 
  FUNCTION MAYUSC(const cad:string):string;    {Convierte a mayúsculas} 
  FUNCTION RIGHT(const cad:string;             {Letras de la derecha} 
    const n:byte):string; 
  FUNCTION SPC(const n:byte):string;           {Espacios en blanco} 
  FUNCTION STRS(const valor:longint):string;   {Como STR$ de Basic} 
  FUNCTION STRSR(const valor:real):string;     {STRS$ para reales} 
  FUNCTION VALORLI(const cad:string):longint;  {Valor de un string como LongInt} 
  FUNCTION VALORR(const cad:string):real;      {Valor de un string como REAL} 
  FUNCTION VALORW(const cad:string):word;      {Valor de un string como WORD}

implementation

  uses dos;
  
  FUNCTION CADENA(const carc:char; const veces:byte):string; 
  { Crea una cadena formada por un mismo carácter repetido varias veces } 
  var 
    cadtmp: string; 
    i: byte; 
  begin 
    cadtmp := '';                               { Cadena vacía } 
    for i := 1 to veces do cadtmp[i] := carc;   { Voy dando valores } 
    cadtmp[0] := chr(veces);                    { Ajusto la longitud } 
    { Las dos líneas anteriores se podrían 
    reemplazar también por: 
    for i := 1 to veces do cadtmp := cadtmp + carc; 
    } 
    cadena := cadtmp                            { Valor definitivo } 
  end;
  
  FUNCTION COMAS(var s:string): string; 
  { Cambia comas por puntos (decimales en formato americano) para poder 
    introducir un número en formato español y hallar su valor} 
  var 
    i: byte; 
    t: string; 
  begin 
    t := s;                            { Copio la cadena inicial } 
    for i :=1 to length(t) do          { La recorro } 
      if t[i]=',' then t[i] := '.';    { Y si encuentro , pongo . } 
    comas := t; 
  end;
  
  FUNCTION CONPUNTO(const num:longint):string; 
  { Devuelve un número como cadena con puntos: x.xxx.xxx } 
  var 
    cadena: string; 
    d: byte; 
  const 
    punto: char = '.'; 
  begin 
    str(abs(num),cadena);              { Empiezo a trabajar sin signo } 
    d := length(cadena);               { Veo la longitud } 
    if d>3 then                        { Si es mayor de 1.000 } 
      insert(punto,cadena,d-2);        { inserto un punto } 
    d := length(cadena);               { Vuelvo a mirar } 
    if d>7 then                        { Si es mayor de 1.000.000 } 
      insert(punto,cadena,d-6);        { pongo otro punto } 
    if num<0 then cadena:='-'+cadena;  { Si es negativo, le pongo signo } 
    ConPunto := cadena; 
  end;
  
  FUNCTION FECHA(const separ:char):tipofecha; 
  { Para ver la fecha como DD/MM/AA, o DD-MM-AA, etc. } 
  var 
    dia,mes,ano,disem: word;          { Fecha leida del DOS } 
    temporal: string[8];              { Temporal, para valor final } 
    tempo2: string[2];                { Temporal, para cada dato } 
  begin 
    getdate(ano,mes,dia,disem);       { Leo la fecha del DOS } 
    str(dia,tempo2);                  { Paso el día a cadena } 
    temporal:=tempo2+separ;           { Y le añado el separador } 
    str(mes,tempo2);                  { Paso el mes } 
    temporal:=temporal+tempo2+separ;  { Y lo añado } 
    str(ano mod 100,tempo2);          { Paso el año (dos ultimas cifras) } 
    temporal:=temporal+tempo2;        { Lo añado } 
    fecha:=temporal;                  { Y se acabó } 
  end;
  FUNCTION HEX(const a:byte):string; 
  { Convierte un byte a hexadecimal } 
  const 
    cadena: string[16] = '0123456789ABCDEF'; 
  begin 
    hex := cadena[a div 16 + 1]       { La primera letra: dividir entre 16 } 
      + cadena[a mod 16 + 1];         { La segunda: resto de la división } 
  end;
  
  FUNCTION LEFT(const cad:string; const n:byte):string; 
  { Cadena formada por los n caracteres más a la izquierda } 
  var 
    temp: string; 
  begin 
    If n > length(cad) then         { Si piden más que la longitud } 
      temp := cad                  { La cojo entera } 
    else 
      temp := copy(cad,1,n);       { Si no, una subcadena } 
    Left := temp; 
  end;
  
  FUNCTION MAYUSC(const cad:string):string; 
  { Convierte una cadena a mayúsculas.  La forma de tratar los caracteres 
    internacionales no es la más adecuada, porque pueden variar en las 
    distintas páginas de códigos, pero sirva al menos como ejemplo de 
    cómo comprobar si un valor está entre varios dados  O:-) } 
  var 
    buc: byte; 
    cad2: string; 
  begin 
    cad2 := cad; 
    for buc := 1 to length(cad2) do 
      begin 
      if cad2[buc] in ['a'..'z'] then           { Letras "normales" } 
        cad2[buc] := upcase(cad2[buc]); 
      { Internacionales: esto es lo que puede dar problemas } 
      if cad2[buc] in ['á','à','ä','â','Ä'] then cad2[buc]:='A'; 
      if cad2[buc] in ['é','è','ë','ê','É'] then cad2[buc]:='E'; 
      if cad2[buc] in ['í','ì','ï','î'] then cad2[buc]:='I'; 
      if cad2[buc] in ['ó','ò','ö','ô','Ö'] then cad2[buc]:='O'; 
      if cad2[buc] in ['ú','ù','ü','û','Ü'] then cad2[buc]:='U'; 
      if cad2[buc] = 'ñ' then cad2[buc]:='Ñ' 
      end; 
      mayusc := cad2                             { Valor definitivo } 
  end;
  
  FUNCTION RIGHT(const cad:string; const n:byte):string; 
  { Cadena formada por los n caracteres más a la derecha } 
  var 
    temp: string; 
  begin 
    If n > length(cad) then                   { Si piden más que la longitud } 
      temp := cad                            { La cojo entera } 
    else 
      temp := copy(cad, length(cad)-n+1, n); { Si no, subcadena } 
    right := temp; 
  end;
  
  FUNCTION SPC(const n: byte):string; 
  { Cadena formada por n espacios en blanco } 
  var 
    t: string; 
    i: byte; 
  begin 
    t := ' ';                         { Al menos uno } 
    for i := 2 to n do t:=t+' ';      { Si hay dos o más, añado } 
    spc := t 
  end;
  
  FUNCTION STRS(const valor:longint):string; 
  { Simplemente porque me gusta más usar STR como función que como 
    procedimiento (recuerdos del Basic, supongo) } 
  var 
    temporal: string; 
  begin 
    str(valor,temporal);             { Llamo al procedimiento STR } 
    strs := temporal; 
  end;
  
  FUNCTION STRSR(const valor:real):string; 
  { Igual que STRS, pero para números reales (deja 2 decimales) } 
  var 
    temporal: string; 
  begin 
    str(valor:3:2,temporal); 
    strsr := temporal; 
  end;
  
  FUNCTION VALORW(const cad:string):word; 
  { Valor de un string como WORD, para evitar usar VAL como procedimiento 
    que es más potente pero también más incómodo a veces (posiblemente, 
    esto también está aquí por culpa del Basic ;-) ) } 
  var 
    uno:word; 
    code:integer; 
  begin 
    val(cad,uno,code); 
    valorw:=uno; 
  end;
  
  FUNCTION VALORLI(const cad:string):longint; 
  { Igual que VALORW, pero para LongInt } 
  var 
    uno:longint; 
    code:integer; 
  begin 
    val(cad,uno,code); 
    valorli:=uno; 
  end;
  
  FUNCTION VALORR(const cad:string):real; 
  { Igual que VALORW, pero para reales.  Primero cambia las , por . } 
  var 
    uno:real; 
    code:integer; 
    cad2:string; 
  begin 
    cad2:=cad; 
    while Pos(',', cad2) > 0 do               { Le cambio , por . (si hay) } 
      cad2[Pos(',', cad2)]:= '.'; 
    val(cad2,uno,code);                       { Y llamo al procedimiento } 
    valorr:=uno; 
  end;

end. 

 

Un ejemplo de programa que usaría estas funciones sería:

{--------------------------} 
{  Ejemplo en Pascal:      } 
{                          } 
{    Prueba de la unidad   } 
{    nStr                  } 
{    USASTR.PAS            } 
{                          } 
{  Este fuente procede de  } 
{  CUPAS, curso de Pascal  } 
{  por Nacho Cabanes       } 
{                          } 
{  Comprobado con:         }
{    - Free Pascal 2.2.0w  } 
{    - Turbo Pascal 7.0    } 
{    - Tmt Pascal Lt 1.20  } 
{--------------------------}

program UsaStr;  { Ejemplo de la unidad nStr }

uses 
  crt, nSTR;
  
var 
  texto: string; 
  numero1: longint; 
  numero2: real;
  
begin 
  texto := 'Este será el texto inicial.'; 
  numero1 := 1234567; 
  numero2 := 1234567.895; 
  clrscr; 
  writeln('  ----- Prueba de la Unidad nSTR, día '+ fecha('-')+ ' -----'); 
  writeln; 
  writeln( texto ); 
  writeln('Convertido a mayúsculas: ', mayusc(texto) ); 
  writeln('Sus 8 primeras letras: ', left(texto,8) ); 
  writeln('Las 7 últimas: ', right(texto,7) ); 
  writeln('La 3ª y las 5 siguientes: ', copy(texto,3,5) ); 
  writeln; 
  writeln('Siete espacios y 10 X: ', spc(7), cadena('X',10), '.'); 
  writeln; 
  writeln('El primer número es: ', numero1); 
  writeln('Si le ponemos puntos separadores: ', ConPunto(numero1) ); 
  writeln('Las dos últimas cifras son: ', numero1 mod 100, 
    ', que en hexadecimal es: $', hex(numero1 mod 100) ); 
  writeln('La segunda y la tercera cifra, como cadena: ', 
    copy(strs(numero1),2,2) ); 
  writeln; 
  writeln('El segundo número: ', numero2 ); 
  writeln('En notación "normal": ', numero2:10:3 ); 
  writeln('Como cadena: ', strsr(numero2) ); 
  writeln('El valor de "123,5" es: ', valorr('123,5') :6:1 ); 
end. 

Que mostraría algo como


  ----- Prueba de la Unidad nSTR, día 16-6-10 -----

Este será el texto inicial.
Convertido a mayúsculas: ESTE SERA EL TEXTO INICIAL.
Sus 8 primeras letras: Este ser
Las 7 últimas: nicial.
La 3ª y las 5 siguientes: te se

Siete espacios y 10 X:        XXXXXXXXXX.

El primer número es: 1234567
Si le ponemos puntos separadores: 1.234.567
Las dos últimas cifras son: 67, que en hexadecimal es: $43
La segunda y la tercera cifra, como cadena: 23

El segundo número:  1.234567895000000E+006
En notación "normal": 1234567.895
Como cadena: 1234567.90
El valor de "123,5" es:  123.5


Actualizado el: 28-12-2011 22:04

AnteriorPosterior