Работа с памятью
Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду
Интересная задачка:
Дано: В памяти по адресу Buf находится массив данных состоящий из ItemCount элементов по ItemLength штук размером SizeOf(LongWord) (4 байта)
все значения _не_константы_ и вычисляются в ходе работы программы.
1. Как задать массив Array[ItemCount, ItemNumber] of LongWord чтобы удобно получать эти значения
Дано: В памяти по адресу Buf находится массив данных состоящий из ItemCount элементов по ItemLength штук размером SizeOf(LongWord) (4 байта)
все значения _не_константы_ и вычисляются в ходе работы программы.
1. Как задать массив Array[ItemCount, ItemNumber] of LongWord чтобы удобно получать эти значения
С уважением, Lost Angel...
Что то типа:
type MyMas = array[1..ItemCount,1..ItemNumber] of LongWord;
SMas = ^MyMas;
....
var mas : SMas;
...
mas:=buf;
Но если ItemCount и ItemNumber могут изменятся (не константы) то, так конечно не получится. Тогда проще объявить одномерный массив размером ItemCount*ItemNumber и к элементу a[i,j] обращатся как к a[(i-1)*ItemNumber+j]
type MyMas = array[1..ItemCount,1..ItemNumber] of LongWord;
SMas = ^MyMas;
....
var mas : SMas;
...
mas:=buf;
Но если ItemCount и ItemNumber могут изменятся (не константы) то, так конечно не получится. Тогда проще объявить одномерный массив размером ItemCount*ItemNumber и к элементу a[i,j] обращатся как к a[(i-1)*ItemNumber+j]
С уважением
вышел из положения немного подругому 
Не очень красиво, конечно с памятью получилось... но куда деваться...
)) особенно [0..1023] 
Если кому интересно: модуль чтения файлов базы данных *.dbc Blizard'а
(телепортер писал для World of Warcraft)

Не очень красиво, конечно с памятью получилось... но куда деваться...


Если кому интересно: модуль чтения файлов базы данных *.dbc Blizard'а
(телепортер писал для World of Warcraft)
Код: Выделить всё
unit DBC;
interface
uses
Classes, SysUtils, Dialogs;
type
TDBCHeader = packed record
FileType: array[0..3] of char;
ItemCount: LongWord;
ItemLength: LongWord;
Data: array[0..1] of LongWord
end;
TDBCData = packed record
Data: array[0..1023] of LongWord;
end;
Const
OffsetBegin = 0;
OffsetData = OffsetBegin + SizeOf(TDBCHeader);
type
TFileDBC = class(TObject)
private
MemBuff: TMemoryStream;
FFileName: TFileName;
FLastError: Cardinal;
FHeader: TDBCHeader;
function GetData(i: Integer): TDBCData;
procedure LoadDescription;
public
Descript: TStringList;
constructor Create(AFileName: TFileName);
destructor Destroy; override;
property FileName: TFileName read FFileName;
property LastError: Cardinal read FLastError;
property Data[index: Integer]: TDBCData read GetData;
property Header: TDBCHeader read FHeader;
function GetStringByOffset(Val: LongWord): String;
end;
implementation
constructor TFileDBC.Create(AFileName: TFileName);
Var
FS: TFileStream;
begin
FFileName := AFileName;
MemBuff := TMemoryStream.Create;
Descript := TStringList.Create;
FS := TFileStream.Create(FileName, fmOpenRead, fmShareDenyNone);
try
MemBuff.CopyFrom(FS, FS.Size);
finally
FS.Free;
end;
FLastError := GetLastError;
MemBuff.Position := OffsetBegin;
MemBuff.ReadBuffer(FHeader, SizeOf(TDBCHeader));
LoadDescription;
end;
procedure TFileDBC.LoadDescription;
Var S: String;
C: Char;
begin
MemBuff.Position := SizeOf(TDBCHeader) +
Header.ItemCount * Header.ItemLength * 4+1;
S := '';
while MemBuff.Position < MemBuff.Size do
begin
MemBuff.ReadBuffer(C, 1);
if C <> #00 then S := S + C
else begin
Descript.Add(S);
S := '';
end;
end;
end;
function TFileDBC.GetStringByOffset(Val: LongWord): String;
Var
S: String;
C: Char;
begin
Result := '';
Val := Val + SizeOf(TDBCHeader) + Header.ItemCount * Header.ItemLength * 4;
if Val < MemBuff.Size then begin
MemBuff.Position := Val-1;
MemBuff.ReadBuffer(C, 1);
if C = #00 then begin
S := '';
MemBuff.ReadBuffer(C, 1);
while (C <> #00) and (MemBuff.Position <= MemBuff.Size) do
begin
S := S + C;
MemBuff.ReadBuffer(C, 1);
end;
Result := S;
end;
end;
end;
function TFileDBC.GetData(i: Integer): TDBCData;
begin
MemBuff.Position := OffsetData + i * Header.ItemLength * 4;
MemBuff.ReadBuffer(Result, Header.ItemLength*4);
end;
destructor TFileDBC.Destroy;
begin
MemBuff.Free;
Descript.Free;
end;
end.
С уважением, Lost Angel...
LAngel, есть на такой случай готовый велосипед - динамические массивы. Работать с ними можно так:
Код: Выделить всё
type TIntArray2d = array of array of Integer;
var ar: TIntArray2d;
var i, j: Integer;
SetLength(ar, ItemCount, ItemNumber);
for i := 0 to ItemCount do
for j := 0 to ItemNumber) do
ar[i,j] := i*j;
Eugie, спасибо. именно это и искал.
С уважением, Lost Angel...
не получается
как я понял, array of array of ... Delphi строит ссылками, а не реальными данными, которые лежат в памяти.
при наведении курсора, в хинте написано:
var TDBCFile.ar: ^array of ^array of Cardinal - DBC.pas (17)
хотя объявлялось:
ar: array of array of Cardinal;
Ну и естественно, когда делаю ссылку на эту структуру и позиционирую её на область памяти, в которой лежат данные, задаю размерность, в лучшем случае в таблице мусор. в худшем - ошибка.

как я понял, array of array of ... Delphi строит ссылками, а не реальными данными, которые лежат в памяти.
при наведении курсора, в хинте написано:
var TDBCFile.ar: ^array of ^array of Cardinal - DBC.pas (17)
хотя объявлялось:
ar: array of array of Cardinal;
Ну и естественно, когда делаю ссылку на эту структуру и позиционирую её на область памяти, в которой лежат данные, задаю размерность, в лучшем случае в таблице мусор. в худшем - ошибка.
С уважением, Lost Angel...
А, понял - тебе надо как бы наложить структуру 2-мерного массива на сплошной блок памяти. Тут дин.массивы действительно не помогут. Тогда можно, как ты сделал, т.е. свой объект, в нем объявить блок памяти достаточного размера и доступаться до него через property. Кстати, property можно сделать типа 2-мерного массива: property Values[X, Y: Integer]: LongWord.
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Помню как то лет десять назад в ТурбоПаскале под ДОСом я накладывал двухмерный массив из структур типа {символ,аттрибуты} на видеопамять текстового режима при помощи ключевого слова absolute, которое позволяло разместить массив в заданном месте.
2B OR NOT(2B) = FF
ещё, в продолжении темы.
Как, с высокой точность отличить 4 байтную структуру Cardinal (DWORD) и Single (Real32) друг от друга?
пока ничего кроме туповатого не придумал... 
Как, с высокой точность отличить 4 байтную структуру Cardinal (DWORD) и Single (Real32) друг от друга?
пока ничего кроме туповатого
Код: Выделить всё
S := FormatFloat('#####.####', DF.DataFloat[Line, Pos]);
if S = '' then S := IntToStr(DF.Data[Line, Pos]);

С уважением, Lost Angel...
В общем случае такого критерия нет и быть не может: оба типа используют весь битовый диапазон (single - с некоторыми оговорками). Но если имеются разумные ограничения на диапазон по каждому типу, то кое-что придумать можно. Например, если целые по модулю < 2^23 (~8000000), то в битовом соответствующем представлении single порядок будет равен 0, а single с нулевым порядком может быть либо 0, либо денормализованным маленьким числом (по модулю <~ 1^-38 ) - чем не критерий? 
Стандартный формат Single:
Проверить можно так:

Стандартный формат Single:
Код: Выделить всё
31|30...23|22.....0|
|s|порядок|мантисса|
Код: Выделить всё
is_single := ((x shl 1) shr 24) <> 0;