Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.14;
Скачать: CL | DM;

Вниз

Сравнение записей   Найти похожие ветки 

 
Wistler ©   (2005-07-24 11:02) [0]

Доброго времени суток. Аж стыдно за такой вопрос, но заклинило.

Есть 2 переменные типа record. Необходимо сравнить их на равенство. Сравнивать все поля не красиво и глупо.

Заранее спасибо.


 
Плохиш ©   (2005-07-24 11:11) [1]

В цикле по всем полям, сравнивая соответствующие.


 
Leonid Troyanovsky ©   (2005-07-24 11:17) [2]


> Wistler ©   (24.07.05 11:02)  
> Доброго времени суток. Аж стыдно за такой вопрос, но заклинило.
>
> Есть 2 переменные типа record. Необходимо сравнить их на
> равенство. Сравнивать все поля не красиво и глупо.


Сравниваешь SizeOf, а затем CompareMem.
Можно и без SizeOf, если они однотипны.

--
Regards, LVT.


 
Lamer@fools.ua ©   (2005-07-24 11:34) [3]

>>Wistler ©   (24.07.05 11:02)

Какого типа поля у записи?


 
Anatoly Podgoretsky ©   (2005-07-24 11:36) [4]

Чего же глупого, кроме то в общем иначе и не возможно. Как сравнить две записи, в которых динамические типы, например string. Кроме того сравнение далеко не тривиально как кажется, типы могут быть очень сложные


 
Wistler ©   (2005-07-24 11:39) [5]


> Сравниваешь SizeOf, а затем CompareMem.
> Можно и без SizeOf, если они однотипны


CompareMem сравнивает данные в динамической памяти, а у меня переменные описаны:
 Type  
         TV:record
           ...
         end;
        V1, V2:TV;


Можно конечно завести 2 дополнительные переменные типа ^TV, и использовать CompareMem, но хотелось напрямую сравнить 2 переменные.


 
Wistler ©   (2005-07-24 11:41) [6]


> Какого типа поля у записи?


String и запись в которой тоже String.


 
Гаврила ©   (2005-07-24 11:52) [7]


>  [5] Wistler ©



> CompareMem сравнивает данные в динамической памяти, а у
> меня переменные описаны:


Что такое "динамической памяти"??


 
Гаврила ©   (2005-07-24 11:53) [8]


> String и запись в которой тоже String.


Кром как "сравнение по полям" ничего не получится


 
Wistler ©   (2005-07-24 11:54) [9]


> Что такое "динамической памяти"??


В функцию надо передать тип Pointer, а не TV!


 
Гаврила ©   (2005-07-24 12:12) [10]


> В функцию надо передать тип Pointer, а не TV!


> Type  
>          TV:record
>            ...
>          end;
>         V1, V2:TV;


Это делается так:
CompareMem(@V1, @V2, ...)
но ,если в записи указатели (huge стринг - это указатель), то, соответственно, не получится, так что - сравнивай по полям


 
Leonid Troyanovsky ©   (2005-07-24 12:13) [11]


> Wistler ©   (24.07.05 11:54) [9]
>
> > Что такое "динамической памяти"??

> В функцию надо передать тип Pointer, а не TV!


Дык, передай адрес TV.
Только, оно не решит твоей проблемы, как коллеги уже объяснили.
Если надо сравнивать строки, то record не лучшее для них место. Т.е., или их в TStringList или все в TObject с специализированными методами сравнения.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-07-24 12:18) [12]


> Гаврила ©   (24.07.05 12:12) [10]

> но ,если в записи указатели (huge стринг - это указатель),



Почему это не получится?
Если строка тажа самая (вплоть до копий - huge ;),
то - изволь.

Так, что сравнение сравнению - рознь.

--
Regards, LVT.


 
Wistler ©   (2005-07-24 12:25) [13]

Написал свою функцию сравнения, в которой сравниавю по полям, так что если изменится структура записи, придётся менять и функции. И как оказалось интересная тема, как написать универсальную функцию сравнения записей.


 
begin...end ©   (2005-07-24 12:52) [14]

Тело длинной строки частью записи не является. В записи содержится указатель на это тело. Поэтому, строго говоря, для решения задачи сравнения записей вполне подойдёт [2].


 
msguns ©   (2005-07-24 12:56) [15]

Не совсем понятно, зачем нужно такое сравнение. Если запись хранит информацию о каком-либо объекте, то у этого объекта должно быть поле, однозначно его идентифицирующее (что-то типа ID), если же один и тот же объект (вернее, запись с его реквизитами-полями) хранится в двух списках - то это что-то, имхо, в голове ;)


 
Anatoly Podgoretsky ©   (2005-07-24 12:57) [16]

Что болтать, выдай критерий равенства двух записей с указательными типами, тогда будет предмет для разговора.


 
begin...end ©   (2005-07-24 12:58) [17]

> Anatoly Podgoretsky ©   (24.07.05 12:57) [16]

Вы это кому?


 
Leonid Troyanovsky ©   (2005-07-24 13:05) [18]


> begin...end ©   (24.07.05 12:58) [17]
> > Anatoly Podgoretsky ©   (24.07.05 12:57) [16]
>
> Вы это кому?


Тому, кто оный критерий утаил, IMHO.

--
Regards, LVT.


 
Essence   (2005-07-24 15:23) [19]

Записи, которые содержат тип string и, разумеется, не динамические типы сравниваются корректно.
 Записи, содержащие в себе динамический массив, не хотят корректно сравниваться. Понятно - там сравниваются адреса.
А записи, содержащие тип Pointer, вобще при сравнении вызывают ругань компилера:)
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Memo1: TMemo;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private-Deklarationen }
 public
   { Public-Deklarationen }
 end;

 TTestArray = array of Integer;

 TTest = record
   i: Integer;
   s: String;
 end;

 TTest1 = record
   i: Integer;
   testArr: TTestArray;
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}
function ListenVergleichen1(t1, t2: TTest):String;
begin
 Result := "t1 ist ungleich t2";
 if SizeOf(t1) = SizeOf(t2) then
   if CompareMem(@t1,@t2, SizeOf(t1)) then
     Result := "t1 ist gleich t2";
end;

function ListenVergleichen2(t3, t4: TTest1):String;
begin
 Result := "t3 ist ungleich t4";
 if SizeOf(t3) = SizeOf(t4) then
   if CompareMem(@t3,@t4, SizeOf(t3)) then
     Result := "t3 ist gleich t4";
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Test1: TTest;
 Test2: TTest;
 Test3: TTest1;
 Test4: TTest1;
 i: Integer;
begin
 Memo1.Clear;
 Test1.i := 1000000;
 Test1.s := "bla-bla-bla-bla-bla-bla-bla-bla";

 Test2.i := 1000000;
 Test2.s := "bla-bla-bla-bla-bla-bla-bla-bla";

 Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
 //-------------------------------------------------------
 Test1.i := 1;
 Test1.s := "bla-bla-bla-bla-bla-bla-bla-bla";

 Test2.i := 1000000;
 Test2.s := "bla-bla-bla-bla-bla-bla-bla-bla";

 Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
 //-------------------------------------------------------
 Test1.i := 1;
 Test1.s := "bla-bla-bla-bla-bla-bla-bla-bla";

 Test2.i := 1;
 Test2.s := "bla ein Mal";

 Memo1.Lines.Add(ListenVergleichen1(Test1,Test2));
 //-------------------------------------------------------

 Test3.i := 10;
 SetLength(Test3.testArr,100);
 SetLength(Test4.testArr,100);
 for i := Low(Test3.testArr) to High(Test3.testArr) do
 begin
   Test3.testArr[i] := i;
   Test4.testArr[i] := i;
 end;

 Memo1.Lines.Add(ListenVergleichen2(Test3,Test4));
 //-------------------------------------------------------

 Test3.i := 10;
 SetLength(Test3.testArr,10);
 for i := Low(Test3.testArr) to High(Test3.testArr) do
   Test3.testArr[i] := i;

 Test4.i := 10;
 SetLength(Test4.testArr,1000);
 for i := Low(Test4.testArr) to High(Test4.testArr) do
   Test4.testArr[i] := i;

 Memo1.Lines.Add(ListenVergleichen2(Test3,Test4));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Close;
end;

end.


 
begin...end ©   (2005-07-24 15:49) [20]

> Essence   (24.07.05 15:23) [19]

Ваши выводы неверны. Потому что эксперимент поставлен неправильно.


 
Essence   (2005-07-24 15:52) [21]


> begin...end ©   (24.07.05 15:49) [20]

А как правильно?


 
Antonn ©   (2005-07-24 16:05) [22]

Essence   (24.07.05 15:23) [19]
TTest = record
  i: Integer;
  s: String;
end;

ох, не нравятся мне стринги в рекордах...


 
Essence   (2005-07-24 16:09) [23]

Чем не нравятся? Если в файл сохранять, то согласен. А чем ещё?


 
Antonn ©   (2005-07-24 16:11) [24]

Essence   (24.07.05 16:09) [23]
в поток не сохраняются... мне этого достаточно.


 
Essence   (2005-07-24 16:13) [25]


> Antonn ©   (24.07.05 16:11) [24]

Ну тогда String[255]:)

Ето же был тест на сравнение.


 
begin...end ©   (2005-07-24 16:15) [26]

> Essence   (24.07.05 15:52) [21]

Не будем пока касаться записей, содержащих поля типа Pointer или динамический массив, а ограничимся записями с полем string (AnsiString).

type
 TRec = packed record
   I: Integer;
   S: string;
 end;

procedure TForm1.Button1Click(Sender: TObject);
var
 R1, R2: TRec;
begin
 R1.I := 1;
 R1.S := "abc";
 R2.I := 1;
 R2.S := "abc";
 // Убедимся, что поля R1.S и R2.S указывают на одинаковые тела строк
 ShowMessageFmt("%s %s", [R1.S, R2.S]);
 // Сравнение записей
 if CompareMem(@R1, @R2, sizeof(TRec)) then
   ShowMessage("Содержимое записей одинаково")
end.


Тест показал, что содержимое записей R1 и R2 одинаково (о чём Вы и говорили). Теперь немного изменим тест:

procedure TForm1.Button1Click(Sender: TObject);
var
 R1, R2: TRec;
begin
 R1.I := 1;
 R1.S := "abc";
 R2.I := 1;
 R2.S := Copy(R1.S, 1, Length(R1.S));
 // Убедимся, что поля R1.S и R2.S указывают на одинаковые тела строк
 ShowMessageFmt("%s %s", [R1.S, R2.S]);
 // Сравнение записей
 if CompareMem(@R1, @R2, sizeof(TRec)) then
   ShowMessage("Содержимое записей одинаково")
end.


На этот раз тест показал, что содержимое R1 и R2 различно. Как же так -- строки одинаковые, а записи разные?
Какие есть предположения?


 
Essence   (2005-07-24 17:00) [27]


> begin...end ©   (24.07.05 16:15) [26]

Выходит здесь тоже сравниваются указатели на строку?


 
begin...end ©   (2005-07-24 17:04) [28]

> Essence   (24.07.05 17:00) [27]

Разумеется. О чём и было сказано в [14].


 
Essence   (2005-07-24 17:16) [29]

Да уж! Шкряб-шкряб озадачено по затылоку:)

К сожалению подумал, что явно не присваиваю значение одной переменной другой, а компилер, собака такая сам это за меня проделал. Раз присваиваю одинаковые значения, значит равносильно, что присвоить значение одной переменной другой.
 Вляпался:(


 
evvcom ©   (2005-07-25 09:16) [30]

Что-то не пойму, Wistler и Essence одно лицо иль нет? Ладно, неважно. Теперь по теме.
Если есть необходимость/желание написать универсальную функцию сравнения, надо передавать в нее кроме указателей на запись, также их TypeInfo. А дальше по TypeInfo разруливать. Примеры в System._New/_Dispose и связанных с ними функциях. Тут уж, батенька, без асма не обойтись.


 
Essence   (2005-07-25 09:59) [31]


> evvcom ©   (25.07.05 09:16) [30]
> Что-то не пойму, Wistler и Essence одно лицо иль нет?

Нет. У нас скорее разные лица:)

Просто подумалось, что, как и говорил begin...end © - сравниваться будут указатели. Решил проверить и ввёл себя в заблуждение. Захотелось на халяву, с помощью одной фукции CompareMem, завалить льва:)


 
evvcom ©   (2005-07-25 11:06) [32]


> сравниваться будут указатели

Где сравниваться? Если в CompareMem, то да. Она один к одному сравнит и усе, не различая что там указатели или данные. Ей по фиг. А если сравнивать надо именно данные, то одной CompareMem здесь не обойтись. Короче нужен ответ на
> Anatoly Podgoretsky ©   (24.07.05 12:57) [16]
> Что болтать, выдай критерий равенства двух записей с указательными
> типами, тогда будет предмет для разговора.


 
Essence   (2005-07-25 11:42) [33]


> evvcom ©   (25.07.05 11:06) [32]
>
> > сравниваться будут указатели
>
> Где сравниваться? Если в CompareMem, то да.

Так, я о том же:)
> А если сравнивать надо именно данные, то одной CompareMem
> здесь не обойтись.

Да, да, да. Никто не спорит, за исключением некоторой поправки: поля типов Integer и Real - тоже относятся к данным:)



Страницы: 1 вся ветка

Текущий архив: 2005.08.14;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.033 c
1-1122018379
WondeRu
2005-07-22 11:46
2005.08.14
Перевод в режим редактирования элеманта TTreeView


4-1117514872
Logo
2005-05-31 08:47
2005.08.14
WriteConsoleInput


1-1122545825
Ирина
2005-07-28 14:17
2005.08.14
Верхний регистр


4-1118750333
Константин_1558
2005-06-14 15:58
2005.08.14
Нужно открыть в проводнике диск CDRom а. Прошу помощи!


1-1121955070
alexander_ua
2005-07-21 18:11
2005.08.14
Массив из 5 и выше млн. элементов типа single-переполнение стека