Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Rakenteinen ohjelmointi

Samankaltaiset esitykset


Esitys aiheesta: "Rakenteinen ohjelmointi"— Esityksen transkriptio:

1 Rakenteinen ohjelmointi
Sisältö Taulukot Osoittimet ja viitevälitys Tietueet

2 1. Taulukko Taulukko on rakenteellinen tietotyyppi, johon voidaan tallettaa melkein minkälaisia tietotyyppejä tahansa. Kuitenkin yksi taulukko voi sisältää vain yhdentyyppisiä alkioita. Sisäisesti taulukko on tiettyyn muistiosoitteeseen varattu sarja peräkkäisiä samantyyppisiä muistipaikkoja. Paikkoihin viitataan taulukon indekseillä, jotka juoksevat arvosta 0 arvoon koko-1 ja jotka ympäröidään hakasulkeilla. Alla esimerkiksi char-tyypin taulukko, jonka koko = 5 Osoite indeksi [0] [1] [2] [3] [4]

3 1. Taulukko indeksi 2 riviä ja 3 saraketta
Taulukko voi olla myös useampiulotteinen (dimensioinen). Tällöinkin se voi sisältää vain yhden tyyppisiä alkioita Alla 2-ulotteinen 2x3 ulotteinen char taulukko, joka sisäisesti muodostuu 1-ulotteisesta taulukosta, jonka alkiot ovat kolmen pituisia taulukoita. Visuaaliseti ajatellaan, että taulukko koostuu kahdesta alakkaisesta rivistä, jolloin voidaan “nähdä” 2 riviä ja 3 saraketta.. Osoite indeksi [0][0] [0][1] [0][2] [1][0] [1][1] [1][2] 2 riviä ja 3 saraketta [0][0] [0][1] [0][2] [1][0] [1][1] [1][2]

4 1. Taulukko Taulukon esittely koodissa Syntaksi Semantiikka
1. rivillä esitellään 1-ulotteinen taulukko, jolle varataan koko peräkkäistä muistipaikkaa. 2. rivillä esitellään 2-ulotteinen taulukko, jolle varataan riv*sar peräkkäistä muistipaikkaa. Rivien lukumäärä = riv ja sarakkeiden lukumäärä = sar tyyppi taulu1 [koko]; tyyppi taulu2 [riv] [sar]; Esimerkiksi 1. rivillä esitellään 5-alkioinen merkkitaulukko 2. rivillä esitellään 2-ulotteinen kokonaislukutaulukko, jossa rivien lukumäärä = 10 ja sarakkeiden lukumäärä = 5 char merkit[5]; int luvut [10] [5];

5 1. Taulukko Taulukon alustaminen koodissa 1) int taulu[3]={12,4,5};
Koodissa taulukko voidaan alustaa antamalla listassa arvot. Viereisissä alustuksissa tulee taulukkoon alkiot: 1) 12, 4 ja 5 2) 0, 0 ja 0 12, 0 ja 0 1. rivi 1, 4 ja 5 2. rivi 8, 2 ja 0

6 1. Taulukko 1-ulotteisen taulukon läpikäyminen
Taulukkoja operoidaan peräkkäiskäsittelyllä käyttämällä toistolauseita for( i=0; i < koko; i++) taulu[i]=i*i; printf(”%i\n”,taulu[i]); 1. esimerkissä lasketaan taulukkoon, jossa on koko alkiota, indeksien 0, …, koko-1 neliöt 2. esimerkissä tulostetaan taulukon luvut kuvaruudulle alakkain 6

7 1. Taulukko 2-ulotteisen taulukon läpikäyminen
2-ulotteisia taulukkoja operoidaan kahdella sisäkkäisellä toistolauseella, joissa 1. laskurimuuttuja (i) on rivien ja 2. laskurimuuttuja (j) on sarakkeiden indeksi for( i=0; i < rivit; i++) for( j=0; j < sarakkeet; j++) taulu[i][j]=i+j; { printf(”%i ”,taulu[i][j]); printf(”\n”); } 1. esimerkissä lasketaan 2-ulotteiseen taulukkoon indeksien summat 2. esimerkissä tulostetaan 2-ulotteisen taulukon rivit kuvaruudulle alakkain (jokaisen rivin jälkeen tulostetaan rivinvaihto) 7

8 1. Taulukko Taulukon välittäminen funktiolle
Taulukot välitetään funktioille C-kielessä automaattisesti viitevälityksellä (kts. seur. osio). Tällöin funktion rungossa käsitellään aina kutsuvan ohjelmanosan taulukkoa eikä sen kopiota void nelioi(int taulu[ ], int koko) { int i; for(i=0;i<koko;i++) taulu[i]=taulu[i]*taulu[i]; } Funkion otsikossa muodollinen taulukkomuuttuja määritellään hakasulkeilla. Funktion rungossa taulukon kenttien arvoihin viitataan aivan tavallisesti hakasulkeissa olevilla indekseillä Huom! Funktio käsittelee nyt kutsuvan ohjelmanosan taulukkoa ja neliöi sen alkiot 8

9 1. Taulukko Osoite ’K’ ’a’ ’l’ ’e’ ’\0’
Merkkitaulukot (C-kielen merkkijonotyyppi) char merkit[5+1] = ”Kalle”; Esitellään 6-alkioinen merkkitaulukko ja alustetaan se kolmella C-kielen merkkityypin alkiolla Sisäisesti merkkitaulukko näyttää nyt tältä Osoite ’K’ ’a’ ’l’ ’e’ ’\0’ Huomaa, että kääntäjä laittaa automaattisesti merkkijonon lopetusmerkin ’\0’. Merkkitaulukon koko varataan muodossa 5+1. Tällöin koodista nähdään suoraan merkkijonon maksimipituus 5 ja yksi ”lokero” jää lopetusmerkille

10 1. Tauluko Merkkijonojen käsittelyfunktiot kirjastossa
Standardikirjaston otsikkotiedostossa string.h esitellään hyödyllisiä merkkijonojen käsittelyfunktioita. Ohessa pari esimerkkiä: #include <string.h> char *strcpy(char kohde[ ], char lähde[ ]) int strcmp(char jono1[ ], char jono2[ ]) strcpy kopioi lähde-merkkijonon kohde-merkkijonoon. Palautetaan kohdemerkkijonon osoite strcmp vertaa kahta merkkijonoa aakkostuksellisesti. Vertailu päättyy ensimmäiseen eroavaan merkkiin tai merkkijonon loppuun, jos ne ovat samat. Palautetaan 0, jos merkkijonot ovat samat, 1, jos jono1 > jono2 tai -1, jos jono1 < jono2.

11 1. Taulukot Merkkijonon lukeminen näppäimistöltä
Standardikirjaston (stdio.h) funktio gets lukee komentoriviltä syötetyn merkkijonon, joka voi sisältää myös välimerkkejä ja erillisiä sanoja. #include <stdio.h> char nimet[32+1]; printf(”Kirjoita nimesi (max 32 merkkiä) \n”); gets(nimet); gets lukee komentoriviltä syötetyn merkkijonon ja sijoittaa merkit parametrina annettuun merkkitaulukkoon. Huom! Funktio ei tarkista kohdetaulukon kokoa, vaan se on ohjelmoijan vastuulla. Taulukon ylivuoto saa ohjelman toimimaan täysin odottamattomasti. 11

12 2. Osoittimet ja viitevälitys
Osoittimien käyttö on keskeinen osa C-ohjelmointia. Ohjelmoijan tulee ehdottomasti ymmärtää osoittimien käytön periaatteet. Jokaiselle muuttujalle ohjelmassa varataan kaksi vierekkäistä muistilohkoa: ensimmäinen sisältää muuttujan osoitteen (LVALUE) ja toinen sen arvon (RVALUE). Osoitinmuuttuja on muuttuja, jonka arvo (RVALUE) on toisen muuttujan osoite (LVALUE). Sanotaan, että se osoittaa jotain muuttujaa. Tavallinen merkkimuuttuja, jonka arvo on ’A’ Osoitinmuuttuja Osoite_ptr Osoite1 Osoite1 ’A’ LVALUE RVALUE LVALUE RVALUE 12

13 2. Osoittimet ja viitevälitys
Osoitinmuuttujan esittely ja asetus Tavallinen merkkimuuttuja, jonka arvo on ’A’ Osoitinmuuttuja Osoite_ptr Osoite1 Osoite1 ’A’ char merkki = ’A’; char *merkki_ptr; // tai pMerkki merkki_ptr = &merkki; rivi: Esitellään tavallinen merkkimuuttuja merkki ja alustetaan sen arvoksi ’A’ rivi: Esitellään osoitinmuuttuja merkki_ptr, joka voi osoittaa merkkityyppiin. rivi: Asetetaan merkki_ptr osoittamaan merkkimuuttujaan merkki. * muuttujan nimen edessä  osoitimuuttuja & muuttujan nimen edessä  palautetaan muuttujan osoite 13

14 2. Osoittimet ja viitevälitys
Muuttujan arvon syöttö ja lukeminen osoitinmuuttujalla Osoitinmuuttuja Tavalliset merkkimuuttujat merkki1 Osoite1 ’A’ Osoite_ptr merkki2 Osoite2 ’B’ char merkki1 = ’A’, merkki2 = ’B’; char *merkki_ptr; merkki_ptr = &merkki2; *merkki_ptr = ’C’; merkki1=*merkki_ptr; Muista! ???????? Osoite_ptr nimi_ptr  Sijoitetaan tai luetaan osoittimen arvokenttää (osoitteita) Osoite_ptr Osoite2 Osoite2 ’C’ *nimi_ptr  Sijoitetaan tai luetaan osoittimen osoittaman muuttujan arvokenttää Osoite1 ’C’ 14

15 2. Osoittimet ja viitevälitys
Tiedonvälitys funktioiden välillä Funktioiden tiedonvälitys tapahtuu parametrien avulla. Periaatteessa on kaksi erilaista tapaa välittää tietoa funktioille arvovälitys ja viitevälitys. Arvovälityksessä funktiota kutsuvasta ohjelmanosasta välitetään kutsuparametrien arvot (RVALUE), joista otetaan kopiot funktion muodollisille parametreille. Viitevälityksessä funktiota kutsuvasta ohjelmanosasta välitetään kutsuparametrien osoitteet (LVALUE), jolloin funktio voi käsitellä kutsuvan ohjelmanosan kutsuparametrien arvokenttiä (RVALUE) 15

16 2. Osoittimet ja viitevälitys
Viitevälityksen määrittely ja kutsu int luku1 = 3, luku2 = 5; vaihda(&luku1,&luku2); Kutsuvassa ohjelmanosassa määritellään ja alustetaan kokonaislukumuuttujat arvoilla 3 ja 5. Lisäksi kutsutaan funktiota vaihda, jolle välitetään edellisten muuttujien osoitteet, void vaihda(int *eka, int *toka) { int temp; temp = *eka; *eka=*toka; *toka=temp; } Funkiossa viitevälitys määritellään esittelemällä muodolliset parametrit osoittimina. Funktio vaihda() vaihtaa kutsuvan ohjelmanosan muuttujien (luku1 ja luku2) arvokenttien sisällöt käyttämällä paikallista apumuuttujaa temp. 16

17 2. Osoittimet ja viitevälitys
Esimerkki, jossa arvovälitys ei toimi int luku1 = 3, luku2 = 5; vaihda(luku1, luku2); Tässsä on edellisen sivun esimerkki toteutettu arvovälityksellä. Nyt kutsuvan ohjelman muuttujat luku 1 ja luku2 eivät muutu funktion kutsussa, koska niistä annetaan funktioille vain kopiot niiden arvoista (RVALUE). void vaihda(int eka, int toka) { int temp; temp = eka; eka=toka; toka=temp; } Funkiossa määritelty arvovälitys, jolloin muodolliset parametrit saavat arvokseen kopiot kutsuparametrien arvoista. Nyt funktion toiminta rajoittuu paikallisten muuttujien eka ja toka arvojen vaihtoon ja siten funktio ei toimi siten kuin on sen tarkoitus. 17

18 2. Osoittimet ja viitevälitys
Taulukon välittäminen funktiolle Taulukot välitetään funktioille C-kielessä automaattisesti viitevälityksellä. Tällöin *- operaattoria ei tarvita parametrien esittelyssä eikä taulukon käsittelyssä funktion rungossa void nelioi(int taulu[ ], int koko) { int i; for(i=0;i<koko;i++) taulu[i]=taulu[i]*taulu[i]; } Funkion otsikossa taulukon viitevälitys määritellään esittelemällä muodollinen taulukkomuuttuja hakasulkeilla. Funktion rungossa taulukon kenttien arvoihin viitataan aivan tavallisesti hakasulkeissa olevilla indekseillä Huom! Funktio käsittelee nyt kutsuvan ohjelmanosan taulukkoa ja neliöi sen alkiot 18

19 2. Osoittimet ja viitevälitys
Taulukon välittäminen funktiolle Taulukon nimi on C-kielessä määritelty vastaamaan taulukon osoitetta (LVALUE), jolloin se voi toimia kutsuparametrina viitevälityksessä. int summa, taulu[5]={3,6,1,0,9}; nelioi(taulu,5); void nelioi(int taulu[ ], int koko) { Kutsuvassa ohjelmanosassa taulukko välitetään funktiolle kirjoittamalla kutsuparametriksi pelkkä taulukon nimi. Funktiokutsun jälkeen kutsuvan ohjelman osan taulukko on muuttunut ja se sisältää nyt arvot {9,36,1,0,81} 19

20 2. Osoittimet ja viitevälitys
Osoitinaritmetiikkaa Taulukon välityksessä funktiolle ja sen käsittelyssä funktion rungossa voidaan käyttää myös osoitinta taulukon yksittäisiin alkioihin. Alla edellinen neliöintiesimerkki Paikallinen osoitinmuuttuja ptr saa kutsuparametrin osoitearvon void nelioi(int *alku, int koko) { int *ptr = alku; while(ptr-alku<koko) *ptr=(*ptr)*(*ptr); ptr=ptr+1; } Osoitteet ovat peräkkäisissä muistipaikoissa [alku] … [alku+koko] Osoitetun muuttujan (taulukon alkion) arvoa käsitellään *-operaattorilla Osoitinaritmetiikka = osoitinta siirretään muistipaikasta seuraavaan lisäämällä osoittimen arvokenttään (osoitteeseen) 1 20

21 2. Osoittimet ja viitevälitys
Osoittimet ja merkkijonot Osoittimien avulla voidaan käsitellä myös merkkitaulukkoja eli merkkijonoja. Seuraava funktio laskee annetun merkkijonon pituuden Paikallinen osoitinmuuttuja ptr saa kutsuparametrin osoitearvon unsigned pituus(char *alku) { char *ptr = alku; while(*ptr != ’\0’) ptr=ptr+1; return ((unsigned)(ptr-alku)); } Testataan onko osoitetun muuttujan arvo merkkijonon lopetusmerkki osoitinta siirretään muistipaikasta seuraavaan lisäämällä osoittimen arvokenttään 1 Palautetaan viimeisen merkin osoitearvo – 1. merkin osoitearvo 21

22 3. Tietueet Tietuetyyppi ja tietuemuuttuja
Tietue struct on rakenteellinen tietotyyppi, joka toisin kuin taulukko voi sisältää useampia tietotyyppejä eli tietokenttiä. Tietueita käsitellään tietuetyypin muuttujilla ja tietueen kenttiä muuttujaan liitettävällä pisteoperaattorilla (.) Huom! Tietueen kentät eivät välttämättä ole peräkkäisissä muistipaikoissa, vaan tilanvaraukset ovat laitekohtaisia Osoite1 120030 LVALUE ”Kalle Virtanen” 32 ”Jokiväylä 11” RVALUE 22

23 3. Tietueet Tietuemuuttuja ja tietuetyyppi
Tietuemuuttuja voidaan määritellään kahdella eri tavalla Kuvataan tietueen rakenne muuttujan esittelyn yhteydessä Määritellään ensin globaalisti uusi tietuetyyppi, jonka yhteydessä kuvataan tietueen rakenne. Jatkossa funktioissa tämän tietuetyypin muuttujat esitellään käyttämällä niiden tyyppinä määriteltyä uutta tietuetyyppiä. 23

24 3. Tietueet Tietuemuuttujan määrittely ilman tietuetyyppiä
Kuvataan tietueen rakenne muuttujan esittelyn yhteydessä struct {kenttien_määrittely} muuttujanimi; int main(void) { struct int id_nro; char nimi[32+1]; unsigned ika; } henkilo ; Tietuemuuttujan henkilo esittely Esittelyssä kuvataan tietueen rakenne. Kentät esitellään kuten paikalliset muuttujat, mutta mitään alkuarvoja ei kenttiin voi rakenteen esittelyssä määrätä Tämä tapa on hyvä, jos muita samanlaisia tietuemuuttujia ei tarvita 24

25 3. Tietueet Tietuetyypin määrittely
Määritellään ensin uusi globaalinen tietuetyyppi, jota käytetään tietuemuuttujan esittelyssä. struct TYYPPINIMI {kenttien_määrittely}; HENKILO tietuetyypin määrittely globaalisti (yleensä heti esikääntäjädirektiivien jälkeen) Funktiossa tietuetyyppiä HENKILO olevien tietuemuuttujien isa ja aiti esittely Tämä tapa on hyvä, jos tarvitaan useampia saman tyyppisiä tietuemuuttujia Huomaa puolipiste tietuetyypin määrittelyn jälkeen struct HENKILO { int id; char * nimi[32+1]; } ; int main(void) { struct HENKILO isa, aiti; 25

26 3. Tietueet Tietueen alustaminen koodissa ja kenttien käsittely
int main(void) { struct HENKILO isa, aiti; aiti.id=123; strcpy(aiti.nimi, ”Maija”); isa ={321,”Matti”}; /* C++*/ Paikallisen tietuemuuttujan tietueen kenttiä käsitellään pistenotaatiolla. Tietueen kenttien alustaminen voidaan kääntäjästä (C++) riippuen tehdä myös aaltosulkeilla rajattuna listana 26

27 3. Tietueet Tietueen kopioiminen int main(void) {
struct HENKILO kalle1, kalle2; kalle1.id=123; strcpy(kalle1.nimi, ”Kalle”); kalle2 = kalle1; Tietuemuuttujan kenttien sisältö voidaan kopioida toiselta samantyyppiseltä tietuemuuttujalta sijoitusoperaattorilla 27

28 3. Tietueet Tietue taulukon alkiona int main(void) {
struct HENKILO hlot[2]; hlot[0].id_nro=111; strcpy(hlot[0].nimi,”Kalle”); hlot[1].id_nro=222; strcpy(hlot[1].nimi,”Ville”); Määritellään 2-paikkainen taulukkomuuttuja hlot, jonka alkiot ovat HENKILO tyyppisiä tietueita Taulukon alkiona olevaa tietuetta käsitellään siten, että indeksoitu taulukon alkio toimii tietueen nimenä. 28

29 3. Tietueet Tietue tietueen kenttänä int main(void) {
struct PISTE {float x; float y;} p1; struct {struct PISTE kp; float sade;} ympyra; p1.x = 0; p1.y = 0; ympyra.sade=5.3; ympyra.kp.x=5; ympyra.kp.y=2; Ensimmäisellä rivillä esitellään samalla kertaa sekä tietuetyyppi PISTE että samantyyppinen tietuemuuttuja p1. Seuraavalla rivillä esitellään tietuemuuttuja ympyrä, jonka rakenteeseen kuuluu PISTE tyyppinen tietuemuuttuja kp sekä float tyyppinen muuttuja sade. Ympyrän kenttiin viitataan pistenotaatiolla, keskipisteen tapauksessa myös sisäisen tietueen kenttiin. 29

30 3. Tietueet Tietuetaulukon välittäminen funktiolle int main(void) {
struct HENKILO hlot[2]; /* taulukon tietueiden alustus */ tulosta (hlot, 2); } void tulosta (struct HENKILO hlot[ ], int koko) { int i; for(i=0;i<koko;i++) printf("%s %i\n",hlot[i].nimi, hlot[i].id_nro); Tietuetaulukko välitetään funktioille samalla periaatteella kuin muutkin taulukkotyypit eli viitevälityksellä. Funktion rungossa tietueita käsitellään samalla pistenotaatiolla kuin kutsuvassa ohjelmassa, missä taietueet on luotu. 30

31 3. Tietueet Tietueosoitin int main(void) { struct HENKILO jokuHlo;
/* taulukon tietueiden alustus */ alustaTietue(&jokuHlo); } void alustaTietue(struct HENKILO * hlo) { strcpy(hlo->nimi,""); hlo->id_nro=0; Kun tietuetta käsitellään osoitintyyppisellä muuttujalla, tietueen kenttiä käsitellään pisteoperaattorin sijasta nuolioperaattorilla ->. Tässä alustetaan tietue ”nollahenkilöksi” eli henkilöksi, jolla ei ole todellisia henkilötietoja, mutta kentät on kuitenkin alustettu, joten niitä voidaan lukea ilman ohjelman kaatumista (testausvaiheessa voi tarvita). 31


Lataa ppt "Rakenteinen ohjelmointi"

Samankaltaiset esitykset


Iklan oleh Google