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

Вниз

Как мне посмотреть исходники процедуры SetLength   Найти похожие ветки 

 
Андрусь   (2002-08-22 13:59) [0]

Привет всем!Такой вот вопрос.Как мне посмотреть исходники процедуры SetLength(прикалываться не надо - подводишь курсор,кликаешь мышкой).Хотябы шапку - типы входных параметров. Зараннее всем большое спасибо.


 
McSimm   (2002-08-22 14:08) [1]

Точка прерывания, CPU Window


 
Hooch   (2002-08-22 14:08) [2]

подводишь курсор,удерживаеш кнопку Контрол, кликаешь мышкой видиш исходник


 
Shaman_Naydak   (2002-08-22 14:10) [3]

Не поверишь, выдрал из хелпа! :)
SetLength procedure
Sets the length of a string or dynamic-array variable.
Unit System

procedure SetLength(var S; NewLength: Integer);

Description

S is a string or dynamic-array variable.

NewLength is the new number of characters or elements in S.

For a short-string variable, SetLength simply sets the length-indicator character (the character at S[0]) to the given value. In this case, NewLength must be a value between 0 and 255.

For a long-string or dynamic-array variable, SetLength reallocates the string or array referenced by S to the given length. Existing characters in the string or elements in the array are preserved, but the content of newly allocated space is undefined. The one exception is when increasing the length of a dynamic array in which the elements are types that must be initialized (strings, Variants, Variant arrays, or records that contain such types). When S is a dynamic array of types that must be initialized, newly allocated space is set to 0 or nil.

Following a call to SetLength, S is guaranteed to reference a unique string or array—that is, a string or array with a reference count of one. If there is not enough memory available to reallocate the variable, SetLength raises an EOutOfMemory exception.

Добавлю от себя, что если переменная многомерный динамический массив, то можно выставлять сразу все размерности, т.е.
var A: array of array of Integer;
begin
SetLength(A, 3, 4); // вполне нормально и корректно!
end;


 
lenin   (2002-08-22 14:10) [4]


> Hooch © (22.08.02 14:08)

Чего, чего, а SetLength не показывает.


 
McSimm   (2002-08-22 14:10) [5]

Шапка (типы входных параметров) -

procedure SetLength(var S; NewLength: Integer);

S - string or dynamic array


 
Dmitriy Polskoy   (2002-08-22 14:15) [6]

Смотри в system.pas


 
Ученик   (2002-08-22 14:17) [7]

>Андрусь © (22.08.02 13:59)
После SetLength( нажми Ctrl+Shift+Пробел


 
Андрусь   (2002-08-22 14:17) [8]

>McSimm
Мастер,а почему на такое компилер ругается

Procedure Delete_Element(Var Arr; ArrSize : Integer; ElemSize, DeleteIdx : Integer);
Var Source, Dest : Integer;
p_source,p_dest:pointer;
Begin
ArrSize := ArrSize * ElemSize;
Source := (DeleteIdx+1)*ElemSize;
Dest := Source-ElemSize;
p_dest:=Pointer(Integer(Arr)+Dest);
p_source:=Pointer(Integer(Arr)+Source);
Move(p_source^,p_dest^,ArrSize-(DeleteIdx+1)*ElemSize);
//Эту строку компилер не пропускает
// SetLength(Arr,ArrSize div ElemSize - 1);
End;


 
Anatoly Podgoretsky   (2002-08-22 14:19) [9]

System.pas


 
McSimm   (2002-08-22 14:21) [10]

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

1. :) Когда компилятор "ругается" он среди бранных слов объясняет причину своего недовольства.

2. Переменная Arr нетипизирована. Поэтому передать ее в SetLength нельзя


 
Андрусь   (2002-08-22 14:30) [11]

>McSimm ©
Не подскажите как с ним договориться. На входе железно будет динамический массив,но тип тоже неизвестен.


 
PVOzerski   (2002-08-22 14:47) [12]

Очень неплохо договариваться через ReallocMem, только отслеживать все возможные утечки памяти придётся самостоятельно. Зато гибкость большая, и для старых версий Delphi, где нет динамических массивов, тоже годится.


 
Ученик   (2002-08-22 14:55) [13]

>Андрусь ©
А как выглядит вызов Delete_Element, желательно с определением типов передаваемых переменных ?


 
Андрусь   (2002-08-22 14:56) [14]

Вот код бы от SetLength глянуть и добавить в мою процедуру что там нужно - тогда можно и без него.


 
Андрусь   (2002-08-22 15:05) [15]

>Ученик © (22.08.02 14:55)
См. Подскажите функцию (Андрусь 22.08.02 14:10)
Вызов процедуры с примером от туда

const del=3;
n=10;
var SS:array of integer;i:integer;
begin
SetLength(SS,n);
For i:=0 To n-1 Do SS[i]:=i;
Delete_Element(SS,Length(SS),SizeOf(SS[0]),del);
end;


 
McSimm   (2002-08-22 15:05) [16]

Когда компилятор встречает SetLength в программе, он в разных случаях генерирует разный код.
Для строк - один, для массивов другой.

В случае с массивами фактически происходит вызов
DynArraySetLength
где в качестве одного из параметров указатель на структуру Type info. Поэтому чтобы откомпилировать SetLength компилятору необходимо знать информацию о типе массива.

Попробуй пойти другим путем. Я не знаю что тебе нужно, но думаю это можно сделать проще


 
Ученик   (2002-08-22 15:15) [17]

procedure Delete_Element(var Arr; TypeInfo : Pointer; DeleteIdx : Integer);
Var
Source, Dest : Integer;
ArrayLen, ElemSize, ArrSize : Integer;
p_source,p_dest:pointer;
Begin
ArrayLen := PInteger(Integer(Arr) - 4)^;
ElemSize := PDynArrayTypeInfo(PChar(TypeInfo) + Length(PDynArrayTypeInfo(typeInfo).name))^.elSize;
ArrSize := ArrayLen * ElemSize;
Source := (DeleteIdx+1)*ElemSize;
Dest := Source-ElemSize;
p_dest:=Pointer(Integer(Arr)+Dest);
p_source:=Pointer(Integer(Arr)+Source);
Move(p_source^,p_dest^, ArrSize-(DeleteIdx+1)*ElemSize);
Dec(ArrayLen);
DynArraySetLength(Pointer(Arr), TypeInfo, 1, @ArrayLen);
End;

Вызов: Delete_Element(I, TypeInfo(TIntegerArray), 3);


 
Игорь Шевченко   (2002-08-22 15:16) [18]

SetLength:

procedure _LStrSetLength{ var str: AnsiString; newLength: Integer};
asm
{ -> EAX Pointer to str }
{ EDX new length }

PUSH EBX
PUSH ESI
PUSH EDI
MOV EBX,EAX
MOV ESI,EDX
XOR EDI,EDI

TEST EDX,EDX
JE @@setString

MOV EAX,[EBX]
TEST EAX,EAX
JE @@copyString

CMP [EAX-skew].StrRec.refCnt,1
JNE @@copyString

SUB EAX,rOff
ADD EDX,rOff+1
PUSH EAX
MOV EAX,ESP
CALL _ReallocMem
POP EAX
ADD EAX,rOff
MOV [EBX],EAX
MOV [EAX-skew].StrRec.length,ESI
MOV BYTE PTR [EAX+ESI],0
JMP @@exit

@@copyString:
MOV EAX,EDX
CALL _NewAnsiString
MOV EDI,EAX

MOV EAX,[EBX]
TEST EAX,EAX
JE @@setString

MOV EDX,EDI
MOV ECX,[EAX-skew].StrRec.length
CMP ECX,ESI
JL @@moveString
MOV ECX,ESI

@@moveString:
CALL Move

@@setString:
MOV EAX,EBX
CALL _LStrClr
MOV [EBX],EDI

@@exit:
POP EDI
POP ESI
POP EBX
end;



 
Андрусь   (2002-08-22 15:18) [19]

>McSimm © (22.08.02 15:05)
Что мне нужно - нужна процедура,которая бы удаляла из динамического массива i-й элемент.Причем чтобы работала для дин.массивов различного типа.И вот там стопор - SetLength.


 
Андрусь   (2002-08-22 15:21) [20]

>Игорь Шевченко © (22.08.02 15:16)
Большое спасибо,но я не шарю в asmе :}.


 
Игорь Шевченко   (2002-08-22 15:35) [21]

Андрусь © (22.08.02 15:21)

Это исходный текст - то, что ты просил.

А кстати зачем удалять произвольный элемент из динамического массива ? Не проще ли список использовать ?


 
PVOzerski   (2002-08-22 15:46) [22]

Я бы игрался только через ReallocMem и Move. И никаких "динамических массивов" с SetLength! Можно, конечно, сделать оболочку-процедуру. Вот как это может выглядеть.
type
MyType=integer; //например
tArray=array[0..0]of MyType; //можно и с другим нач. индексом
pArray=^tArray;
var
MyArray:pArray;
i:longint;
begin
//создаём массив из 1000 элементов
GetMem(MyArray,1000*sizeof(MyType));
//заполняем
for i:=0 to 1000-1 do
MyArray[i]:=i;
//удаляем сотый элемент через "сдвиг"
move(MyArray[100],MyArray[99],sizeof(MyType)*((1000-1)-100));
//уменьшаем длину массива
ReallocMem(MyArray,999*sizeof(MyType));
end.

За правильность расчёта длины смещаемого блока не ручаюсь: нет времени долго думать. Но идея, надеюсь, понятна. PS: ни SetLength, ни Length при таком подходе неприменимы. PPS: Этот подход допускает использование открытых массивов, но только с использованием функции Slice.


 
Alx2   (2002-08-22 16:10) [23]

>Ученик © (22.08.02 15:15)
Класс!


 
Андрусь   (2002-08-22 16:11) [24]

>PVOzerski © (22.08.02 15:46)
К этому выводу я уже приходил. Но всё же хотелось бы без GetMem...

>Игорь Шевченко © (22.08.02 15:35)
Идея интерестная,но как приспособить под это списки. Исходная задача: нужно смоделировать некоторый процесс в тонкой плёнке. Есть динамические массивы с элементами типа Record, описывающими различные участки и состояния плёнки.Я хочу написать процедуру удаления элемента,общую для всех динамических массивов. TList удобен тем что там уже всё реализовано.

type
PRGrain = ^RGrain;

RGrain = Record
Left :integer;
Top :integer;
Height:integer;
Width :integer;
Phase :TPhase;
End;

Затем использовать:

Procedure Add_Element(ALeft,ATop,AHeight,AWidth :integer;
Phase :TPhase);
var p:PRGrain;
Begin
New(p);
p^.Left:=ALeft;
.............
Lisr.Add(p);
End;

Я правильно пишу? Только вот напрягает один момент:в случае масива память будет выделена одним куском,а тут разбросана. Число элементов м.б.довольно велико,следовательно доступ,обращение - в общем скорость работы с таким массивом понизится.
P.S. В Минск не собираетесь - буду очень рад с умным человеком пообщаться.


 
Alx2   (2002-08-22 16:28) [25]

>Ученик © (22.08.02 15:15)
Только вот в хелпе написали:
The actual format of the runtime type information is internal to the compiler and may change between releases.


 
Игорь Шевченко   (2002-08-22 16:29) [26]

Андрусь © (22.08.02 16:11)

Пишешь правильно.

Я так полагаю, что фрагментация памяти здесь окажет не слишком сильное влияние. Со списком работать в данном случае может быть проще, а это значит, что можно сосредоточиться на решении основной задачи.

В Минск рад бы (уж очень город нравится!), но повода нету...


 
Ученик   (2002-08-22 16:34) [27]

>Alx2 © (22.08.02 16:28)
В вопросе есть версия D6 :-)


 
Alx2   (2002-08-22 16:41) [28]

>Ученик © (22.08.02 16:34)
Получается D6 only? :)


 
Ученик   (2002-08-22 16:47) [29]

>Alx2 © (22.08.02 16:41)
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1030015372&n=0


 
Андрусь   (2002-08-22 17:27) [30]

>Игорь Шевченко © (22.08.02 16:29)
А вот что делать с удалением. Допустим хочу удалить элемент,где Let,Right определены. Как это сделать. Сканируем сесь List,находим удовлетворяющих запросу,делаем Delete.Что происходит с участками памяти,на которые указывал указатель.Они получаюся неосвобождёнными.Эт нехорощо.Как удалить где все элементы удалены - опять полное сканирование?


 
Игорь Шевченко   (2002-08-22 17:32) [31]

Андрусь © (22.08.02 17:27)

procedure List.DeleteRGrain (ALeft, ARight : Integer);
var
ItemToDelete : PRGrain;
ItemToDeleteIndex : Integer;
begin
ItemToDeleteIndex := SearchItemIndex(Left, Right);
ItemToDelete := Items[ItemToDeleteIndex];
Delete(ItemToDeleteIndex);
Dispose (ItemToDelete);
end;

SearchItemIndex лучше организовать с использованием двоичного поиска



 
Андрусь   (2002-08-22 17:51) [32]

>Игорь Шевченко © (22.08.02 17:32)
>SearchItemIndex лучше организовать с использованием двоичного поиска.
Извините,чего то не до конца въехал,что вы имели в виду.


 
Игорь Шевченко   (2002-08-22 17:55) [33]

binary search - стандартный алгоритм поиска в ОТСОРТИРОВАННОМ списке. Достаточно быстрый.


 
Андрусь   (2002-08-22 18:17) [34]

Т.е. перед каждым удалением сортировать список,но по чём?


 
Игорь Шевченко   (2002-08-22 18:22) [35]

По тому, по чему будешь чаще всего искать, очевидно. Если ищещь по координате Left, к примеру, то по ней.
Но при удалении список не надо отсортировывать, надо при добавлении. Можно и линейный поиск использовать...


 
Андрусь   (2002-08-22 18:51) [36]

Тут у меня прикол то вообще. Плёнка плоская,координата х,у. Поиск д. идти по двум коорд.


 
Андрусь   (2002-08-22 20:48) [37]

Как организовать бинарный поиск,простите великодушно не въехал.


 
Игорь Шевченко   (2002-08-23 09:46) [38]

Пример двоичного поиска есть в
Program Files\Borland\Delphi\Source\Vcl\Classes.pas
TStringList.Find



 
Alx2   (2002-08-23 10:39) [39]

>Поиск д. идти по двум коорд.
Тогда сортируй по двум координатам сразу.



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

Форум: "Основная";
Текущий архив: 2002.09.05;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.009 c
7-14307
KPY
2002-06-27 08:19
2002.09.05
Не могу поймать VK_RWIN


1-14153
Lamer86
2002-08-24 21:32
2002.09.05
TStrings


1-14008
PEC
2002-08-26 08:42
2002.09.05
Привет народ


3-13976
Duke2
2002-08-16 16:27
2002.09.05
Не сохраняются данные пи сбое эл.энергии


3-13875
PD
2002-08-16 23:51
2002.09.05
работа с BLOB-полями





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский