Kaukonäkömaa eli C++ tutti numero 5 =================================== OSA V Viides osastomme mietiskelee menneitä ja murehtii tulevia. Lisäksi kurkistamme rekisteröidyn tavaramerkin konepellin alle, juhlimme vuoden onnistuneita juhlia, nautimme maalaissaasteista, tallomme naapurin petuniat ja syömme hullun lehmänhoitajan vaimon leipomia pipareita. Löysätkäämme kiristävät solmiot, laittakaamme jalat pöydälle, pää kattoon ja aloittakaamme! Disclaimer ---------- Tässäpä ei ole disclaimeria tai mitään muuta varoitusta, koska sellaiset on todettu täysin turhiksi. Tai no ei oikeasti ole, joten kaipa tähän pitää pieni sitten kirjata. Enpäs siis ota vastuuta esimerkkien toimivuudesta tai asioiden oikeellisuudesta. Sanastomme osaajista hetkellinen huomionaihe tehkäämmä. Kellertävissä pyhäasusteissaan hyppivätten he ympärse niittyjä perse punaisena tietämättä ruokansa olevan eläimen persettä. Reikä vain poistettuna kosmeettisenpuoleisista syistä, ja notteivat ymmärtäisi, paljonko on kello. Samanaikaisenpuoleisesti herraskansansa makoilee kotopuolessaan lämmin keinoketun nahkaturkkitossut jalassaan syöden helmeilevää hernepitoista kurmeeruokaa ja juoden lasillisen konjamiinipulloaan. Sisältöhän tarjottihin vierahille, joten isäntään tyytyminen. Naama auringon muotoisena ja kokoisena loistaen voivatten kutsua itseään melkein oppineemmanpuoleiseksi, ylemmäksi sivistyshenkilöitymäksi, jonka sanaan luottavat sokeasti näkevät ihimisenpuoleiset kuin Taavetin jouluruoan tähteisiin. Viikunaa unohtamatta. Syödään viheriö. Tulevaisuuden maan tieteelle, unohtamatta biologiaa, matikkaa, lohta, puista taimenta tai maantiedettä. Kaivakaamme punainen lanka ompelulaatikosta ja tehkäämmä siitä punaiset villasukat, sillä villapaitaan ei tuosta langasta riitä, ja pipon teimmä jo yksi osa takaperin, ja jotkut jopa oikeinpäinkin. Mutta siis, esimerkkilöiden lisäksi, ei kielellisestä saannista tahi annista (eikä myöskään Annista) takeita luettavuuden, ymmärrettävyyden tahi olemassaolon oikeutuksen muodossa, anneta. Ei edes sanastomme osaajahenkilöt eikä heidän lähi-, kauko- tai ei-sukulaiset. Sinne, missä lehmämme juovat ja kissatkin osaavat heiluttaa häntää. Tuhannen voltin ankkapaistia vaahtosammuttimen aromikkaalla makuvivahteella! Ja kaikille tiedoksi vielä, että tätä saa levitellä vapaammanpuoleisesti, aivan kuten naapurin koira saa levitellä omia antejaan, kunhan ei ihan julkeasti mene levittelemään. Tai no kyllä tätä saa levittää kun ei sitä ole toistaiseksi laissakaan kielletty. Tai no on, sillä tämähän on teos ja tekijänoikeuden alainen, mutta kun näistä teoksista saa määrätä se tekijänoikeuden haltija, joka sattuu olemaan minä, niin minäpä päätänkin, että tätä saa levitellä. Ei kyllä menis läpi tämä selitys siinä naapurin koiran tapauksessa, vaan vankilaan pistäsivät tai ainakin sakkoja antasivat. On kyllä ihme touhua. Mutta enpä voi mitään, niin on joku minua viisahampi mennyt päättämään. Tosiaankin semmoinen lisäys vielä, että se paritus on kieällettyä niin eipä mennä sutenööriperkeleet perimään tämän levityksestä maksua elikkäs ilmahteeksi pitääpi siirrellä muille immeisille. Puhukkonää totta vai ihan palturia? ----------------------------------- Kunpas heilläsä, kuten meillänsä oikeutemme vaieta on, niin miskemme sitten puhelisi vihreistä niittyhistä tahi ole hiljaisemmanpuoleinen? Tai miksei sitten tehdä molempia asioitansa? Seuraa kolmen rivin hiljaisuus! Noin! Nyt sitten puhellaan vaikkapata niistä vihrehistä niittyhistä. Kun kuitenkin tuolla lumen allansa semmosia on hehtaarikaupallansa. Siellä sitten juuri joskus keväällä syntyneiset vasikkaiset hyppivätten innoissansa. Vähän kuin C++ tuttia imeskelleet lapsokaiset, jotka pääsevät ensimmäistä heipähei maailma -ohjelmaansa kirjailemaan editoriinsa ja kääntelemäänvääntelemään ja saamaan kilometrikaupallansa virheilmoituksia. Tuosta taas jotenkin hassuloisella tavalla tuli mieleeni, notta pitäisi varmaan tätä tutinpuoleista jatkeskella elikkäs puhukaamma sitten totuudenpuoleisista tahi noista epätotuuksistansa. Kun meilläpä onkin tällainen aito boolean tyyppi, toisin kuin C:ssä, jossa pitääpi kokonaisluvusta väännellä totuusarvojansa. Niin, tämän tyypin nimi on ylläettäen bool ja sillä voipi olla kaksi arvoa: false tahi true, joista epätotuutta ja totuutta vastaavasti nuo ilmaisevatten. Ja tuota falsea vastaapi numero nolla (0) ja totuudenpuoleista nummero yksi (1). Testailu käydään yksinkertaisesti esimerkkilöisesti if-vermehellä tahi jollakin muulla ehtoa hyväksyvällä vermehellänsä. Niin, ja nuo vertailunpuoleiset palauttavatten sitten totuustyyppiänsä. Esimerkkiä. ---[ totuus.cpp ]--- #include using namespace std; int main() { //Määritellään totuusarvoja bool a = false; bool b = true; //Määrittelemätön arvo. Koska bool -tyyppi varaa 8 bittiä, voi tämän //arvo tulostaessa olla mikä tahansa arvovälillä oleva arvo bool c; //Jos muuttujalle määritetään jokin arvo, tulee arvoksi 1 eli true bool d = 42; cout << a << " " << b << " " << c << " " << d << endl; int i; cout << "Annappa jokin kokonaisluku: "; cin >> i; c = i<5; cout << "Antamasi numero oli "; if (c) cout << "pienempi"; else cout << "suurempi tai yhtäsuuri"; cout << " kuin 5" << endl; cout << a << " " << b << " " << c << " " << d << endl; return 0; } -------------------- Nyt sitten vielä viimeiset jouluiset vanukkaat suuhunsa ja uutukaisentapainen otsakeaiheinen jossain vaiheessansa tuohon pitäisi kirjata. Niin ja lammas. Keskustelunpuoleinen aihe olkoon, millainen olisi maailma, jos satusediä kasvaisi puissa? Tahis, jos alkaisi yleismaailmallinen kemian vallankumous, jossa ainoaksi Viralliseksi oppiaineheksi hyväksyttäisiin vain kemia? Tosin tällaisentapaista ei pitäisi tapahtuman, vaan toisittensapäin, sillänsä luontoiset tieteiset ei oikeastinsa olekkaan mitään erillisiä vermehiä, vaan niitänsä pitäisi käsitellä yhtenä aineena. Tosin tämä ei ole hyvä suuntaus, olkoot nämä sitten saman asian tulkintaa erillisiltä kanteiltansa, mutta tietojansa voisi yhdistellä ja sovellella. Siis mietitäänpä ihmisenkaltaista otusta, joka päättääpi matemaattisen kaavaisen perustella, notta tämä onpi paras ratkaisunsa tuohon asiaan, jota voitaisiin vaikkapa x:llä merkkilöidä. Muttas tämä luontoinen esimerkiksinsä on ongelmiaan ratkaissut hieman vähätellen jonkin verran pidempään kuin tuo ihmis-rukka, joka suurissa pienissä aivoissansa uskoopi olevansa hänet luonutta luontoista etevämpi ja kätevämpi ja keksivänsä vaikkansa mitä! Niin, muttas voisi olla viisaampi hän. Luonnossansa, jopa itsessänsä on rakenteita, joita mallintamalla ja soveltamalla saisi kaikennäköisenmuotoista hassua aikaan. Jonkinlaiset ihmisolennot ovatten tällaiseen jo ruvenneet ja suuruspäissään tuhonneet omat menestymismahdollisuutensa muotoiset. Esimerkkilöidään esimerkiksi kultaisen leikkauksen soveltamistansa, joka on mennyt joissakin asioissansa melkeistä humoristisemmanpuoleiseksi räpeltelyksensä. Eipäs tulekaan semmoisista mitään, ehei! Kun ei immeisolennon pitäisi itseään luuleman liian viisahaksi vaan toimiskella annetuilla ehdoillansa ja sovellella tuota vain sopivissa mittasuhteisissaan kuitenkaan suureltaosin sitä muuttamatta, vaikkakin se sallittakoon jaloissa tarkoituksissaan toimiville. Lienee paremmanpuoleista lopetella tähän, sillä C++ kieleisestä puhukaamma! Tosin mielessänne pidelkää, että ohjelmiansa tuletta tekemään, joissa ongelmiakin esiintynee, niitä ratkeskelkaa tahi valmiita ratkaisunmuotoisia muualta etsiskelkää. Itse turhemmanpuoleisesti älkööt yrittäkö pyöriä uudelleen keksiä tahi sen kulkemaa matkaansa turhaan sätehen kerronnaisilla laskeskelemaan. Suut rullallensa ja rulla suuhun! Seuraaava aiheinen! Tyyppi hei! ----------- Voi pyhä Sylvi ja ei-niin pyhä Anna-Liisa. Tiedostaaksesi herra Heinänuhanenän oikean olemuksen hänen verhottuaan itsensä naamiaisvieraan asuun ja livahdettuaan naapurin kekkereillensä kuokkimaan, sinun tulee suorittaa tunnistustoimenpiteitä. Kaikiltansa vaan naamiot poies ja kasvonvertailua muistikuvaansa herra Heinänuhanenästänsä. Tahi sittensä henkilökortistansa tahi muusta asikirjapaperintapaisesta henkilöisen tunnistus. Niin, C++ kurkistelee naisten hameenhelmojen alapuoleisen lisäksi myös tyyppiinsä ja kertoopi, notta millainen otus, olio tahi muu tyyppi sieltä takaisinpäin vilkutteleepi. Tätä kutsuloidaan RTTI:ksi elikkäs Run Time Type Identification tahi jotain tuonnepäin. RÄTTI on sitten ihan eria asia, mutta kukaan ei estele sinua tuollaiseksi sitä lueskelemaan. Mutta pyyhitäänpä hieman RTTIllä lattiaa ja tutkitaan tuota RÄTTIä. Noin. Olioinenhan on päivän sana ja ehkä myös toisen. Tai no ei se taida olla, mutta puhutaanpa olioisista. Siis kun oliollansa on tyyppi ja sitä tunnistelemaan lähdetään, niin typeid() on mukava funktioinen. Sillekkös olion antaa olioisen tai oikeastaan minkä tahansa muuttujan nimisen, niin se palauttaapi type_info -luokkaisen ilmentymäisen, joka kertoo kaikkea kivaansa. Tärkeimmät metodinsa tuolta lienee sittensä name(), joka kertoopi C-tyylisenä merkkailujononaan tuon vermehen nimen (luokan- tahi muu tyypinnimi). Sitä voipi myös vertailla == ja != operattoreillansa. Niin, yksi esimerkki kertoo enemmän kuin yksi kuollut vainaja talouden kehityksestä. ---[ tyyppi.cpp ]--- #include #include using namespace std; //Määritellään muutama luokka tunnistelua varten class luokka { public: virtual string a() { return "yksi"; } }; class luokka2 : public luokka { public: virtual string a() { return "kaksi"; } }; class luokka3 : public luokka2 { public: string a() { return "kolme"; } }; class luokka4 { public: string a() { return "neljä"; } }; int main() { //Tavallisia tyyppejä int a; double b; //Ei ihan perustavallinen tyyppi string c; //Luokkia luokka d; luokka2 e; luokka3 f; //Osoittimia luokkiin luokka* g = &d; luokka2* h = new luokka3(); luokka3* i = new luokka3(); luokka* j = new luokka2(); luokka4 k; luokka4* l = new luokka4(); //Tulostellaan tyyppi-informaatiota cout << typeid(a).name() << " " << typeid(b).name() << " " << typeid(c).name() << endl << typeid(42).name() << " " << typeid(3.141).name() << " " << typeid("Testi").name() << endl << typeid(d).name() << " " << typeid(e).name() << " " << typeid(f).name() << endl << typeid(g).name() << " " << typeid(h).name() << endl << typeid(*g).name() << " " << typeid(*h).name() << endl << typeid(i).name() << " " << typeid(j).name() << endl << typeid(*i).name() << " " << typeid(*j).name() << endl << typeid(k).name() << " " << typeid(l).name() << endl; //Tulostaa: Samat if (typeid(g)==typeid(j)) cout << "Samat" << endl; else cout << "Eri" << endl; //Tulostaa: Eri if (typeid(h)==typeid(i)) cout << "Samat" << endl; else cout << "Eri" << endl; //Tulostaa: Eri if (typeid(h)==typeid(*h)) cout << "Samat" << endl; else cout << "Eri" << endl; //Tulostus riippuu toteutuksesta, mutta tulostettava nimi on jokin //type_info -luokan johdannainen cout << typeid(typeid(a)).name() << endl; cout << typeid(typeid(d)).name() << endl; //Tyyppejä voi tunnistella myös dynamic_cast:lla, sillä se varmistuupi //ensin, notta tyyppimuunnos on mahdollinen ja sitten vasta muuntaapi. //Yllättäen sopiipi tilanteisiin, jossa pitää tarkistella ja muunnella. if ((g = dynamic_cast(&d))) cout << "Ok, " << g->a() << endl; else cout << "Virhe" << endl; if ((g = dynamic_cast(&f))) cout << "Ok, " << g->a() << endl; else cout << "Virhe" << endl; if ((g = dynamic_cast(j))) cout << "Ok, " << g->a() << endl; else cout << "Virhe" << endl; //Tästä minulla kääntäjä varoittelee, ettei tämä voi koskaan onnistua if ((g = dynamic_cast(&d))) cout << "Ok, " << g->a() << endl; else cout << "Virhe" << endl; return 0; } -------------------- Tunne tyyppisi! Tiedä heikkoutesi! Nuole rautatankoa pakkasella ja revi kielesi irti. Ruoka maistuu eri tavalla sen jälkeen (paitsi, jos ruoka on maistunut huonosti tai ei ollankaan tätä ennen). Syntymäpäivälahjavinkkejä nyt vessapaperin sisäpinnalta. Hetkenä minä hyvänsä, myös pyyhinnän jälkeen. Aimo A. raahasi okametsään AA-kattoa Nemoille. Elli, omena! Ottakaa nääs te makoisa haara omia! Moniperintä ----------- Tänään on siis lahjahevosen suut katselmuksessa. Kuinka sulttaanikokelas, sheikki Al Ahmed Jared Haleeba, suhtautuu moniavioitumiseen. Haastattelussa myös hänen kolmekymmentä vaimoaan! Melkoista moniperintää saavat harrastaa he sheikin kuoltua! Muttas mepäs harrastelemme moniperintään jo nyt ja C++:n kanssa. Tai no luokkien. Niin, kun tottumaan olemme menneet, että luokkia voi periyttää, muttas kun perijättären ei tarvitse kauaa suremaan jäädä vaan uusi sulhoehdokkuus näkyypi jo horisontissansa. Hiiohoi, ja rommia mul' on! Niin, siis periytettäviä luokkiahan voipi olla useamman kappaletta, jolloin tämä uusi perivä luokka saapi kaikkien ominaisuutensa. Ehtonansa on, että metodiensa pitää olla yliladattavissansa, elikkäs samannimisiä saapi näissä ollansa, mutta erimääränsä tahi erityyppisiänsä parametrejä hälle tarjottava. Tietystinsä siellä privaattihuoneessansa saapi olla mitä tahansa, joten siis julkeillensa metodeillensa ja muuttujillensa päteepi tämä. ---[ peri.cpp ]--- #include using namespace std; //Määritellään luokkaA class luokkaA { public: //Määre inline tarkoittaa, että metodikutsun sijasta kyseinen koodi //pitäisi kääntää suoraan sen kutsun kohdalle. Tämä on tehokkaamman //puoleinen tapa ja säästää varsinkin yksinkertaisissa metodeissa //turhalta kutsulta. Olkon muuttuja a luokkaA:n esiintymä: //int i = a.a(2); tulee int i = 2*2; Vältytään turhalta kutsulta ja //useimmat (ellei kaikki) kääntäjät pystyvät vielä optimoimaan tuon //int i = 4; Ilman inlineä jouduttaisiin tosiaan kutsumaan aliohjelmaa //ja välittää sille parametri (työntämällä se pinoon) ja palauttaa tulos inline int a(int x) { return 2*x; } virtual int b(int x) { return x*x; } }; //Toinen luokka class luokkaB { private: //Määre volatile kertoo, että tätä voidaan muuttaa tavalla, jota //kääntäjä ei välttämättä voi havaita tai hallita. Kääntäjä huomioi //määreen siten, ettei optimoi tähän vaikuttavaa koodia kovin //voimakkaasti. volatile int num; public: inline void c(int x) { num = x; } inline int d() { return num; } }; //Moniperivä luokka. Perii sekä luokkaA:n että luokkaB:n ominaisuudet. class luokkaC : public luokkaA, public luokkaB { public: inline int e(int x) { return d()*a(x); } }; int main() { //Määritellään pari osoitinta luokkaA *a; luokkaB *b; //Ja yksi moniperivän luokan ilmentymä luokkaC c; //Peritty luokkaB:ltä c.c(6); //Kutsutaan eri metodeja cout << c.a(4) << " " << c.b(4) << " " << c.d() << " " << c.e(4) << endl; a = &c; b = &c; //Voidaan käyttää vain kyseisen luokan metodeja, eli //luokkaA: a() ja b() sekä luokkaB: d() ja c() cout << a->a(4) << " " << a->b(4) << " " << b->d() << endl; //Never underestimate the power of tyyppimuunnos! Eli tyyppimuunnoksella //saadaan nuista luokkaC-tyyppisiä taasen ja metodien kutsunta //onnistuupi. cout << ((luokkaC*)a)->a(4) << " " << ((luokkaC*)a)->b(4) << " " << ((luokkaC*)a)->d() << " " << ((luokkaC*)a)->e(4) << endl; return 0; } ------------------ Nyt kun on peritty rikkaat tädit, kummit ja kaimat sekä kaikki muut, niin voimmekin mennä etelän lomallensa nautiskelemaan kirkkahasta. Siis aurinkoisesta. Pois mielisestä huonoiset ajatuksenpuoleiset! Suuhun ne laitetaan! Pörröötiö. Pyyhkikääpä nyt silmälasinne (jos sinullansa ei ole silmälaseja, lue ohjastustansa osaisesta nummero kaksi) ja jatkakaapa matkaanne kohti seuraavanpuoleista kappaleista, jossa pölisemme kuin matot, katsomme maailmaa naapurin tekosilmin ja herkuttelemme ajatuksella lämpimästä pullasta! Tuonne käymmä. Lisää Äs Tee Ällää ------------------ Elikkätä, kun tuolla on kaikenlaista ihmeellistä, kummallista ja hassua, niin kerrotaanpa hieman lisää kahdenpuolisesta asiaisesta, kuten pinosta, jonosta, listasta, elefantista, mammutista, siperianharmaatiikeristä ja kamelista. Näitä kun voipi käytellä eriävällä tavallansa eriäviin, tahi miksei jopas samoihin, tarkoituksiinsa. Murmeliopiston lehmävainaatkin hyppivät kattoon ja syöpi viimeisen ateriansa uudestaan, kunhan osaavatten sen lantakasastaan eroitella. Suurehkon toimintapainotteisen iltapäiväisen ratoksi, katsellaan hetki seuraavaa kirjainta ja huudetaan "örööasn möealneaa", joka tarkoittaa "syökää minun leipäni, ja juokaa kaikki viinini, mutta C++ tuttiini ette perkeleet koske!" jo lähes unohtuneella öröälääsiän kielellä. Niin siis joo. Elikkätä, pino (first in, last out) toimiipi rakenteena, jossas joo. Tätä jaksa selitää, kun kaikki enklantia osaavat pystyvät tuosta sulkeisrakenteesta tarkoituksenmukaisuuden selviöimään. Kerronpa sitten tämän kappaleen verran tennispallosta. Tennispallo on pyöreä, keltainen ja se on ontto sisältä. Siinä on yleensä valkeat saumat ja sitä lyödään tennismailalla. Tennispallojen sielunelämää ei paljoa tunneta, sillä ne normaalisti vain pysyvät paikoillaan liikkumattomina. Joskus ne kuitenkin innostuvat vierimään pitkin lattiaa tai muuta pintaa. Ne näkee liikkessä myös silloin, kun niitä lyödään mailalla. Tästä tennispallo on tullut tunnetuksi ja tästä niiden kidutusnäytöksistä on tullut suurta huvia herrasväen keskuudessa. Siinä tennispalloja lyödään kaikin voimin, jolloin ne lähtevät kiitämään karkuun kuin päätön kana. Niiden epäonneksi toisessa suunnassa on toinen kiduttaja, joka lyö niitä uudestaan. Muiden hämäykseksi tästä on tehty kisailumuotoista, jossa kiduttamaan kykenemätön osapuoli tuottaa vastustajalleen pisteen. Paras kiduttaja julistetaan kolmieräisen kidutussession voittajaksi. Noin, nyt sitten seuraava aihe! Joopati, elikkä jono (first in, first out tai last in, last out) onpi rakenne, jota tavataan luonnossa muun muassa pankkien konttoreissa, vähittäistavaraliikkeissä, lippukassoilla, köyhien ruoka-avussa, rikkaiden ruoka-avussa, lääkäripalvelun luona, muiden palveluiden luona ja ylipäätään kaikkialla, missä vaan on ihmisotuksia. Eikäs aina tarvita edes ihmisotusta, sillä muutkin luontokappaleiset osaavatten jonottaa, mutta näillänsä ihmisotuksilla jonottaminen on lähes pakonomaista toimintaa, vaikkakin useammat vihaavat jonottamista. Ihmiset ovatkin keksineet uusia jonomalleja, kuten etuilujonon (first in, possible first out, but not necessary, if second or any later comes first out), jononvaihdon (first in, first out, but last in may not come out at all, because he changes to another queue, which he believes to get him out quicker), uusintajonon (first in, first in again), lahjontajonon (first in, first corrupted), kiireellisyysjonon (first in, first out, if not last in, first out) (sukua etuilujonolle, mutta tässä etuilu tapahtuu koko jonon ohi ja hyväksytysti), yhtäaikaisjonon (first in, out within x first), ikuisuusjonon (first in, never out), melkein ikuisuusjono (last in, possible never out), vitutusjono (first in, pissed out), olematon jono (not in, not out), palvelujono (last in, tomorrow again last in, hopefully some day out), kertyvä jono (in, never out), raha-automaattijono (first in, first robbed), autojono (first in, first passed over), ynnä muita. Mutta tutustutaanpa näiden mallien hyödyntelyyn. ---[ pinojono.cpp ]--- #include #include #include using namespace std; int main() { //Int-pino stack si; //Työnnetään pinoon arvoja for (unsigned int i=0; i<10; i++) si.push(i+1); cout << "Pinon koko: " << si.size() << endl; //Tyhjennetään pino ja tulostetaan sen arvot while (!si.empty()) { //Lukee päälimmäisen arvon cout << si.top() << " "; //Poistaa päälimmäisen arvon si.pop(); } cout << endl; //Int-jono queue qi; //Työnnetään jonoon arvoja for (unsigned int i=0; i<10; i++) qi.push(i+1); cout << "Jonon koko: " << qi.size() << endl; cout << "Viimeinen arvo: " << qi.back() << endl; while (!qi.empty()) { //Lukee ensimmäisen arvon cout << qi.front() << " "; //Poistaa ensimmäisen arvon qi.pop(); } cout << endl; return 0; } ---------------------- Jonottelua vaan ihmettelemään sitten läheisen marketin kassalle! Tahi ihmettelemään, notta miten eläimet syövät toisiaan! Niin, siitä tosiaan piti maininnantapainen heitellä ilmoille, notta prioriteettijonoinen on olemassansa myöäs ja siinäkös on metodi top(), jokas palauttaapi suurimmaisen prioriteettisen omaavan vermehen. Muttas koskas jotain rajantapaista tähänkin tuttivermeeseen pitää vetään, niin vedetään se tähän, eikä mennä ihan kaikkea hassuloista selittelemään. Niin, notta prioriteettisjonoinen jääpi ulkoiselle puolelle. Muttas onneksi on vieläs yksi vermeinen, jottas voidaan siihen siirryskellä. Niin tuo yksis vermes on karttas eli map. Tuo onpi assosiatiivinen listainen, jossas siis avaimena voipi olla jokin muu kuin nummeroarvoinen, kuten tavanomaisessa listassaan. Ja koska nyt ei enää pölistä, sillä meidät on pöllytetty ulkona ja ripustettu telineelle pakkaseen kolmeksi tunniksi, joten voimme siirtyä hetikohta tähän aiheeseensa ja esimerkkilöisiin. Niin, me voimme, mutta teemmekö me niin? Paljonko on monta? Onko vielä jotain kysyttävää? Kauanko hetki kestää? Miksi vielä kyselemme? Milloin on ruokinta-aika? Onko tänään muuta ruokaa kuin matoja ja siilieläimen piikkejä? Haukkuuko halli vai onko se sittenkin naapurin koira? Suunta on. Maanantai-apina ja Aamu-gorilla löivät vetoa, huhujen mukaan herra Veto on haastamassa heidät oikeuteen! Olisivat hekin käyttäneet karttaa, niin eivät olisi eksyneet! Rakentakaamme jälkiviisaana omat karttamme, jalkaviisaat eivät siihen pystykään, vaikkakin jalanjälkiviisaat ovat oikealla tiellä oppiakseen tämän taidon, niin mikseivät sitten jalkaviisaatkin joskus? Ihmettelemään jäämmä. ---[ kartta.cpp ]--- #include #include using namespace std; int main() { //Voidaan määritellä omia tyyppejänsä tahi vermehiä, jotka korvataan //sitten tuolla jossain. Eli syntaksi: typedef korvaavat vermeet määre //Helpottaa varsinkin pidempiä vermehiä kirjoitettaessa typedef map M; //Määritellään kartta. Typedefin ansiosta kenties yksinkertaisempi //määritelmä? Perässä kommenteissa rivin tulos tahi oikea muoto. M m; //map m; //Täytetään kartta arvoilla m[string("Matti Meikäläinen")] = 10; m[string("Maija Meikäläinen")] = 20; m[string("Erkki Esimerkki")] = 42; m[string("Oskari Olematon")] = 0; m[string("Heikki Harmiton")] = 66; cout << "Koko: " << m.size() << endl; //Haetaan kartan arvo cout << "Erkki Esimerkki: " << m[string("Erkki Esimerkki")] << endl; //Haetaan olematon arvo, kun tuota ei ole, niin sille lisätään tyhmä //arvo eli tässä tapauksessa nolla (0). Eli ei kovin hyväinen tapa. cout << "Erki Esimerkki: " << m[string("Erki Esimerkki")] << endl; cout << "Koko: " << m.size() << endl; cout << "Iteroidaan:" << endl; //Parempi tapa on iteroida karttainen läpi, tässä voidaan myös vertailla //jotain hassuntapaista, jos tiettyä arvoansa etsitään. M::iterator i = m.begin(); //map::iterator i = m.begin(); while (i!=m.end()) { cout << i->first << ": " << i->second << endl; i++; } return 0; } -------------------- Joopajoo. Juokaamme lisää virvokkeenpuoleista ja siirtykäämmä hetkisen päästä takaisin tännepäie. Jöppööti. Noin. Hetki. Olen poissa. Näin. Paluuntehneenä on helppo hymyillä! Saati sitten kirjoitta tutoriaalia, sillä poissaollessani on melkoisen hankala tätä kirjoittaa, kun ei nuo mobiilit elikkäs langattomat ja/tahi liikkuvaiset muistiinpanovälineiset kovin käteviäpäteviä ole tällaisen tyyppiseen kirjailemiseen. Tai no kyllähän esimerkkilöisesti kannettava tietämätön kone tahi tuollainen taskumuistiovermes ihan kelvollisia olisi, mutta kun kyseisessä ajanhetki-paikka-henkilö -risteymässä ei kyseisiä ollut käytettävissään, olkoon tilanne sitten tällainen... Että on ikävämmänpuoleinen rasitusvamma oikeanpuoleisessa kaulajäntehessä, johtuen epähygienisestä työasennosta ja epäergonomisen hammasharjan käytöstä. Vai olikos se taas toistepäin? No ihan sama miten olivatten, muttas minusta kyllä ihmiseläimen ei tulisi nukkua auton takakontissa. Voisis oikeastaan kansalaisaddressin kerätä auton takakontissa nukkumista vastaan ja vedota kansanterveyissyihin. Elikkätä menkääpä osoitteeseen kansalaisaddressiautontakakontissanukkumistavastaan ja täyttäkää tietonne sinne! Niin, ja toinen addressi voisi olla hyvä viallisia URL-osotteita vastaan. Kun kaiken maailman hörötörrelöt ilmoittavatten osoitteensa ties missä muodossa. Olkoon vaikkapa Kauppa X, jonka sivujen osoite onpi http://www.kauppax.fi ja sitten painavatten osoitteen lehteensä. Siellä saattaapi olla www.kauppax.fi, kauppax.fi tai jopa pelkkä kauppax. Näistä tietenkinsä ensimmäinen on melkein ok, sillä useimmat tajuavatten, notta http-protokollaa pitää käyttää (tai jos eivät, niin selain tajuaa), mutta sen käyttö toki olisi suotavaa. Toinen osoite on mahdollisesti väärin, silläs yleensä tuo www -etuinen liitteinen on melkeistä kuuluvainen osa tuota domainnimeä. On toki domainvermehiä, joissa tuota ei ole tai se ohjaapi eri osoitteeseen tai sitten on alias (esim. minun domainissani http://roivas.org on niin, että tuo edellinen muoto on oikia ja http://www.roivas.org onpi alias tuohon edelliseen), mutta yleensä kaikillansa ei välttämättään näin ole. Viimeinen muoto onpi sitten ehdottomasti väärinpäärin ja jos tuollaisenmuotoisia näette painettuna, niin ehdottoman ehdottomasti menkää ja valittakaa kyseiselle liikkehelle, boikotoikaa sitä, tehkääpi vaikka mitä! Tosin laittomanpuoleisiin toimenpiteisihin ei pidä ryhtyä, sillänsä ne ovatten laittomanpuoleisia. Näinhin sanoihin ja näihin tunnelmiin päätämme tämän kappaleen tähän. Assert Amlah ------------- Eräs vihaisenpuoleinen palaute tuli rättejä päänään käyttävältä lukijaltamme, Assert Amlahilta, notta emme ole hänen nimikkofunktiotansa käsitteet! Kyseisessänsä on tietenkin amlah... eiku assert -funktio, jota jo C-heimolaiset käyttivätten keskeyttäessään raskauksiaan eli aiheuttivat abortin ohjelmallensa. Tämäkös sitten on siis juuri tarkoitettu tähän. Elikkäs heitetään assertin sisään vaan komentojansa ja epätotuutta palauttelevatten, tuo keskeyttääpi ohjelmaisen suorituksen. Suoraista toimintaa, äksöniä sekä luotien viuhuntaista! Suoraan toimintaisen keskipisteisestä, Assert, oleppa hyvä! ---[ amlah.cpp ]--- #include #include #include //malloc:a varten using namespace std; //Epäonnisentapainen funktio inline bool ok() { return false; } int main() { int x; do { cout << "Annappa nummero 1-5 tahi 0 lopettaaksesi: "; cin >> x; switch (x) { //Ultimate poistumisvalinta case 0: cout << "Poies!" << endl; break; //Assert pääsee hallitsemaan, jos x ei ole nolla, jota //se ei ole, sillä tänne tullaan vain, jos x==1, //joten paipai! case 1: assert(x==0); cout << "Ok" << endl; break; //Luodaan osoitin, joka osoittaa ei-minnekään, ja //verrataan notta osoittaako tuo jonnekin. Jos näin on, //niin ok, muutoin assert sanoo hyvästit case 2: { int *ip=NULL; assert(ip!=NULL); } cout << "Ok" << endl; break; //Kutsutaan funktiota, jonka onnistumista assertti //valvoopi, ja epäonninen funktio saa assertin //suuttumaan ja heips! case 3: assert(ok()); cout << "Ok" << endl; break; //Yritetään varata muistia liikaa (tuo size_t(-1) //yrittää varata suurimman mahdollisen muistialueisen), //ja verrataan notta onnistuuko se varauksen tapainen. //Jos näin onpi niin kyllä sitä selkäiseen taputellaan, //muutoin sanotaan heipskukkuu! case 4: { void *tmp; assert((tmp=malloc(size_t(-1)))!=NULL); free(tmp); } cout << "Ok" << endl; break; //Tämän pitäisi onnistua aina. case 5: assert(true); cout << "Ok" << endl; break; default: cout << "Väärä valinta!" << endl; } } while (x>0); return 0; } ------------------- Ulosteinen taas riippuu koneisesta, kääntäjästä ja vaikka mistä! Tuo nelostesti ei ole idiotti-, kone- eikä mitenkään muuten varma, joten se voipi jollain jopa onnistua. Muttas siis tuo assertti heittäpi ilmoillensta SIGABRT -signaalinsa, ainaskiin minun vermehellä, tietenkin joku UNIX-signaaleista tietämätön järjestelmäinen tappaapi tuon toiselle tavallansa. Ja tuo assertti muuten onpi yleisesti toteutettu makrona, jotens joo. Käteväpätevä varsinkin testauksessa. Ja tuon assertin voipi muuten hyvinsä siis uudelleenmääritellänsä. Esimerkkilöisesti: #undef assert #define assert(x) x Tällöistä siis kaikista assert(jotain); -riveistä tuleepi jotain; -rivejänsä. Jep. Kätevätäpätevätä varsinkin testauksen kannaltansa, jolloin nuo assertit voipi sinne rauhassaan jätellä, mutta uudelleenmääritteleepi sen testauksen ja oikeaksi todentamisen jälkeensä. Tuo esimerkkinen koodi muuten valitteleepi tuon esimerkkilisäyksen jälkeensä, sillä sinne tulee melko hassujansa lausahduksia, kuten x==0; joka ei tietenkään kääntäjän mielestä järkevältä tunnu. Onkin melkeistä suositeltavampaa käyttää jotain oikeaa virheenpaikannustansa, kuten heitellä keskeytyksiä tahi muuta järkevää, pätevää ja hassua. Tahi jättää ne oikeammanpuoleiset assertit sinne. Loppusanat ---------- Nyt kun on jo uudenvuodenlupauksentapaisetkin mennehet, ja muutenkin saa taas valehdella ja rikkoloida lupauksia minkä kerkiää, niin lupaankin, notta ainakin yksi osa on tulossa sitten vielä joskus. Ehkä useampi. Tosin tämä lupauksentapainen voipi ehkä melkein suurella todennäköisyydellänsä pitää, sillä asioita olisi vieläs muutama jäljellänsä. Ja vaikkei olisi, niin semmosiahan voipi keksiä vaikka mistä. Niin, onneksi tämä maailma on niin hassu paikka, etteivät ota mielipuolisiin sairaaloihinsa immeisiä, jotka eivät ole itsellensä ja tahi ympäristöllensä vaarallisia, joten he voivatten C++ tutoriaalin tapaisia kirjoitella minkä kerkiävätten. Näin on närhet ja närhen munaiset. Tosin Närhen munia enpä ole nähnyt, mutta kuullut. Ja kaikille yhdelle yhtäaikaiselle lukijoille toivotus, tosin enpä kerro mitä toivottelen. Niin, ja C++ tutti ilman humppaa on olematon! Hei sun hulinas vei! Hetki vaan, uudestaan, kas käymme kohti unholaa. Kenet vaan sä muistaa saat ja kenet tahansa unohtaa. Mut' mieti tarkkaan, kunnolla, keitä tahdot sä muistella sitten joskus vanhana, koko elämäs varrelta. Hernekeitto (c) sormen toiseksi viimeisen vie kädestä tämä numero, Joro (Tuo Joro olen edelleensä minähenkilö elikkästä Jouni Roivas, http://roivas.org, sähköisenpuoleinen posti virtaa pitkin hutkii ja vie kohti jroivas@iki.fi. Käherrintarvikkeita myyvät alan erikoisliikkeet sekä Pertti-Maija Ala-Sumpuuki.)