PDA

Ver la Versión Completa : Buscar en una estructura record


fcios
06-04-2018, 16:24:04
Hola, como puedo armar una función para que me sirva para buscar en distintas estructuras Record ?
(por lo menos no ví ninguna que lo haga) :(

por ejemplo tengo

TProvincias = record
Provin : string;
Importe : currency;
Descri : string;
end;

TIvas = record
Codigo : string;
Descri : string;
Porcentaje : currency;
end;

TaProvincias = array of TProvincias;
TaIvas = array of TIvas;

// luego defino las variables
aProvincias : TaProvincias;
aIvas : TIvas;


:confused: y acá el problema de como buscar, este es un simple ejemplo que no funciona, cualquier ayuda es bien venida

function BuscarEnRecord(aRecord:array of TObject; Campo:variant; Buscar:Variant):integer;
///////////////////////////////////////////////////
// aRecord = array donde buscar
// Campo = campo del record donde buscar
// Buscar = string o número a buscar
///////////////////////////////////////////////////
var i:integer;
begin
for i:=0 to Length(aRecord) do begin
if aRecord[i].Campo = Buscar then begin
Result := i;
Exit;
end;
end;
Result := -1; // no lo encontró
end;



Muchas Gracias

ecfisa
06-04-2018, 16:59:41
Hola.

¿ En cuál versión de Delphi estas trabajando ?

Saludos :)

fcios
06-04-2018, 18:45:43
usando delphi 7

Caminante
06-04-2018, 18:59:02
Código Delphi [-] (http://www.clubdelphi.com/foros/#) if aRecord[i].Campo = Buscar then begin



Hola

Veo que en el parametro campo envias el nombre del campo que quieres buscar. La verdad eso no lo veo viable y no creo que alguna version de delphi la acepte.

Tal vez usando RTTI podrias acceder a cualquier campo del record pero de esa forma no lo creo.

Se que no es de ayuda pero creo que tendrias que buscar otra manera. Haber si alguien mas nos saca de la duda.

Saludos

ecfisa
06-04-2018, 19:19:06
Hola.
usando delphi 7
Por eso era mi pregunta, desde Delphi 7 no veo posible que accedas a los campos de un record.

Si fuese Delphi 2010 o una versión superior, podrías hacerlo usando RTTI como se muestra en este enlace: List the Record's element\fields (https://stackoverflow.com/questions/4394091/list-the-records-element-fields)

Saludos :)

fcios
06-04-2018, 20:16:46
y hay alguna forma de buscar siempre en el primer campo ?

escafandra
09-04-2018, 13:55:34
y hay alguna forma de buscar siempre en el primer campo ?

Si sabes el tipo, si.

Mira este ejemplo:

type
TR = record
UNO: integer;
DOS: CHAR;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
V: TR;
begin
V.UNO:= 1;
Edit1.Text:= IntToStr(PInteger(@V)^);
end;



Saludos.

fcios
12-04-2018, 21:46:56
Muchas gracias a todos, lo de escafandra anda ok

pero quiero poder recibir cualquier tipo record, por ejemplo

type
TR = record
UNO: string; // integer;
DOS: CHAR;
end;

TR3 = record
campo1: string;
DOS: CHAR;
end;

aTR = array of TR;
aTR3 = array of TR3;


// como debo definir aRecord para poder recibir cualquier tipo de array record ?, (mi mira a los punteros está muy desviada) Muchas gracias


function BuscarEnRecord2(aRecord: record^; Buscar:string):integer;
///////////////////////////////////////////////////
// aRecord = array donde buscar
// Buscar = string
///////////////////////////////////////////////////
var i:integer;
// s:string;
begin
for i:=0 to Length(aRecord) -1 do begin
// s := PString(@aRecord[i])^;
// if s = Buscar then begin
if PString(@aRecord[i])^ = Buscar then begin
Result := i;
Exit;
end;
end;
Result := -1; // no lo encontró
end;

escafandra
12-04-2018, 22:22:45
Lo que pretendes tiene solución con punteros, pero el primer campo de cada estructure (record) debe ser del mismo tipo, en este caso String. No nos importa como se llame, lo podemos localizar.

Basado en tu código, podemos definir el parámetro aRecord como un array de punteros. Cada puntero apuntará a un elemento de una estructura.


type
TR = record
UNO: string; // integer;
DOS: CHAR;
end;
PTR = ^TR;

TR3 = record
campo1: string;
DOS: CHAR;
end;

aTR = array of TR;
aTR3 = array of TR3;
PaTR = ^aTR;

TRecods = array of pointer;
PPString = ^PString;

var
Form1: TForm1;

implementation

{$R *.dfm}


function BuscarEnRecord2(aRecord: TRecods; Buscar:string):integer;
var i:integer;
begin
for i:=0 to Length(aRecord) -1 do begin
if (PPString(@aRecord[i])^)^ = Buscar then begin
Result := i;
Exit;
end;
end;
Result := -1; // no lo encontró
end;

procedure TForm1.Button1Click(Sender: TObject);
var
R0,R1,R2: TR;
PR: TRecods;
Index: integer;
begin
// Preparamos el array de punteros... como quieras...
SetLength(PR, 3);
R0.UNO:= 'Hola';
R1.UNO:= 'Caracola';
R2.UNO:= 'Adios';
PR[0]:= @R0;
PR[1]:= @R1;
PR[2]:= @R2;

// Buscamos
Index:= BuscarEnRecord2(PR, 'Adios');
if Index >= 0 then
ShowMessage('Eureca ' + IntToStr(Index));
end;



Saludos

fcios
17-04-2018, 15:16:58
:) gracias escafandra !!

fcios
04-08-2018, 00:51:10
Una ayuda más por favor
como busco en el primer campo recorriendo un array,
muestro con ERROR donde recibo error al compilar, gracias de antemano



type
TR = record
UNO: string; // integer;
DOS: CHAR;
end;
PTR = ^TR;

TR3 = record
campo1: string;
DOS: CHAR;
end;

aTR = array of TR;
aTR3 = array of TR3;
PaTR = ^aTR;

//TRecods = array of pointer;
PPString = ^PString;

TRecord2 = pointer; //array of pointer;


function BuscarEnRecord4(aRecord: TRecord2; Buscar:string):integer;
var i:integer;
s:string;
begin
i := Length(aRecord); // :confused: ERROR Incompatible Types
for i:=0 to Length(aRecord) -1 do begin // :confused: ERROR Incompatible Types
s := (PPString(@aRecord[i])^)^; // :confused: ERROR Array typed required
if (PPString(@aRecord[i])^)^ = Buscar then begin // :confused: ERROR Array typed required
Result := i;
Exit;
end;
end;
Result := -1; // no lo encontró
end;

procedure TForm1.BitBtn4Click(Sender: TObject);
var
a1: aTR;
a2: aTR3;
Index: integer;

PR2 :TRecord2;
begin
SetLength(a1,3); // seteo a 3 items
a1[0].UNO := 'Hola';
a1[1].UNO := 'Carola';
a1[2].UNO := 'Adios';

SetLength(a2,3); // seteo a 3 items
a2[0].campo1 := 'Hola2';
a2[1].campo1 := 'Carola2';
a2[2].campo1 := 'Adios2';

// Buscamos
PR2 := @a1;
Index:= BuscarEnRecord4(PR2{@a1}, 'Adios');
if Index >= 0 then
ShowMessage('Eureca ' + IntToStr(Index));

Index:= BuscarEnRecord4(@a2, 'Adios2');
if Index >= 0 then
ShowMessage('Eureca ' + IntToStr(Index));

end;

ecfisa
04-08-2018, 23:18:30
Hola.

El error se produce por que estas enviando a la la función Length() (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_Length.html) un valor de tipo TRecord2 y esta sólo admite los tipos string o array.

Si deseas obtener el tamaño en bytes del argumento "aRecord" deberías usar la función SizeOf() (http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.SizeOf).

Saludos :)

fcios
06-08-2018, 21:22:04
ok, si yo defino

SetLength(a1,3); // seteo a 3 items
a1[0].UNO := 'Hola';
a1[1].UNO := 'Carola';
a1[2].UNO := 'Adios';


como hago para saber que tengo que recorrer 3 items dentro de la funcion ?
y como puedo obtener el primer campo, que también me da error al compilar
s := (PPString(@aRecord[i])^)^; // ERROR Array typed required

muchas Gracias

ecfisa
06-08-2018, 22:37:26
Hola.

como hago para saber que tengo que recorrer 3 items dentro de la funcion ?
Sea "a1" un arreglo estático o dinámico de elementos de cualquier tipo, podes conocer su capacidad mediante la función y las cotas inferior y superior con las funciones [url=http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_Low.html]Low() (]Length()[/url) y High() (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_High.html) respectivamente.

vg.r.:

...
var
v1: array[1..10] of Pointer;
v2: array of PChar;
begin
ShowMessageFmt('%d - %d - %d',[Length(v1), Low(v1), High(v1)]);
// mostrará: 10 - 1 - 10

SetLength(v2, 10);
ShowMessageFmt('%d - %d - %d',[Length(v2), Low(v2), High(v2)]);
// mostrará: 10 - 0 - 9 (indexación base-cero)


y como puedo obtener el primer campo, que también me da error al compilar
Revisa el tipo de "aRecord". Fijate que escafandra en su código lo declara como TRecods (TRecods = array of pointer)

Saludos :)

fcios
06-08-2018, 23:23:31
ok, en lo de Escafandra busca en el primer campo de CADA array si mando varios arrays, eso está ok

Yo quiero buscar en el primer campo dentro del único array que le mando, por eso definí
BitBtn4Click que llama a
function BuscarEnRecord4(aRecord: TRecord2; Buscar:string):integer;

y lo que me cuesta, entra varias cosas..., es poder definir aRecord de un tipo puntero que pueda apuntar a cualquier tipo de TRecord
por eso arme el ejemplo de
BitBtn4Click que llama a
function BuscarEnRecord4(aRecord: TRecord2; Buscar:string):integer;

GRACIAS otra vez

ecfisa
07-08-2018, 17:24:24
ok, en lo de Escafandra busca en el primer campo de CADA array si mando varios arrays, eso está ok

Yo quiero buscar en el primer campo dentro del único array que le mando, por eso definí
BitBtn4Click que llama a
function BuscarEnRecord4(aRecord: TRecord2; Buscar:string):integer;

y lo que me cuesta, entra varias cosas..., es poder definir aRecord de un tipo puntero que pueda apuntar a cualquier tipo de TRecord
...
Pero es que ya está... aRecord esta definida de tipo TRecord2 que es un Pointer, es decir que este código de ejemplo,

...
type
TRecord2 = Pointer;

function foo(aRecord: Pointer; cad: string): Boolean; // (TRecord2 ó Pointer a gusto)
begin
ShowMessage(PAnsiString(aRecord)^);
//...
end;

procedure TForm1.Button1Click(Sender: TObject);
var
r1 : record
a: string;
b: Integer;
end;

r2 : record
c: string;
d: Double;
end;
begin
r1.a := 'Hola';
r1.b := 1;

r2.c := 'mundo';
r2.d := 3.1416;

foo(@r1, 'Hola');
foo(@r2, 'mundo');
end;

funciona sin problemas siempre y cuando el primer campo de los Records sea del mismo tipo...

Saludos :)

fcios
07-08-2018, 22:51:14
ok, eso funciona bárbaro... pero r1 no es un array

serias tan amablede hacerlo funcionar definiendo un array como por ejemplo

SetLength(a1,3); // seteo a 3 items
a1[0].UNO := 'Hola';
a1[1].UNO := 'Carola';
a1[2].UNO := 'Adios';

que está en el ejemplo BuscarEnRecord4 y BitBtn4Click que es donde me dan los errores,
yo quiero poder recorrer el array que le mande

Gracias