Форум: "Основная";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];
ВнизКак вставить элемент внутрь массива рекордов ? Найти похожие ветки
← →
Кто---то © (2004-11-15 01:40) [0]Задумал написать функцию, которая бы вставляла элементы в массивы ЛЮБЫХ рекордов, но запнулся на том, как её озаглавить :
function InsertRec(anArray : array of ... ; Index : Integer): Boolean;
array of что ? array of record не получается. А как быть ? Мне же надо, чтобы не под какую то конретную рекорду, а чтобы универсально было. Как же написать тогда ?
Когда мы пишем :
function InsertRec(var anArray : array of ...
Мы разве не просто ссылку на массив передаём ? И если ссылку, то какая Дельфи разница на массив чего ведёт эта ссылка ?
А если передаём не только ссылку, то что именно ещё передаём ?
Подробности см в теме :
http://delphimaster.net/view/1-1100211902/
Если тема закрыта потому, что этот вопрос слишком сложен для мастеров - то так и скажите, чтобы я зря не спрашивал. Всего не знает никто, кроме Бога, ничего в этом постыдного нет.
← →
GuAV © (2004-11-15 02:06) [1]Кто---то © (15.11.04 1:40)
Когда мы пишем :
function InsertRec(var anArray : array of ...
Мы разве не просто ссылку на массив передаём ?
не совсем. открытый массив всегда передаётся двумя параметрами: ссылкой на первый элемент и количеством элементов минус один. и кстати на самом деле программера не должно волновать как он передается.
Кстати учитывая сабж от открытых массивов прийдётся вообще отказаться, т.к. изменить размер отрытого массива внутри процедуры невозможно, т.к. статический массив тоже может быть актуальным параметром, там где формальный открытый массив.
Динамические массивы тоже не подойдут, т.к. в этом случае типы формального и фактического параметра должны совпадать, что не позволит реализовать универсальность.
в случае классов можно всё же наверное передавать untyped параметр или указатель на массив, приводя его в процедуре к дин. масиву указателей.
в случае именно записей всё гораздо сложнее...
← →
Кто---то © (2004-11-15 02:31) [2]
> GuAV © (15.11.04 02:06) [1]
Вот моя функция :function InsertRec(var anArray : array (??? Что сюда вписать ???) ; Index : Integer): Boolean;
var
i, j : Integer;
begin
j := Length(anArray);
Result := (Index > 0) and (Index < j));
if not Result then break;
SetLength(anArray, j +1);
for i := j +1 downto Index +1 do anArray[i] := anArray[i -1];
end;
Дело за малым. Угадать слово. Или несколько. :) Как бы ты решил этот кроссворд ?
← →
GuAV © (2004-11-15 02:34) [3]I say again:
от открытых массивов прийдётся вообще отказаться, т.к. изменить размер отрытого массива внутри процедуры невозможно, т.к. статический массив тоже может быть актуальным параметром, там где формальный открытый массив.
Для справки: array of xxx в параметре - это и есть "открытый массив".
PS: рекомендую ещё раз перечитать [1].
← →
Кто---то © (2004-11-15 02:41) [4]
> GuAV © (15.11.04 02:34) [3]
> PS: рекомендую ещё раз перечитать [1].
Но мне нужно решение в рамках Дельфи. Ответ "отказаться" - не подходит.
Макросов в Дельфи вроде нету. По крайней мере раньше небыло. :)
Использовать процедуру или функцию - нельзя. Как же быть ? Каждый раз вписывать этот блок из пяти строчек что ли ? Это неудобно. Хотелось бы этого избежать.
← →
dhdd (2004-11-15 02:45) [5]function InsertRec(anArray:pointer;index,recsize:integer):Boolean; -> А чего вставлять? и нужна ли функция.
function InsertRec(anArray,rec:pointer;index,recsize:integer):Boolean;
В массив по адресу anArray со смещением index*recsize помещаем содержимое rec размером recsize: дальше по ассемблеру для оптима.
← →
GuAV © (2004-11-15 02:45) [6]О чём вообще речь ?
если о type TRecord=class ..., как в той ветке то реализовать в принципе можно.
в случае же type TMyRec=record... весьма затруднительно... проще согласится с тем что никак.
← →
Кто---то © (2004-11-15 03:10) [7]
> dhdd (15.11.04 02:45) [5]
> function InsertRec
> (anArray,rec:pointer;index,recsize:integer):Boolean;
> В массив по адресу anArray со смещением index*recsize помещаем
> содержимое rec размером recsize: дальше по ассемблеру для
> оптима.
Честно сказать - не понял.
Прежде чем вставлять что-либо, массив надо раздвинуть в определённой точке. Вот мы и пытаемся.
> GuAV © (15.11.04 02:45) [6]
> О чём вообще речь ?
> если о type TRecord=class ..., как в той ветке то реализовать
> в принципе можно.
Есть массив рекордов причём тут классы ? Для чего эти переделки и навороты на ровном месте ?
← →
dhdd (2004-11-15 03:25) [8]>Кто---то: массив надо раздвинуть
Честно сказать - не понял.
← →
Кто---то © (2004-11-15 03:45) [9]
> dhdd (15.11.04 03:25) [8]
> >Кто---то: массив надо раздвинуть
> Честно сказать - не понял.
Ну скажем массив из 10 рекордов. Чтобы вставить новый рекорд на место третьего, нужно увеличить количество рекордов до 11 и сдвинуть все начиная с третьего, чтобы освободить место куда вставить новый рекорд.
← →
dhdd (2004-11-15 04:02) [10]Ну и смещай его через move:
всё копируй (move) в новый массив (заново GetMem+1).
с 3 до 11 копируй по индексу +1 и вставляй " новый рекорд на место третьего".
← →
Кто---то © (2004-11-15 04:15) [11]
> dhdd (15.11.04 04:02) [10]
> Ну и смещай его через move:
> всё копируй (move) в новый массив (заново GetMem+1).
> с 3 до 11 копируй по индексу +1 и вставляй " новый рекорд
> на место третьего".
Можно пример кода ?
← →
Verg © (2004-11-15 06:22) [12]
> Дело за малым. Угадать слово. Или несколько. :) Как бы ты
> решил этот кроссворд ?
Никак. По крайней мере пока.
> Мы разве не просто ссылку на массив передаём ? И если ссылку,
> то какая Дельфи разница на массив чего ведёт эта ссылка
> ?
Да, формально передается ссылка. Но информация о типе хранимых элементов там те лежит. Там есть только счетчик ссылок и длина массива (не размер в байтах, а сколько элементов).
Например, дин. массив вообще может быть равен nil, что означает пустой массив (length = 0).
Информацию же о типе хранимых в массиве элементах компилеру нужно знать явно.
Зная только pointer равный дин. массиву узнать тип хранимого элемента невозможно.
А тип нужно знать обязательно, т.к. это может быть и дин. массив и рекорд, содержащий строки, дин. массивы, интерфейсы и проч. нескалярные структуры. Т.о. процесс вставки/удаления элементов из такого массива может быть намного сложней, чем простой realloc и move...
← →
Кто---то © (2004-11-15 07:01) [13]
> Verg © (15.11.04 06:22) [12]
> Т.о. процесс вставки/удаления элементов из такого массива
> может быть намного сложней, чем простой realloc и move...
А какой ? Или какое тут решение самое простое ?
← →
Verg © (2004-11-15 07:38) [14]
> А какой ? Или какое тут решение самое простое ?
Решение чего? Тут - это где?
Я вроде тебе ясно сказал - невозможно работать с динамическим массивом не указав явно типа хранящихся в нем элементов.
← →
Кто---то © (2004-11-15 07:53) [15]
> Verg © (15.11.04 07:38) [14]
> Я вроде тебе ясно сказал - невозможно работать с динамическим
> массивом не указав явно типа хранящихся в нем элементов.
Пусть указав.
В постинге [2] есть функция. Вы можете её передалать так, чтобы она заработала ?
← →
ЮЮ © (2004-11-15 08:11) [16]Type
TSomeArray: array of <SomeType>
function InsertRec(var Array : TSomeArray; Index : Integer): Boolean;
← →
KilkennyCat © (2004-11-15 09:34) [17]
> Verg © (15.11.04 07:38) [14]
возможно, глупость скажу... а если рассматривать массив, как область памяти, элемент массива аналогично, то разве мы что-либо нарушим в структуре, если одну область к памяти прибавим к другой? И важна ли нам в данном случае структура?
Я к сожалению, не силен в истинной реализации работы памяти, все время представляю ее чем-то вроде файла...
← →
ЮЮ © (2004-11-15 09:38) [18]>KilkennyCat © (15.11.04 09:34) [17]
И колько памяти занимает элемент массива неизвестного типа?
← →
KilkennyCat © (2004-11-15 09:45) [19]
> ЮЮ © (15.11.04 09:38) [18]
разве это невозможно узнать?
← →
ЮЮ © (2004-11-15 09:53) [20]Как, если тип не известен? Зачем, если синтаксис Delphi все равно не позволит написать и использоваь такую функцию
← →
KilkennyCat © (2004-11-15 09:57) [21]
> ЮЮ © (15.11.04 09:53) [20]
стоп... тип же известен. как я понял, имеется ввиду проблема создания процедуры, для которой типы неизвестны, но не для всей программы в целом. и если мы передаем ей данные о том, где хранится массив, где хранится будущий элемент, то можем ли мы слепить их?
← →
Verg © (2004-11-15 10:12) [22]
> 17] KilkennyCat © (15.11.04 09:34)
>
> > Verg © (15.11.04 07:38) [14]
>
>
> возможно, глупость скажу... а если рассматривать массив,
> как область памяти, элемент массива аналогично, то разве
> мы что-либо нарушим в структуре, если одну область к памяти
> прибавим к другой? И важна ли нам в данном случае структура?
> Я к сожалению, не силен в истинной реализации работы памяти,
> все время представляю ее чем-то вроде файла...
Да как угодно.
Но здесь-то, раз уж применяются SetLength и Length, то речь шла о такой структуре как "динамический массив" - структура, поддерживаемая компилятором. Живет эта структура по своим правилам и нарушать эти правила компилер не позволит, т.к. он обязан выполнять корректно то, о чем заявляет в своих возможностях. Вот и все.
← →
KilkennyCat © (2004-11-15 10:20) [23]
> Verg © (15.11.04 10:12) [22]
ну разумеется. Однако, я вовсе не подразумевал использование стандартных функций. Естественно, что все придется реализовывать самому.
← →
grig_p (2004-11-15 10:35) [24]Советую отказаться от массивов и использовать TObjectList. А вместо записей использовать классы.
TMyRec = class
...
описание полей
...
end;
только перед использованием класс нужно предварительно создать, удаление класса обеспечивает исключение из списка TObjectList (см. хелп по нему).
← →
Кто---то © (2004-11-16 03:23) [25]
> ЮЮ © (15.11.04 08:11) [16]
> Type
> TSomeArray: array of <SomeType>
>
> function InsertRec(var Array : TSomeArray; Index : Integer):
> Boolean;
Что такое СамТип ? И какой он ?
Если я эту функцию хочу использовать для работы с массивами разных рекордов, то какой СамТип писать ? Или его можно как-то динамически менять ?
← →
ЮЮ © (2004-11-16 04:43) [26]для работы с массивами разных рекордов нужны будут свои типы.
var параметром может быть именно этот тип, а не array of T<SomeRecord>.
Для чего это в Unit Types эти типы, если бы всё так было просто?
type
TIntegerDynArray = array of Integer;
TCardinalDynArray = array of Cardinal;
TWordDynArray = array of Word;
TSmallIntDynArray = array of SmallInt;
TByteDynArray = array of Byte;
TShortIntDynArray = array of ShortInt;
TInt64DynArray = array of Int64;
TLongWordDynArray = array of LongWord;
TSingleDynArray = array of Single;
TDoubleDynArray = array of Double;
TBooleanDynArray = array of Boolean;
TStringDynArray = array of string;
TWideStringDynArray = array of WideString;
Ешё раз повторюсь, универсальный список любых рекордов - это TList, т.е. список указателей, которые, в свою очередь, указывают на участок памяти произвольного типа.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMyRecord = record
a: integer;
b: string;
end;
PMyRecord = ^TMyRecord;
TMyRecordDynArray = array of TMyRecord;
TForm1 = class(TForm)
btnAddToList: TButton;
procedure FormCreate(Sender: TObject);
procedure btnAddToListClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FList: TList;
FDynArray: TMyRecordDynArray;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function InsertRecInList(AList: TList; ANewRec: pointer; Index : Integer): boolean;
begin
// в этом случае InsertRecInList "универсальна", но для доступа к рекордам
// (в том числк для освобождения памяти) требуется приведение к реальному типу
Result := (Index >= 0) and (Index <= AList.Count);
if not Result then exit;
AList.Insert(Index, ANewRec);
end;
function AddRecInMyRecordDinArray(var ADynArray: TMyRecordDynArray; ARecord: TMyRecord): boolean;
begin
// в этом случае для каждого типа динамического массива запискей
// нужна будет своя процедура для манипуляции элементами массива, но пропадает
// необходимость контролировать занимаеиую сассивом память
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FList := TList.Create;
end;
procedure TForm1.btnAddToListClick(Sender: TObject);
var
myRec: PMyRecord;
begin
New(myRec);
InsertRecInList(FList, myRec, 0);
Caption := IntToStr(FList.Count);
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
i: integer;
myRec: PMyRecord;
begin
for i := 0 to FList.Count - 1 do begin
myRec := FList.Items[i];
dispose(myRec);
end;
end;
end.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.041 c