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