21. Záznamy: TYPE

Na čo to je

Hráč má polohu, počet životov a skóre. Sú to štyri premenné, ktoré patria k sebe. Záznam (record) ich spojí do jedného celku s vlastným menom, takže sa dajú odovzdať rutine naraz.

Ako sa to píše

Najprv sa opíše typ záznamu – aké položky má:

Action!
TYPE Player=[BYTE x, y, lives
             CARD score]

Potom sa meno typu používa ako každý iný typ:

Action!
Player hero, enemy           ; dve premenné typu Player
Player POINTER who           ; ukazovateľ na záznam

hero.x=10                    ; položka sa píše za bodku
who.score==+100              ; cez ukazovateľ rovnako, bez ^

Celý program

Súbor examples/records.act:

Action!
; Records: several values that belong together

TYPE Player=[BYTE x, y, lives
             CARD score]

PROC Show(Player POINTER who)
  Print("at ")      PrintB(who.x)
  Put(',)           PrintB(who.y)
  Print(" lives ")  PrintB(who.lives)
  Print(" score ")  PrintCE(who.score)
RETURN

PROC Hit(Player POINTER who, CARD points)
  who.score==+points
RETURN

PROC Main()
  Player hero, enemy

  hero.x=10
  hero.y=5
  hero.lives=3
  hero.score=0

  enemy.x=30
  enemy.y=12
  enemy.lives=1
  enemy.score=500

  Print("Hero:  ")  Show(hero)
  Print("Enemy: ")  Show(enemy)

  Hit(hero, 250)
  hero.x==+1
  Print("Hero:  ")  Show(hero)
RETURN

Preklad a spustenie

action26 records.act --sim

Čo uvidíš

Hero:  at 10,5 lives 3 score 0
Enemy: at 30,12 lives 1 score 500
Hero:  at 11,5 lives 3 score 250

Ako to funguje

Jedna rutina Show obslúži hrdinu aj nepriateľa. To je hlavný zmysel záznamov: rutiny sa píšu pre typ, nie pre jednu konkrétnu premennú.

Pole záznamov

Action! nemá Player ARRAY. Viac záznamov za sebou sa robí poľom bajtov a ukazovateľom, ktorý sa posúva o veľkosť záznamu. Meno typu vo výraze je veľkosť záznamu v bajtoch.

Súbor examples/records-array.act:

Action!
; An array of records: a block of bytes and a pointer that walks through it

TYPE Star=[BYTE x, y
           CARD points]

DEFINE COUNT="3"

PROC Main()
  BYTE ARRAY room(12)        ; room for COUNT records of 4 bytes
  Star POINTER s
  BYTE i

  FOR i=0 TO COUNT-1
  DO
    s=room+i*Star            ; the address of record number i
    s.x=i*10
    s.y=i+1
    s.points=(i+1)*100
  OD

  FOR i=0 TO COUNT-1
  DO
    s=room+i*Star
    Print("Star ")    PrintB(i)
    Print(": x=")     PrintB(s.x)
    Print(" y=")      PrintB(s.y)
    Print(" points=") PrintCE(s.points)
  OD

  Print("One record takes ")
  PrintB(Star)
  PrintE(" bytes")
RETURN
action26 records-array.act --sim
Star 0: x=0 y=1 points=100
Star 1: x=10 y=2 points=200
Star 2: x=20 y=3 points=300
One record takes 4 bytes

s=room+i*Star vypočíta adresu záznamu číslo i: začiatok poľa plus i-krát veľkosť záznamu. Záznam Star má dva BYTE a jeden CARD, teda 4 bajty; tri záznamy potrebujú 12 bajtov.

Časté chyby

Čo sa staloČo povie prekladač alebo program
položka, ktorá v zázname nie je (hero.speed)error ACT008: undeclared name 'speed'
priradenie celého záznamu (enemy=hero)error ACT010: illegal assignment: cannot assign to Player 'enemy' – kopíruj položku po položke
ukazovateľ na záznam bez priradenej adresyzápis na náhodné miesto v pamäti
meno typu a meno premennej sa líšia len veľkosťou písmen (TYPE P, premenná p)je to to isté meno – veľké a malé písmená sa nerozlišujú
pole pre záznamy je malézáznamy za koncom poľa prepíšu inú pamäť

Mená položiek sú mená ako každé iné. Dva typy záznamov v jednom programe preto nemôžu mať položku s rovnakým menom – prekladač ohlási error ACT006: 'x' is already declared. Pomáha predpona: px, py pre hráča, sx, sy pre hviezdu.

Vyskúšaj si

  1. Pridaj do Player položku CHAR symbol a vypisuj ju v Show.
  2. Napíš PROC Move(Player POINTER who, BYTE dx, dy), ktorá posunie hráča.
  3. V druhom programe zmeň COUNT na 5. Čo ešte treba zmeniť?

Zhrnutie

Späť: 20. Ukazovatele · Ďalej: 22. Bity