Wiki-kopiopeilipalvelin

Tämä on pascal.chatin wikin peilipalvelin. Muokkaus, historia ja kirjautuminen ovat siellä.

Howdy World (Hello World on steroids)/fi

English · Português · Suomi

Tämä Wikisivu on Lazarus ohjelmoinnin perusopastusta. Tässä selitetään ensimmäisiä askeleita miten saada toimiva ohjelmisto ja joitakin hyviä käytäntöjä selitetään myös matkan varrella. Lopputulos on (toivottavasti)kaksitahoinen: lukija ymmärtää peruskäsitteet miten rakentaa ohjelmisto Lazaruksella ja hän saa todellisen palan toimivaa ohjelmistoa, joka voidaan sisällyttää muihin ohjelmiin: laskimen. Laskin on melko helppo toteuttaa ja jokainen ymmärtää sen käsitteitä. Joten sitä ei tarvitse kuvata "liiketaloudellisesti" etukäteen. Laskin on rajoitettu vain kokonaisluku laskelmiin, mutta voidaan helposti laajentaa. Tämä opetusohjelma ei kuvaa Lazaruksen asennusta. Vaan oletetaan, että Lasarus on asennettu ja käyttövalmis (mieluiten viimeinen vakaa versio). Tämä opetusohjelma on enemmän tai vähemmän alustasta riippumaton. Kaikki kuvakaappauksia tehtiin Windows XP PC; joten sininen / punainen / harmahtava väritys.

Suositeltavaa luettavaa ennen tätä: Kattava Lazaruksen käyttöönotto.

Aloitus

On parasta luoda erillinen hakemisto/kansio jokaista uutta projektia varten. Joten ennen kuin tartutaan varsinaisiin "puikkoihin" niin luodaa hakemisto johon tallennetaan tämä laskin projekti (tehdään tämä käyttöjärjestelmän avulla). Tämä hakemisto on juuri kaikille projektiin luoduille tiedostoille.

(Teksti, joka kuvaa toimia, jotka täytyy suorittaa on merkitty luettelomerkeillä kuten edellinen rivi.)

On siis aika aloittaa uusi Lazarus projekti.

Voit varmistaa, että kaikki tiedostot uudessa projektissa päätyvät oikeaan hakemistoon on projekti tallennettava ensin.

Teoriassa ohjelma, joka on täten luotu on pala toimivaa ohjelmistoa, joka voidaan suorittaa. Ennen kokoamisen ensimmäistä kertaa, kaksi muutosta suositellaan: osoitetaan uusia paikkoja (hakemistoja) varten kootuille käännösyksiköille ja kohdetiedostolle.

Alla oleva kuva näyttää miten tämä on Windows koneella.

Tekemällä näin projektikansio ei täyty tuotoksella, joka syntyy kääntämisessä. Projektikansion tiedostot vaaditaan kun (uudelleen) kootaan ohjelma. Kaikki se mitä on lib ja bin hakemistoissa voidaan poistaa kun projekti arkistoidaan.

Nyt ensimmäisenä testinä projekti voidaan koota ja ajaa.

Jos kaikki meni hyvin niin nähdään tyhjä ikkuna. Nyt tiedetään että ollaan luotu vankka perusta johon voidaan alkaa rakentaa ohjelmaa.

Ensimmäinen komponentti

Lazaruksessa on komponenttipaletti:

Kaikki komponentit, jotka ovat saatavilla rakentaessa käyttöliittymää on ryhmitelty loogisesti välilehtiin. Todellinen välilehtien määrä riippuu asennetuista paketeista. Mutta peruspaletti näyttää suunnilleen samanlaiselta mitä on kuvassa. Ensimmäinen välilehti on Standard, jonka jälkeen Additional, Common jne. Komponentin tyypin nimi löytyy kun vie hiiren osoittimen komponentin kuvakkeen yläpuolelle jolloin vihjetekstinä näkyy tyypin nimi (tarkemmin sanottuna: näytetään minkä tyyppinen on komponentin luokka). Selitystä komponenteista löytyy myös mm Kattava Lazaruksen käyttöönotto.

Ensimmäinen asia, joka tehdään laskinohjelmaan on luoda siihen näyttö, jossa syötetyt numerot ovat tai näytetään. Tähän käytetään TEdit-komponenttia tai Controls:ia.

Note: Joskus visuaalisia komponentteja kutsutaan myös Controls:ksi. "Komponentin (component)" ja "control" erolla ei nyt ole merkitystä.

Jos halutaan sijoittaa komponentti lomakkeelle niin se on oltava valittuna. Painamalla F12-näppäintä se vaihtaa valituksi vuorotellen lomakkeen tai lähdekoodieditorin.

Nyt kun komponentti on sijoitettu lomakkeelle se voidaan räätälöidä tarpeisiimme. Tämä mukauttaminen tapahtuu komponenttimuokkaimessa. Se on ikkuna näytön vasemmalla puolella jossa on TEdit-komponentin ominaisuuksien luettelo jotka ovat muokattavissa.

Ominaisuudet määrittävät komponentin ulkoasua ja käyttäytymistä. Ominaisuuksia on helppo vaihtaa: klikkaa jotain niistä, syötä uusi arvo ja paina Enter. Vaikutukset komponenttiin ovat heti näkyvissä. Kaikki komponenttimuokkaimessa kerralla näytettävät ominaisuudet kuuluvat yhdelle komponentille. Se komponentti, joka on valittu voidaan tunnistaa pienistä mustista neliöistä lomakkeella. Neliöt ympäröivät komponenttia. Niin tapa muuttaa komponentin ominaisuuksia, on ensin valita se ja sitten tehdä muutoksia komponenttimuokaimella. Jos mitään komponenttia ei ole valittu niin lomakkeen ominaisuudet näkyvät.

Tee seuraavat muutokset komponentin Edit1 ominaisuuksiin.

Nämä ominaisuudet ovat melko itsestään selviä. Varsinkin kun edellä olevia muutoksia tehdään ja niiden vaikutuksia seurataan lomakkeella.

Viimeistely koskettaa myös käytettävää kirjaisinta (Font), jota käytetään näyttämään tekstejä kaikissa komponenteissa. Kirjaisin eli fontti voidaan muuttaa kahdessa paikassa: TEdit-tyyppisen edDisplay komponentin Font ominaisuudessa tai lomakkeen Font-ominaisuudessa. Muuttaminen lomakkeen Font-ominaisuudessa on se etu, että "kaikki" asetut komponentit lomakkeella tulee "perimään" tämän fontin. Nyt tehdään tälläinen muutos.

Klikkaa komponenttimuokkaimessa Font-ominaisuutta. Font-rivi on nyt korostettu ja painike kolmella pisteellä ... näkyy.

Lomakkeen otsikko ei ole kovin mielekäs. Oletusteksti "Form1" näytetään.

Kaikkien näiden toimien tuloksena on lomake, joka näyttää (suurinpiirtein) tältä:

Nyt on hyvä aika tallentaa tehty työ.

Muista tallentaa ja tallentaa usein!

Painikkeet

Mitä hyötyä on laskimesta, jos numeroita ei voida syöttää? Niin seuraava askel on lisätä painikkeet numeroille 0..9. Ennen kuin laitetaan numeropainikkeita niin ns säiliö/kontti (container) sijoitetaan lomakkeelle. Säiliö rajaa alueen lomakkeelle johon komponentit voidaan ryhmitellä. Lomake on säiliö. TPanel on toinen säiliö, joka voidaan sijoittaa lomakkeelle. Säiliöihin voidaan sijoittaa sisällä sijaitsevia säiliöitä, mutta siitä lisää jossain toisessa opetusohjelmassa.

Uusi paneeli on nyt näkyvissä lomakkeella oletusleveydellä, korkeudella ja tekstillä. Huomio, että paneelin Caption tekstin fontti periytyy lomakkeelta. Tätä paneelia käytetään ryhmittelemään kaikki painikkeet, joten useita ominaisuuksia, on muutettava.

(Koon kasvattaminen lomakkeella antaa tilaa komponenteille.)

Nyt lisätään numeronäppäimet.

Tämä on toistettava myös numeroille 1..9. Nopein tapa tehdä tämä on kopioda 0-näppäintä ja liittämällä sitä.

Seuraavaksi on neljä painikketta matemaattisia laskuja varten (lisäys, vähennys jne).

Ja "erikoisnäppäimet":

Kaikki painikkeet on sijoitettu, muuta lomaketta sopivan tiiviiksi.

Sen pitäisi näyttää tältä:

Muista tallentaa ja tallentaa usein!

Tapahtumiin vastaaminen

Graafinen sovellus on usein tapahtuma-pohjainen ohjelma. Tämä tarkoittaa sitä, että sovellus ei tee mitään ennen kuin kerromme sitä tekemään jotain. Esimerkiksi syöttämällä dataa näppäimistön kautta, painalluksina jne. Yksi asioista on että laskimen tarvitsee vastata kun hiirellä klikataan numeroita 0..9. Tässä on Lazarus ohjelman kehitysympäristö auttaa. Niin sanotun tapahtumakäsittelijän lisääminen painiketta varten on helppoa.

pascal
edDisplay.Text := edDisplay.Text + '0';

Eli edDisplay on TEdit-komponentti. Tapa muuttaa sen sisältöä on muokata sen Text-ominaisuutta. Edellä esitetty lause lisää numeron "0" muokkausruutuun ja tämä näkyy näytöllä välittömästi.

pascal
edDisplay.Text := edDisplay.Text + '1';

On hyvä idea kääntää koodin ajoittain tarkistaen syntaksivirheet (käännösaikainen virhe).

Tietenkin se on nyt helppo lisätä tapahtuman käsittelijät numeroille 2..9, mutta tämä johtaa paljon tarpeettomaan koodiin. Jokainen tapahtuma käsittelijä on lähes samanlainen, ainoa erona on että numero on erilainen. Tapa poistaa tämä päällekkäisyys on luoda aliohjelma, joka tekee käsittelyn ja lisää muuttuvat tiedot (numerot 0..9) parametrina.

pascal
  
{ TForm1 }

  TForm1 = class(TForm)
    btnDigit0: TButton;
    btnDigit1: TButton;
    btnDigit2: TButton;
    btnDigit3: TButton;
    btnDigit4: TButton;
    btnDigit5: TButton;
    btnDigit6: TButton;
    btnDigit7: TButton;
    btnDigit8: TButton;
    btnDigit9: TButton;
    btnFunction: TButton;
    btnFunction1: TButton;
    btnFunction2: TButton;
    btnFunction3: TButton;
    btnCalculate: TButton;
    btnPlusMinus: TButton;
    btnClear: TButton;
    edDisplay: TEdit;
    Panel1: TPanel;
    procedure btnDigit0Click(Sender: TObject);
    procedure btnDigit1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

Huomaa, että edellisessää luokkamäärittelyssä kaikki komponentit ja aliohjelmat on määritelty lisäämällä ne lomakkeen kautta "osoittamalla kohtaa ja klikkaamalla". Älä tee mitään (manuaalista) muutoksia sinne!! Kehitysympäristö ei välttämättä ymmärrä niitä ja menee sekaisin. Paikka lisätä mukautettuja muuttujia, aliohjelmia ja funktioita on private tai public osio. Pääsääntöisesti kaikki muokatut muuttujat lisätään private osioon. Aliohjelmat ja funktiot lisätään usein private osioon, paitsi jos muut (luokat, lomakkeet) tarvitsee kutsua näitä aliohjelmia tai funktioita (jonka ei pitäisi tapahtua liian usein).

Takaisin numeron näyttö ongelmaan: tarvitaan aliohjelma, joka lisää numeron näytölle, jossa itse numerot voi vaihdella.

pascal
  
  private
    { private declarations }
    procedure AddDigit(const pDigit: byte);
  public
    { public declarations }
  end;

Seuraavaksi aliohjelman AddDigit varsinainen koodi olisi syötettävä. Jälleen voidaan hyödyntää kehitysympäristöä:

Kehitysympäristö luo määritelmän tälle uudelle aliohjelmalle ja asettaa tekstikursorin tyhjän rungon sisälle. Jolloin heti voidaan aloittaa kirjoittaminen.

pascal
edDisplay.Text := edDisplay.Text + IntToStr(pDigit);

Huomaa että function IntToStr() muuttaa numeerisen arvon, numeron, merkkijono arvoksi jotta se voidaan lisätä näytön tekstiin.

Nyt käyttää tätä aliohjelmaa kaikissa numeroissa 0..9:

pascal
procedure TForm1.btnDigit0Click(Sender: TObject);
begin
  AddDigit(0);
end;
pascal
procedure TForm1.btnDigit1Click(Sender: TObject);
begin
  AddDigit(1);
end;

Ennen kuin teet tämän sekvenssin kaikkille muille numeropainikkeille, varmista, että tämä todella tekee sen mitä halutaan.

Hyvä ohjelmoija on laiska ohjelmoija

Nyt voimme lisätä tapahtuman käsittelijät numeronäppäimille 2..9. Mutta sitten taas meillä on sama ongelma, luodaan paljon tarpeeton koodia: AddDigit (2), AddDigit (3) jne. Mitä jos olisi olemassa tapa kertoa painikkeet toisistaan? Onneksi on.

Kaikki komponenteilla on kokonaisluku ominaisuus nimeltään Tag (muista: kontrollit on vain erikoinen komponentti, joka perii tämän Tag ominaisuuden). Se on ominaisuus, jolla ei ole varsinaista toimintoa. Se on olemassa, jotta sitä voidaan käyttää tarvittaessa. Mitä jos jokaisen painikkeen numeroarvo olisi tallennettu Tag ominaisuuteen...

Nyt kaikkilla numeropainikkeilla on oma ainutlaatuinen Tag arvo. Emme ole muuttaneet numeropainiketta 0 koska Tag arvon oletusarvo on jo 0. Nyt hyödynnetään tämä Tag arvo:

pascal
procedure TForm1.btnDigit0Click(Sender: TObject);

Parametri Sender on käytännössä viittaus painikkeeseen, jota painettiin. Typecasting avulla voidaan parametria käyttää kuin se olisi TButton.

pascal
procedure TForm1.btnDigit0Click(Sender: TObject);
begin
  AddDigit(TButton(Sender).Tag);
end;

Ei näytä siltä että olisi saavutettu paljon, yksi rivi koodia korvaa toisen. Kuitenkin jos lisätään koodi muihin numeroihin (1..9) se näyttää täsmälleen samalta. Joten kaikki muut numerot voidaan laittaa käyttämään tätä koodia uudelleen!

Katsotaanpa tarkemmin komponenttimuokkaimella.

Komponenttimuokkaimessa voidaan komponentin ominaisuuksien lisäksi muuttaa tapahtumankäsittelijöitä. Komponenttimuokkaimessa voidaan heti nähdä kun numeropainiketta 0 klikataan niin kutsutaan aliohjelmaa btnDigit0Click (tämä on onClick tapahtumakäsittelijässä).

Nyt kaikki painikkeet jakaa yksi yhteisen aliohjelman, joka tekee juuri mitä halutaan paitsi numeropainiketta 1. Muistutuksesksi se että numeron 1 painikeeseen luotiin tapahtumankäsittelijä btnDigit1Click ja sitä ei todellakaan tarvita enää.

Nyt kaikki painikkeet jakavat saman tapahtumakäsittelyn ja lisää numeroa näyttöruudussa.

Numeropainikkeilla on eräs viimeistely asia vielä tehtävä: tapahtumakäsittelijä btnDigit1Click edelleen olemassa, mutta sitä ei käytetä enää joten se olisi poistettava. Turvallisin tapa tehdä tämä (toistaiseksi) on antaa kehitysympäristön käsitellä sitä. Jotta tämä toimisi niin vaihtoehto Poista automaattisesti tyhjät metodit olisi oltava käytössä.

Tästä lähtien kaikki tyhjät metodit poistetaan automaattisesti heti, kun lähdetiedosto tallennetaan.

Hienosäätöä

Jotain hyvää : laskin ohjelma kääntyy ja toimii kun klikkaa numeroa 0..9. Mutta se ei käyttäydy juuri niin kuin haluamme: siellä on aina ärsyttävä nolla luvun alussa ja salliiasivan liikaa numeroita.

Poistetaan etunollat

Normaalisti kokonaisluku, joka on suurempi (tai pienempi) kuin nolla ei ala nolla numerolla. Joten laskimenkin pitäisi kompensoida tämän. Onneksi tämä on helppo toteuttaa. Muista, että on vain yksi aliohjelma, joka käsittelee numeroiden lisäämisen: AddDigit. Tämä on paikka johon lisätä logiikka joka tukahduttaa nämä etunollat.

pascal
procedure TForm1.AddDigit(const pDigit: byte);
begin
  // Poistaa etunollan lisättäessä numeroa
  if edDisplay.Text = '0' then
    edDisplay.Text := IntToStr(pDigit)
  else
    edDisplay.Text := edDisplay.Text + IntToStr(pDigit)
end;

Rajaa numeroiden määrä

Tämä demo laskin ei osaa käsitellä numeroita, jotka ovat liian suuria. Joten täytyy rajoittaa numeroiden määrä joita voidaan syöttää. Jälleen looginen paikka tehdä tämä on aliohjelma AddDigit:

pascal
procedure TForm1.AddDigit(const pDigit: byte);
begin
  // Rajoittaa numeroiden määrän
  if length(edDisplay.Text) < 8 then
  begin
    // Poistaa etunollan lisättäessä numeroa
    if edDisplay.Text = '0' then
      edDisplay.Text := IntToStr(pDigit)
    else
      edDisplay.Text := edDisplay.Text + IntToStr(pDigit);
  end;
end;

Toiminnot

Nyt on aika tarkastella varsinaista toimintaa jota halutaan toteuttaa: lisäämistä, vähentämistä, kertomista ja jakamista. Tapa, jolla käyttäjä aikoo käyttää laskinta menee jotenkin näin:

  1. Käyttäjä syöttää luvun
  2. Käyttäjä painaa toimintonäppäintä (esimerkiksi "+")
  3. Käyttäjä syöttää toisen luvun
  4. Käyttäjä painaa "="
  5. Ohjelma vastaa lisäämällä ensimmäisen ja toisen luvun

Heti kun käyttäjä painaa "=" -painiketta ohjelma on tiedettävä kolme asiaa:

  1. Mikä oli toiminto?
  2. Mikä oli ensimmäinen luku?
  3. Mikä oli toinen luku?

Mikä oli toiminto?

Jotenkin täytyy rekisteröidä, mikä tietyn toiminnan tyyppi valittiin. Ja on tiedettävä, mitkä toiminnat ovat käytettävissä. Yksi tapa toteuttaa tämä on luoda luetteltu tyyppi (tai käyttäjän määrittämä skalaarityyppi), joka sisältää kaikki sallitut toiminnot.

pascal
 
type

  { Kaikki tuetut toiminnot laskimessa }
  TOperationType = (otNone, otPlus, otMinus, otMultiply, otDivide);

  { TForm1 }

  TForm1 = class(TForm)

, joka lisätään private osaan lomakkeen luokan määrittelyyn.

pascal
  
  private
    { private declarations }
    SelectedOperation: TOperationType;
    procedure AddDigit(const pDigit: byte);

Mikä oli ensimmäinen luku?

Ensimmäisen luvun tilapäiseen tallennukseen tarvitaan muuttuja.

pascal
  
  private
    { private declarations }
    SelectedOperation: TOperationType;
    FirstNumber: longint;
    procedure AddDigit(const pDigit: byte);

Mikä oli toinen luku?

Mitähän seuraavaksi?

Nyt on aika toteuttaa toimintopainikkeiden toiminnot: lisäys, vähentäminen, kertominen ja jakaminen. Aloitetaan "+" -painikkeella. Vähän niin kuten aikaisemminkin : kun "+" painiketta painetaan niin täytyy tallentaa ensimmäinen luku ja se mikä operaatio on käytössä. Niin, että mitä aiotaan tehdä.

Hetkinen! Ennen kuin lisätään koodia tähän ja tehdään samoin kolmeen muuhun käyttöpainikkeelle, muista mitä aiemmin kerrottiin, kun numeroita 0..9 lisättiin: Ei lisätä päällekkäistä koodia! On kohtuullista olettaa, että koodi kolmessa muussa toimintopainikkeessa on sama kuin "+" painikkeessa, lukuun ottamatta itse operaatiota. Joten siinä säästää jonkin verran työtäkin.

pascal
  
  private
    { private declarations }
    SelectedOperation: TOperationType;
    FirstNumber: longint;
    SecondNumber: longint;
    procedure AddDigit(const pDigit: byte);
    procedure StoreOperation(const pOperation: TOperationType);

Aliohjelmassa StoreOperation on tehtävä kaksi asiaa: tallentaa toiminto ja tallentaa luku, joka on näytössä, jolloin sitä voidaan käyttää myöhemmin.

pascal
procedure TForm1.StoreOperation(const pOperation: TOperationType);
begin
  // tallentaa toiminnon
  SelectedOperation := pOperation;

  // tallentaa luvun
  FirstNumber := StrToInt(edDisplay.Text);
end;

Ok, takaisin "+" -painikkeeseen:

Nyt hyvä testata ohjelmaa ja katsoa mitä tapahtuu:

Mitä tapahtuu kun painaa "+"-painiketta tai jotain muuta toimitopainikketta: näyttö ei tyhjenny. On löydettävä tapa jolla näyttö tyhjentyy, kun toimintopainiketta painetaan. Koska on käytetty aliohjelmia yhdistämään samanlaisia ??toimia, tämä on helppo muutos.

pascal
  private
    { private declarations }
    SelectedOperation: TOperationType;
    FirstNumber: longint;
    SecondNumber: longint;
    doClearDisplay: boolean;
    procedure AddDigit(const pDigit: byte);
    procedure StoreOperation(const pOperation: TOperationType);
pascal
procedure TForm1.StoreOperation(const pOperation: TOperationType);
begin
  // tallentaa toiminnon
  SelectedOperation := pOperation;
  // tallentaa luvun
  FirstNumber := StrToInt(edDisplay.Text);
  // Näytön muistiin että täytyy aloittaa uusi luku
  doClearDisplay := true; 
end;
pascal
procedure TForm1.AddDigit(const pDigit: byte);
begin
  // Täytyykö näyttö tyhjentää ensin?
  if doClearDisplay then
  begin
    edDisplay.Text := '0';   // Laitetaan näyttöön nolla
    doClearDisplay := false; // Tyhjennys tehty
  end;

  // Rajoittaa numeroiden määrän
  if length(edDisplay.Text) < 8 then
  begin
    // Poistaa etunollan lisättäessä numeroa
    if edDisplay.Text = '0' then
      edDisplay.Text := IntToStr(pDigit)
    else
      edDisplay.Text := edDisplay.Text + IntToStr(pDigit);
  end;   
end;

Nyt hyvä testata ohjelmaa ja katsoa mitä tapahtuu:

Jo ollaan aika pitkällä: voidaan kirjoittaa numeroita ja valita toiminto. Nyt on aika tehdä todellisia laskelmia.

Tehdään laskutoimitukset

Nyt kun on tallennettu luvut ja toiminta, on aika tehdä todellisia laskelmia. Aloitetaan helppolla: yhteenlaskulla.

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
var result: longint;
begin
  case SelectedOperation of
    otPlus: begin
              // Nouda toinen luku
              SecondNumber := StrToInt(edDisplay.Text);
              // Laske lasku
              result := FirstNumber + SecondNumber;
              // Näytettävä tulos
              edDisplay.Text := IntToStr(result);  
            end;
  end;
end;

Edellä oleva koodi on melko yksinkertainen: jos käyttäjä painaa "+" -painiketta, ensimmäinen ja toinen luku lasketaan yhteen ja tulos tallennetaan Edit-komponenttiin näytölle. On hyvä huomata että koodissa käytetään case of valintarakennetta.

Nyt on toimiva laskin (joka voi vain lisätä kaksi lukua):

Nyt voisi lisätä kolme muuta puuttuvaa toimintoa ( '-', '*' ja '/'). Mutta ei vielä, on parantamisen varaa. Katsotaan seuraava lausetta:

pascal
SecondNumber := StrToInt(edDisplay.Text);

Olemme nähneet tämän tapaisen lauseen ennenkin: Aliohjelma StoreOperation sisältää jotain vastaavaa:

pascal
FirstNumber := StrToInt(edDisplay.Text);

Lukumäärän laskemiseksi käyttäjän kirjoittaman luvun muunto nyt tapahtuu kahdessa eri paikassa. Ei haluta toistaa tätä niin on hyvä idea luoda kokonaan uusi toiminto, joka tekee laskelman.

pascal
   
private
    { private declarations }
    SelectedOperation: TOperationType;
    FirstNumber: longint;
    SecondNumber: longint;
    doClearDisplay: boolean;
    procedure AddDigit(const pDigit: byte);
    procedure StoreOperation(const pOperation: TOperationType);
    function GetDisplayValue: longint;
pascal
function TForm1.GetDisplayValue: longint;
begin
  result := StrToInt(edDisplay.Text);
end;

Jonkin verran koodin uudelleen kirjoittamista, takaisin laskentaan.

Nyt katso seuraavat lausetta:

pascal
              // Nouda toinen luku
              SecondNumber := GetDisplayValue;
              // Laske lasku
              result := FirstNumber + SecondNumber;

Muuttujaa SecondNumber käytetään tallentamaan arvo näyttöruudusta. Kuitenkin se ei ole välttämättä tarpeen. Edellä oleva koodi voidaan yksinkertaistaa:

pascal
              // Laske lasku
              result := FirstNumber + GetDisplayValue;

Nyt katsotaan seuraavia lauseita:

pascal
              // Laske lasku
              result := FirstNumber + GetDisplayValue;
              // Näytettävä tulos 
              edDisplay.Text := IntToStr(result);

Sama koskee myös result muuttujaa. Edellä oleva koodi voidaan yksinkertaistaa:

pascal
              // Näytettävä tulos 
              edDisplay.Text := IntToStr(FirstNumber + GetDisplayValue);

Nyt voimme lisätä kolme jäljellä olevaa toimintaa.

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  case SelectedOperation of
    otPlus     : edDisplay.Text := IntToStr(FirstNumber + GetDisplayValue);
    otMinus    : edDisplay.Text := IntToStr(FirstNumber - GetDisplayValue);
    otMultiply : edDisplay.Text := IntToStr(FirstNumber * GetDisplayValue);
    otDivide   : edDisplay.Text := IntToStr(FirstNumber div GetDisplayValue);
  end;
end;

Nyt on toimiva laskin kaikille neljälle toiminnolle:

Intermezzo

Kun kaikki tämä työ on tehty niin nyt on "käyttökelpoinen" laskin. Mutta jotkut asiat eivät ole aivan oikein. Ilmeinen asia on nollalla jakaminen. Ja painikkeet "C" ja "+/-" eivät toimi vielä. Nämä asiat käsitellään seuraavassa osassa.

Katsotaanpa ensin lisätä toista aliohjelmaa, vain huvin vuoksi (no, ei enempää tietenkään :-)):

pascal
  
  private
    { private declarations }
    SelectedOperation: TOperationType;
    FirstNumber: longint;
    SecondNumber: longint;
    doClearDisplay: boolean;
    procedure AddDigit(const pDigit: byte);
    procedure StoreOperation(const pOperation: TOperationType);
    function GetDisplayValue: longint;
    procedure SetDisplayValue(const pValue: longint);
pascal
procedure TForm1.SetDisplayValue(const pValue: longint);
begin
  edDisplay.Text := IntToStr(pValue);
end;

Edellä oleva koodi pitäisi näyttää aika lailla tutulta. Tutustu aliohjelmaan, joka tekee kaikki laskelmat:

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  case SelectedOperation of
    otPlus     : edDisplay.Text := IntToStr(FirstNumber + GetDisplayValue);
    otMinus    : edDisplay.Text := IntToStr(FirstNumber - GetDisplayValue);
    otMultiply : edDisplay.Text := IntToStr(FirstNumber * GetDisplayValue);
    otDivide   : edDisplay.Text := IntToStr(FirstNumber div GetDisplayValue);
  end;
end;

Tämä aliohjelma voidaan nyt yksinkertaistaa.

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  case SelectedOperation of
    otPlus     : SetDisplayValue(FirstNumber + GetDisplayValue);
    otMinus    : SetDisplayValue(FirstNumber - GetDisplayValue);
    otMultiply : SetDisplayValue(FirstNumber * GetDisplayValue);
    otDivide   : SetDisplayValue(FirstNumber div GetDisplayValue);
  end;
end;

Selvittämättömiä asioita

On pari asiaa, jotka pitää vielä tehdä: toteuttaa kaksi painiketta ja tehdä laskin hieman vankempi.

"+/-"- painike

pascal
procedure TForm1.btnPlusMinusClick(Sender: TObject);
begin
  SetDisplayValue(0 - GetDisplayValue);
end;

Katso työn hedelmät! Käytetään uudelleen aliohjelmaa SetDisplayValue ja funktiota GetDisplayValue. Ne toteuttavat vastalukupainikkeen toiminnon.

Kokeile ajamalla ohjelma ja paina "+/-" -painiketta.

"C"-painike

pascal
procedure TForm1.btnClearClick(Sender: TObject);
begin
  SetDisplayValue(0);          // Aloittaa alusta
  SelectedOperation := otNone; // Toimintoa ei ole vielä valittu
  doClearDisplay := false;     // Näyttö on nyt nollattu
end;

Edellä oleva koodi on melko itsestään selvä: Näyttö tyhjentyy (ensimmäinen rivi). Se "unohtaa" oliko vireillä jotain toimintaa tyhjentämällä SelectedOperation muuttujan. Ja kerrotaan ei tarvitse tyhjentää näyttöä, kun uusia numeroja lisätään, koska se oli jo tyhjentynyt aiemmin.

Nollalla jako

Kokeile jotain ihan "päätöntä": aja sovellus ja yrittä jakaa luku 10 luvulla 0. Tällöin sovellus kaatuu. Täytyy varmistaa, ettei tälläistä tapahdu. Se missä tämä tarkistetaan on tietysti paikka, jossa kaikki laskut suoritetaan (TForm1.btnCalculateClick).

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  case SelectedOperation of
    otPlus     : SetDisplayValue(FirstNumber + GetDisplayValue);
    otMinus    : SetDisplayValue(FirstNumber - GetDisplayValue);
    otMultiply : SetDisplayValue(FirstNumber * GetDisplayValue);
    otDivide   : if GetDisplayValue <> 0 then
                       SetDisplayValue(FirstNumber div GetDisplayValue)
                   else
                     begin
                       // Näytä virheviesti käyttäjälle
                       MessageDlg('On mahdotonta jakaa numerolla nolla(0)!', mtWarning, [mbCancel],0);
                       // Resetoidaan laskin. Aloitetaan puhtaalta pöydältä
                       btnClearClick(nil);
                     end;
  end;
end;

Huomionarvoisia asioita:

  1. MessageDlg on toiminto, jolla näytetään lyhyt varoitus / virhe / informatiivinen viesti käyttäjälle.Myös ShowMessage voidaan myös käyttää. Se on vähän helpompi käyttää, mutta ei voi näyttää varoitus / virhe kuvakkeet.
  2. btnClearClick(nil): heti kun virhetilanne syntyy niin täytyy nollata laskin. Toiminta on pohjimmiltaan sama kuin painamalla C-painiketta. "C"-painikkeen painamista simuloidaan suoraan kutsumalla sen tapahtumakäsittelijää.

Ylivuodot

Nyt kaksi asiaa olisi voinut tapahtua:

  1. Sovellus antaa väärän tuloksen (jotain 1674919425).
  2. Sovellus nostaa virhe.

Jos se on ensimmäinen vaihtoehto sitten ylivuoto virheet on poistettu projektista. Ne sallitaan rastittamalla ylivuoto ruutu:

Nyt kun ajaa ohjelmaa uudelleen niin tapahtuu ylivuotoja.

Jos se oli toinen vaihtoehto tämä tarkoittaa, että täytyy lisätä poikkeuskäsittelyä laskimeen. Poikkeuskäsittelyä käytetään estämään sovelluksen kaatumista kun virheitä esiintyy. Tässä tapauksessa halutaan käsitellä aritmeettinen ylivuoto virhe, joka saattaa esiintyä. Koska kaikki laskelmat tehdään yhdessä paikassa, se on helppo napata ylivuotovirheet kiinni.

pascal
procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  // Napataan mikä tahansa ylivuotovirhe
  try
    case SelectedOperation of
      otPlus     : SetDisplayValue(FirstNumber + GetDisplayValue);
      otMinus    : SetDisplayValue(FirstNumber - GetDisplayValue);
      otMultiply : SetDisplayValue(FirstNumber * GetDisplayValue);
      otDivide   : if GetDisplayValue <> 0 then
                     SetDisplayValue(FirstNumber div GetDisplayValue)
                   else
                     begin
                       // Näytä virheviesti käyttäjälle
                       MessageDlg('On mahdotonta jakaa numerolla nolla(0)!', mtWarning, [mbCancel],0);
                       // Resetoidaan laskin. Aloitetaan puhtaalta pöydältä
                       btnClearClick(nil);
                     end
    end;
  except
    on E: EIntOverflow do
      begin
        // Näytetään virheviesti
        MessageDlg('Laskelman tulos oli liian iso laskimen käsiteltäväksi!', mtWarning, [mbCancel], 0);
        // Resetoidaan laskin. Aloitetaan puhtaalta pöydältä
        btnClearClick(nil);
      end
  end
end;

Huomaa, että vaikka poikkeusten käsittely on paikallaan niin sovellus vielä pysäyttää ajettaessa sitä kehitysympäristöstä käsin. Kuitenkin sovellus ainoastaan keskeytetyy ja on yhä aktiivinen. Paina F9 jatkaaksesi. Tämä näyttää toisen pop up-ikkunan, debuggeri ilmoitus ikkuna. Paina Jatka. Nyt ohjelman oma poikkeuskäsittely "heittää" odotetun viestin. Jos sovellus ajetaan kehitysympäristön ulkopuolella niin sitten nähtäisiin vain se viesti mikä lisättiin poikkeuskäsittelyyn.

Hienosäätö

Muista, että tietyssä vaiheessa muuttuja nimeltä SecondNumber otettiin käyttöön. Jos valitaan Suorita / Kokoa valikosta, sitten rakentamisen jälkeen kääntäjä näyttää viestin "Kääntäjän viestit"-ikkunassa, että tätä tiettyä muuttujaa ei koskaan käytetä. Jos klikkaat kääntäjän viestin tekstiä kehitysympäristö avaa lähdekoodieditorissa kohdan, jossa muuttuja on määritelty.

Heti kun demo Laskin käynnistetään nähdään että numero 0 on valittuna näytössä (katso kuva alla).

Tämä on absurdia, koska käyttäjä ei pitäisi voida kirjoittaa mitään kyseiseen kohtaan. Vielä pahempaa, kun hän kirjoittaa jotain siellä, mikä ei ole numero, meidän laskin voisi kaatua! Joten on parempi olla antamatta pääsyä lainkaan tähän. Se pitää korjata.

Suorita ohjelma nähdä näiden muutosten jälkeen.


From the Free Pascal wiki, page "Howdy World (Hello World on steroids)/fi", as it stood on 2019-11-14 after a change by Djzepi, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Versio 2, viimeksi muokannut WikiArchive .