Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Помогите сделать тип данных.... [D5, Win95/98]


TankMan ©   (2002-10-21 00:43:00) 

Эх.. кажется правильно сформулировал вопрос...
я вот мучаюсь, но так и не могу сделать...
Мне нужен тип, вобщем, вроде такого
type TMyType=array of record
Per1,Per2,Per3:TStrings;
end;
Только вот чтобы при описании
Peremennaya:TMyType;
Работать с записью можно было как с типом TStrings
,т.е. Peremennaya.Add(...) ну и соответственно
Peremennaya[0].Per1 или Per2...вот...
Я сколько не парился, ну не получается у меня.. пожалуйста, кому не особо сложно, подскажите как сделать такой тип. Буду очень признателен.


Рыжик   (2002-10-24 11:46:00) [1]

Так, начнём по-порядку:
> а почему это так, ведь по идее, во второй раз он должен
> добавить a[1].Per1[0] а не заменять a[0].per1[0]

Так и происходит, т.е во второй раз добавляется а[1].Per1[0]. Но обрати внимание на то, что TRecord - это "псевдорекорд", который на самом деле является классом! При добавлении в массив класса в действительности добавляется указатель, а не значение (как, например, было бы с каким-нибудь Integer или другим простым типом данных). Получается следующее: мы создали всего один объект TRecord, чего-то с ним сделали, занесли указательна него в первый элемент массива. Теперь вызываем метод этого же самого(!) объекта, и заносим во второй элемент массива. В результате имеем a[0]=a[1]. Т.е. когда мы делали rec.Clear;
rec.Per1.Add("2"); мы изменили сам объект, на который ссылается a[0]. Поскольку в a[0] находится указатель, а не сам объект, то и
результат ShowMessage(a[0].Per1[0]);//выдаст "2", а не "1"


> как тогда добавлять a[1]?

Именно так, как ты и делаешь в TankMan © (23.10.02 20:16)

> //rec.free не надо?

Нет. Если вызвать rec.Free сразу после добавления его в массив, а потом попытаться обратиться к этому эл-ту массива, то вы увидите, что a[0]=nil и a[0].Per1[0] вызовет ошибку. Уничтожением объекта rec занимается "массив" a.


> Ты говоришь, что не надо делать rec.free?
> А в каком месте TMyType его освобождает?

a.Free вызывает a.Destroy (если a<>nil). Дальше см. реализацию TMyType.Destroy:
destructor TMyType.Destroy;
var i:integer;
begin
for i:=0 to Length(FItems)-1 do
FItems[i].Free;
inherited;
end

Ну так вот. После всего вышесказанного, я советую разобраться, как всё это действует, а потом написать самостоятельно то, что требовалось. Очень полезно для развития ;)


TankMan   (2002-10-23 20:16:00) [2]

Погоди ка, а почему это так, ведь по идее, во второй раз он должен добавить a[1].Per1[0] а не заменять a[0].per1[0], как тогда добавлять a[1]?
a:=TMyType.Create;
rec:=TRecord.Create;//создали одну "запись"
rec.Per1.Add("1");//добавили одну строку
a.Add(rec);
//rec.free не надо?
rec:=TRecord.Create;
rec.Per1.Add("2");
a.Add(rec);
ShowMessage(a[0].Per1[0]);//выдаст "1", а не "2"?
ShowMessage(a[1].Per1[0]);//выдаст 2?
a.Free;//не надо делать Rec.Free;
Так чтоли?
Ты говоришь, что не надо делать rec.free?
А в каком месте TMyType его освобождает?
Я что-то не пойму?И если так, то почему?


Рыжик   (2002-10-23 11:53:00) [3]

Только будьте внимательны с элементами массива: при добавлении нужно каждый раз(!) создавать новый, а освобождением их занимается TMyType.
Например:
a:=TMyType.Create;
rec:=TRecord.Create;//создали одну "запись"
rec.Per1.Add("1");//добавили одну строку
a.Add(rec);
rec.Clear;
rec.Per1.Add("2");
a.Add(rec);
ShowMessage(a[0].Per1[0]);//выдаст "2", а не "1"
a.Free;//не надо делать Rec.Free;


TankMan   (2002-10-23 10:45:00) [4]

>>Рыжик
Ооо.. спасибо большое это - то, что мне нужно было... спасибо.


Рыжик   (2002-10-22 12:44:00) [5]

Типа того:
TRecord = class
public
Per1,Per2,Per3:TStrings;
constructor Create;
destructor Destroy; override;
end;

TMyType = class
private
FItems:array of TRecord;
function GetItems(Index: integer): TRecord;
procedure SetItems(Index: integer; const Value: TRecord);
public
property Items[Index:integer]:TRecord read GetItems write SetItems; default;
procedure Add(Item:TRecord);
procedure Delete(Index:integer);
destructor Destroy; override;
end;

implementation

procedure TMyType.Add(Item: TRecord);
var i:integer;
begin
i:=Length(FItems);
SetLength(FItems,i+1);
FItems[i]:=Item;
end;

procedure TMyType.Delete(Index: integer);
var i:integer;
rec:TRecord;
begin
rec:=FItems[Index];
for i:=Index+1 to High(FItems) do
FItems[i]:=FItems[i-1];
SetLength(FItems,Length(FItems)-1);
rec.Free;
end;

destructor TMyType.Destroy;
var i:integer;
begin
for i:=0 to Length(FItems)-1 do
FItems[i].Free;
inherited;
end;

function TMyType.GetItems(Index: integer): TRecord;
begin
Result:=FItems[Index];
end;

procedure TMyType.SetItems(Index: integer; const Value: TRecord);
begin
FItems[Index]:=Value;
end;

{ TRecord }

constructor TRecord.Create;
begin
inherited;
Per1:=TStringList.Create;
Per2:=TStringList.Create;
Per3:=TStringList.Create;
end;

destructor TRecord.Destroy;
begin
Per1.Free;
Per2.Free;
Per3.Free;
inherited;
end;


Пример:

procedure TForm1.Button1Click(Sender: TObject);
var a:TMyType;
rec:TRecord;
begin
a:=TMyType.Create;
rec:=TRecord.Create;
rec.Per1.Add("tra-la-la");
a.Add(rec);
ShowMessage(a[0].Per1[0]);
a.Free;
end;


TankMan   (2002-10-21 21:24:00) [6]

Да но как я понимаю это просто массив строк, а мне нужен массив записей, и именно записей с 3 полями TStrings... может я чего недопонимаю?


Viktor Kushnir   (2002-10-21 08:38:00) [7]

Вот кусечек хелпа к Дельфи на тему Array properties

type

TStringArray = class
public
property Strings[Index: Integer]: string ...; default;
...
end;

Ну естественно, что методы SetString И GetString для записи и чтения из массива, тбе надо будет описать самому.


TankMan   (2002-10-21 01:54:00) [8]

А может класс какой переопределить чуток и сделать такой, который нужно? Только вот проблема, я так и не смог разобраться, как сделать так, как сделано в типе TStrings. :(


TankMan   (2002-10-21 01:51:00) [9]

>Peremennaya.Add(...) это только с классами и вроде в Д7 можно
Ну а как-то же реализует это TStrings?


Anatoly Podgorestky   (2002-10-21 00:58:00) [10]

Смутно объясняешь
Peremennaya.Add(...) это только с классами и вроде в Д7 можно
Peremennaya[0].Per1 это ты уже описал, только выделяй место в массиве с помощью SetLength(Peremennaya,N)
Посмотри в хелпе разделы по Record и Dynamic Arrays
Книги тоже не помешают


Наверх

Титульная страница Поиск, карта сайта Написать письмо