Autor Téma: Dotaz na dynamické pole  (Přečteno 262 krát)

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Dotaz na dynamické pole
« kdy: 29-05-2019, 17:45:04 »
Dá se dynamické pole nastavit podobně jako statické?
Kód: Delphi [Vybrat]
  1. charCounters: Array[1488..1514] of byte;
Přiřazením paměti pomocí setLenght to asi nejde?

Chtěl jsem udělat dynamické pole, abych mohl k různým polím sloužícím k podobnému účelu (počítání znaků) přistupovat pomocí pointeru. Tzn. že téže pointer bych mohl nastavit na jakékoliv pole. Ty pole jsou

Kód: Delphi [Vybrat]
  1. type TMainCharCounters = Array[1488..1514] of byte;
  2. type TMinorCharCounters = Array[1488..1514] of byte;

Ale říkal jsem si, že k tomu asi ten pointer nepůjde nastavit, protože každý typ je jiný. Takže teď zvažuji dynamickou cestu:

Kód: Delphi [Vybrat]
  1. type TCountersType = byte;
  2. type TCounter = Array of TCountersType;

Jenže tam je problém že to začíná od nuly, což nechci. Chci aby si uživatel mohl nadefinovat číslo min a max, kterým hodnota znaku končí a podle toho by se mělo automaticky vytvořit pole s indexy od min až po max. To asi nejde, co?

Používám Delphi 7
« Poslední změna: 29-05-2019, 18:05:31 od vangog »

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #1 kdy: 29-05-2019, 18:08:38 »
Tak jsem to udělal, ale to přece bude číslovat od nuly, ne?
 
procedure allocateCountersMemo(PCounter: TCounter; min: Word; max: Word);
begin
  min := 1488;
  max := 1514;
  SetLength(X, max-min);
end;

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #2 kdy: 29-05-2019, 18:48:18 »
Píšu třídu pro překlad/převod znaků. Program sbírá statistické data o znacích v daném rozsahu. Jelikož UTF-8 má přibližně ~65000 hodnot tak nechci vytvářet pole (více polí) o délce 65000, ale jen například rozsah 60.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4420
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Dotaz na dynamické pole
« Odpověď #3 kdy: 29-05-2019, 19:38:47 »
Dynamické pole vždy začína od nuly. S tým nič neurobíš.
Mohol by si použiť fintu typu MyArray[MyIndex/Value - Min]
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #4 kdy: 29-05-2019, 19:55:38 »
Chci to co nejjednodušší pro snadný a rychlý přístup, žádné výpočty. Vymyslel jsem to. Je to kompromis. Použiju rozsah Word. Velikost pole bude max. 65532*2 byty. K dispozici bude jedna polovina a druhá polovina mi poslouží pro kopii dat. Teď píšu koment.

 < Memory solution >
  "How to allocate memory for Data analysis."
  A developer can allocate memory by allocateCountersMemo(M, N)
  where N is maximum index, so arrayRange is calculated as N+1.

  He can use setCopyArrayOffset() to define where to copy backup
  values. E.g.
  .allocateCountersMemo(256, 512); (range 256) for processing
  .setCopyArrayOffset(0); // 0-255 (range 256) for copy purposes

  For copy purposes, developer needs to check not to
  overlap the original data range!

  The maximum range is 65535 / 2 ... eg.
  .allocateCountersMemo(0, 32767);
  .setCopyArrayOffset(32768); // the copy will be saved in the range 32768-65535

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #5 kdy: 29-05-2019, 19:57:02 »
Začínám takto:
Kód: Delphi [Vybrat]
  1.   MyTranslation := TTranslation.Create;
  2.   // Memory rage 0 to 1514
  3.   MyTranslation.allocateCountersMemo(1488, 1514);
  4.   MyTranslation.setCopyArrayOffset(0);
  5.  

část třídy
Kód: Delphi [Vybrat]
  1. procedure TTranslation.allocateCountersMemo(minOrd: Word; maxOrd: Word);
  2. begin
  3.   TAObj.min := 1488;
  4.   TAObj.max := 1514;
  5.   TAObj.arrayRange := TAObj.max-TAObj.min;
  6.   SetLength(obj1.arr, TAObj.max + 1);
  7. end;
  8. procedure TTranslation.setCopyArrayOffset(copyOffset: word);
  9. begin
  10.   TAObj.copyOffset := copyOffset;
  11. end;

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #6 kdy: 29-05-2019, 21:59:43 »
Mám k tomu ještě dotaz. Když chci vynulovat jen část například v poli [0-100] of word chci vynulovat indexy 50-77, jak to udělat? Mě napadá jen alokovat pomocné pole o rozsahu 0-26 a toto vynulované zkopírovat pomocí move. Ale zdá se mi to komplikované, protože zas musím dynamicky vytvářet pomocná pole.
« Poslední změna: 29-05-2019, 22:14:04 od vangog »

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4420
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Dotaz na dynamické pole
« Odpověď #7 kdy: 29-05-2019, 22:14:01 »
Čo vlastne myslíš pod "vynulovat indexy 50-77".
  • nastaviť hodnoty poľa na null, 0 či nil?
  • zrušiť tieto riadky v array. Čiže zmeniť rozmer poľa?
  • niečo iné?
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Dotaz na dynamické pole
« Odpověď #8 kdy: 30-05-2019, 00:01:54 »
Myslel jsem toto:

Kód: Delphi [Vybrat]
  1. procedure TTranslation.allocateCountersMemo(minOrd: Word; maxOrd: Word);
  2. begin
  3.   TAObj.min := minOrd;
  4.   TAObj.max := maxOrd;
  5.   TAObj.arrayRange := TAObj.max-TAObj.min;
  6.   SetLength(obj.arr, TAObj.max + 1);
  7.   setLength(temp.arrCharCountersRange, t.arrayRange);
  8.   setLength(temp.arrCharRange, t.arrayRange);
  9.   obj.arrO := @obj.arr;
  10. end;
  11. procedure TTranslation.clearArray;
  12. begin
  13.   move( temp.arrCharRange, t.chars, t.arrayRange*sizeOf(boolean));
  14.   move( temp.arrCharCountersRange, t.charCounters, t.arrayRange*sizeOf(TCounterType));
  15. end;

Ještě řeším pointery, ty mi moc nejdou. Mám pole Arr a snažím se k němu dostat přes pointer.

Kód: Delphi [Vybrat]
  1. type TTracker = record
  2.   arr: TArrayOfPositions;
  3.   arrO: ^TArrayOfPositions; // array output for backup
  4.   arrOP: Pointer;
  5. end;
  6.  

Co jsem udělal
Kód: Delphi [Vybrat]
  1. type TArrayOfPositions = Array of word;
  2. procedure TTranslation.setCopyArrayOffset(copyOffset: word);
  3. begin
  4.   TAObj.copyOffset := copyOffset;
  5.   obj.arrO := @obj.arr;
  6.   obj.arrOP := Inc(PByte(obj.arrO),copyOffset*sizeOf(TArrayOfPositions));
  7. end;
  8.  
  9.  
Zkouším tyto dva pokusy, ale potřebuju ten pointer posunout o copyOffset, tak aby ukazoval na určitý element. Nějaká rada jak to správně udělat?

Edit:
Myslím že jsem na to přišel
Kód: Delphi [Vybrat]
  1. procedure TTranslation.allocateCountersMemo(minOrd: Word; maxOrd: Word);
  2. begin
  3.   TAObj.min := minOrd;
  4.   TAObj.max := maxOrd;
  5.   TAObj.arrayRange := TAObj.max-TAObj.min;
  6.   SetLength(obj.arr, TAObj.max + 1);
  7.   setLength(temp.arrCharCountersRange, t.arrayRange);
  8.   setLength(temp.arrCharRange, t.arrayRange);
  9.   obj.arrO := @obj.arr;
  10. end;
  11. procedure TTranslation.setCopyArrayOffset(copyOffset: word);
  12. begin
  13.   TAObj.copyOffset := copyOffset;
  14.   Inc(obj.arrO,copyOffset);
  15. end;
  16.  
https://helloacm.com/pointer-arithmetic-in-delphi/
« Poslední změna: 30-05-2019, 00:31:47 od vangog »

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 766
  • Karma: 43
    • Verze Delphi: 10.3
Re:Dotaz na dynamické pole
« Odpověď #9 kdy: 30-05-2019, 16:15:15 »
Mám k tomu ještě dotaz. Když chci vynulovat jen část například v poli [0-100] of word chci vynulovat indexy 50-77, jak to udělat? Mě napadá jen alokovat pomocné pole o rozsahu 0-26 a toto vynulované zkopírovat pomocí move. Ale zdá se mi to komplikované, protože zas musím dynamicky vytvářet pomocná pole.

Kód: Delphi [Vybrat]
  1. fillchar(Pole[50], sizeof(Pole[50])*(77-50+1), 0);