Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.014 c
3-1120824311
yk
2005-07-08 16:05
2005.08.14
Как отловить исключение в ХП?


1-1122323177
dRake
2005-07-26 00:26
2005.08.14
Подскажите функцию :)


3-1120464571
ANB
2005-07-04 12:09
2005.08.14
Как определить, что выполнение оператора SQL закончилось (Oracle)


1-1122280587
LLi kn par
2005-07-25 12:36
2005.08.14
Как сд-ть так чтобы ф-лы бфли скрытыми, системными и т. д.


1-1122188478
tttyu
2005-07-24 11:01
2005.08.14
как получить текущую позицию ScrollBar а в Richedit?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский