03 agosto 2007

El tipo Variant

Las variables de tipo Variant dan una gran flexibilidad a Delphi permitiendo el almacenamiento de cualquier tipo de dato básico dentro de las mismas.

Estas variables son muy útiles cuando se necesitan procesar muchos datos en tiempo de ejecución antes de saber su tipo, pero debido a los errores que puede causar hay que tener cuidado al utilizarlas.

Lo que no pueden contener es ninguna estructura de datos, objetos ni punteros. Por ejemplo, no se puede hacer:

var
Variable: Variant;
begin
Variable := nil;

Ya que provocaría un error al compilar. Pero si se puede hacer:

Variable := NULL;

Y mucho ojo porque no es lo mismo una variable Nula que una variable Vacia. Cuando se crea una variable Variant y no se hace nada con ella sigue siendo una variable Vacia, pero no nula. Será Nula si nosotros se lo decimos como hemos visto anteriormente.

¿Pero como sabemos que tipo tipo de dato contiene una variable Variant? Pues para eso tenemos la función VarType que nos devuelve el tipo de dato que contiene una variable Variant. Aquí tenemos una función que nos devuelve el tipo de dato de un Variant:

function TipoVariable( Variable: Variant ): String;
var iTipo: Integer;
begin
iTipo := VarType( Variable );

case iTipo of
varEmpty : Result := 'Vacía';
varNull : Result := 'Nula';
varSmallInt : Result := 'SmallInt';
varInteger : Result := 'Integer';
varSingle : Result := 'Single';
varDouble : Result := 'Double';
varCurrency : Result := 'Currency';
varDate : Result := 'Date';
varOleStr : Result := 'OleStr';
varDispatch : Result := 'Dispatch';
varError : Result := 'Error';
varBoolean : Result := 'Boolean';
varVariant : Result := 'Variant';
varUnknown : Result := 'Desconocida';
varByte : Result := 'Byte';
varWord : Result := 'Word';
varLongWord : Result := 'LongWord';
varInt64 : Result := 'Int64';
varStrArg : Result := 'StrArg';
varString : Result := 'String';
varAny : Result := 'Any';
end;

Result := 'Tipo ' + Result;
end;

Veamos un ejemplo de su utilización volcando el contenido en un Memo:

var
Variable: Variant;
begin
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := NULL;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := 125;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := 1250;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := 125000;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := -1800;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := -1900000;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := 'Cadena de texto';
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );
Variable := True;
Memo.Lines.Add( 'Variable=' + VarToStr( Variable ) );
Memo.Lines.Add( TipoVariable( Variable ) );

El resultado que mostrará en pantalla será el siguiente:

Variable=
Tipo Vacía
Variable=
Tipo Nula
Variable=125
Tipo Byte
Variable=1250
Tipo Word
Variable=125000
Tipo LongWord
Variable=-1800
Tipo SmallInt
Variable=-1900000
Tipo Integer
Variable=Cadena de texto
Tipo String
Variable=True
Tipo Boolean

Como vemos según el dato que guardamos en la variable va adaptándose de un tipo a otro.

Pruebas realizadas en Delphi 7.

02 agosto 2007

Conversiones entre unidades de medida

Delphi incorpora una librería interesante encargada de realizar conversiones entre unidades de tiempo, volumen, distancia, etc. Para ello hay que añadir las unidades ConvUtils y StdConvs:

uses
Windows, Messages, ..., ConvUtils, StdConvs;

La función encargada de realizar conversiones es la siguiente:

Convert( ValorAConvertir: Double; DesdeUnidad, HastaUnidad: TConvType): Double;

Veamos algunos ejemplos mostrando el resultado en un campo Memo.
Para convertir de millas a kilómetros:

var dMillas, dKilometros: Double;
begin
dMillas := 15;
dKilometros := Convert( dMillas, duMiles, duKilometers );
Memo.Lines.Add( Format( '%8.4f Millas = %8.4f Kilometros', [dMillas, dKilometros] ) );

Esta otra convierte de pulgadas de área a centímetros de area:

var dPulgadas, dCentimetros: Double;
begin
dPulgadas := 21;
dCentimetros := Convert( dPulgadas, auSquareInches, auSquareCentimeters );
Memo.Lines.Add( Format( '%8.4f Pulgadas de área = %8.4f Centímetros de área', [dPulgadas, dCentimetros] ) );

Y si queremos convertir libras en kilogramos:

var dLibras, dKilos: Double;
begin
dLibras := 60;
dKilos := Convert( dLibras, muPounds, muKilograms );
Memo.Lines.Add( Format( '%8.4f Libras = %8.4f Kilos', [dLibras, dKilos] ) );

También podemos convertir unidades de temperatura:

var dFahrenheit, dCelsius: Double;
begin
dFahrenheit := 84;
dCelsius := Convert( dFahrenheit, tuFahrenheit, tuCelsius );
Memo.Lines.Add( Format( '%8.4fº Fahrenheit = %8.4fº Celsius', [dFahrenheit, dCelsius] ) );

Así como conversión entre unidades de volumen:

var dMetrosCubicos, dLitros: Double;
begin
dMetrosCubicos := 43;
dLitros := Convert( dMetrosCubicos, vuCubicMeters, vuLiters );
Memo.Lines.Add( Format( '%8.4f Metros cúbicos = %8.4fº Litros', [dMetrosCubicos, dLitros] ) );

Ahora vamos a ver todos los tipos de conversión según las unidades de medida.
Para convertir entre unidades de área tenemos:

auSquareMillimeters
auSquareCentimeters
auSquareDecimeters
auSquareMeters
auSquareDecameters
auSquareHectometers
auSquareKilometers
auSquareInches
auSquareFeet
auSquareYards
auSquareMiles
auAcres
auCentares
auAres
auHectares
auSquareRods

Convertir entre unidades de distancia:

duMicromicrons
duAngstroms
duMillimicrons
duMicrons
duMillimeters
duCentimeters
duDecimeters
duMeters
duDecameters
duHectometers
duKilometers
duMegameters
duGigameters
duInches
duFeet
duYards
duMiles
duNauticalMiles
duAstronomicalUnits
duLightYears
duParsecs
duCubits
duFathoms
duFurlongs
duHands
duPaces
duRods
duChains
duLinks
duPicas
duPoints

Convertir entre unidades de masa:

muNanograms
muMicrograms
muMilligrams
muCentigrams
muDecigrams
muGrams
muDecagrams
muHectograms
muKilograms
muMetricTons
muDrams
muGrains
muLongTons
muTons
muOunces
muPounds
muStones

Convertir entre unidades de temperatura:

tuCelsius
tuKelvin
tuFahrenheit
tuRankine
tuReamur

Convertir entre unidades de tiempo:

tuMilliSeconds
tuSeconds
tuMinutes
tuHours
tuDays
tuWeeks
tuFortnights
tuMonths
tuYears
tuDecades
tuCenturies
tuMillennia
tuDateTime
tuJulianDate
tuModifiedJulianDate

Convertir entre unidades de volumen:

vuCubicMillimeters
vuCubicCentimeters
vuCubicDecimeters
vuCubicMeters
vuCubicDecameters
vuCubicHectometers
vuCubicKilometers
vuCubicInches
vuCubicFeet
vuCubicYards
vuCubicMiles
vuMilliLiters
vuCentiLiters
vuDeciLiters
vuLiters
vuDecaLiters
vuHectoLiters
vuKiloLiters
vuAcreFeet
vuAcreInches
vuCords
vuCordFeet
vuDecisteres
vuSteres
vuDecasteres
vuFluidGallons
vuFluidQuarts
vuFluidPints
vuFluidCups
vuFluidGills
vuFluidOunces
vuFluidTablespoons
vuFluidTeaspoons
vuDryGallons
vuDryQuarts
vuDryPints
vuDryPecks
vuDryBuckets
vuDryBushels
vuUKGallons
vuUKPottles
vuUKQuarts
vuUKPints
vuUKGills
vuUKOunces
vuUKPecks
vuUKBuckets
vuUKBushels

Pruebas realizadas en Delphi 7.

01 agosto 2007

Tipos de puntero

Pointer:

- Es un tipo general de puntero hacia cualquier objeto o variable en memoria.
- Al no ser de ningún tipo suele ser bastante peligroso si provoca desbordamientos de memoria.

PAnsiChar:

- Es un tipo de puntero hacia un valor AnsiChar.
- También puede ser utilizado para apuntar a caracteres dentro de una cadena AnsiString.
- Al igual que otros punteros permite la aritmética, es decir, los procedimientos Inc y Dec pueden utilizarse para mover el puntero en memoria.

PAnsiString:

- Apunta hacia una cadena AnsiString.
- Debido a que AnsiString ya es un puntero hacia si misma, el puntero PAnsiString no suele utilizarse mucho.

PChar:

- Es un tipo de puntero hacia un valor Char.
- Puede ser utilizado para apuntar a caracteres dentro de una cadena string.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.
- Suele utilizarse mucho para procesar cadenas de caracteres terminadas en cero, tal como las utilizadas en el lenguaje C/C++.
- Los caracteres Char son idénticos a los de las variables AnsiChar, siendo de 8 bits de tamaño.

PCurrency:

- Apunta hacia un valor Currency.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.

PDateTime:

- Apunta hacia un valor TDateTime.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.

PExtended:

- Apunta hacia un valor Extended.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.

PInt64:

- Apunta hacia un valor Int64.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.

PShortString:

- Apunta hacia una cadena ShortString.
- Debido a que las variables ShortString difieren de las variables string,
para apuntar a una variable ShortString es necesario utilizar la función Addr.

PString:

- Apunta hacia una cadena String.
- Al ser la cadena String un puntero en si misma no suele utilizarse mucho este puntero.

PVariant:

- Apunta hacia un valor Variant.
- Al ser Variant un tipo genérico y variable hay que extremar la precaución en el manejo de este puntero.

PWideChar:

- Apunta hacia un valor WideChar.
- Puede ser utilizado para apuntar a caracteres dentro de una cadena WideString.
- Permite aritmética de punteros mediante los procedimientos Inc y Dec.

PWideString:

- Apunta hacia una cadena WideString.
- Al ser ya cadena WideString un puntero en si misma no suele utilizarse mucho.

Pruebas realizadas en Delphi 7.

31 julio 2007

Tipos de variable para el manejo de caracteres

AnsiChar:

- Permite el almacenamiento de un carácter o un número entero.
- Valores comprendidos entre 0 y 255.
- Gasta un byte de memoria (8 bits).

AnsiString:

- Un tipo de dato que almacena una cadena de caracteres tipo AnsiChar.
- Cada carácter gasta un byte de memoria (8 bits), aunque la longitud de la cadena puede ser ilimitada.
- Al ser su contenido dinámico gastará tantos bytes como caracteres tenga la cadena en ese momento.
- El primer elemento comienza por [1].

ShortString:

- Variable para guardar un simple carácter o un número entero.
- Valores comprendidos entre 0 y 255.
- Al ser su contenido dinámico gastará tantos bytes como caracteres tenga la cadena en ese momento.
- Permite un máximo de 255 caracteres.
- El primer elemento comienza por [1].

String:

- Un tipo de dato que almacena una cadena de caracteres.
- Cuando se crea es tratado como AnsiString.
- La longitud es ilimitada siendo cada carácter de un byte (8 bits).
- El primer elemento comienza por [1].

WideChar:

- Almacena un carácter internacional.
- Puede guardar un carácter o un número entero entre 0 y 65535.
- Gasta 2 bytes de memoria (16 bits).

WideString:

- Un tipo de dato que almacena una cadena de caracteres tipo WideChar.
- Cada carácter gasta 2 bytes de memoria (16 bits), aunque la longitud de la cadena puede ser ilimitada.
- Al ser su contenido dinámico gastará tantos bytes como caracteres tenga la cadena en ese momento.
- El primer elemento comienza por [1].

Pruebas realizadas en Delphi 7.

30 julio 2007

Los tipos reales en Delphi

Currency:

- Tipo flotante de punto fijo con 4 decimales usado para valores financieros, minimizando así los errores de redondeo (recomendado para programas de gestión).
- Gasta 8 bytes de memoria (64 bits).

Double:

- Tipo flotante de uso general.
- Soporta hasta 15 dígitos de precisión.
- Gasta 8 bytes de memoria (64 bits).

Extended:

- Tipo flotante con alta capacidad y precisión.
- Soporta hasta 19 dígitos de precisión.
- Gasta 10 bytes de memoria (80 bits).

Real:

- Tipo flotante general obsoleto mantenido por compatibilidad hacia atrás (usar Double en su lugar).
- Soporta hasta 15 dígitos de precisión.
- Gasta 8 bytes de memoria (64 bits).

Real48:

- Tipo flotante general obsoleto mantenido por compatibilidad hacia atrás (usar Extended en su lugar).
- Soporta hasta 11 dígitos de precisión.
- Gasta 6 bytes de memoria (48 bits).

Single:

- El tipo flotante que tiene menos capacidad y precisión, aunque es el más rápido de procesar.
- Soporta hasta 7 dígitos de precisión.
- Gasta 4 bytes de memoria (32 bits).

Pruebas realizadas en Delphi 7.

Publicidad