You are on page 1of 140

Vilniaus universitetas Matematikos ir informatikos fakultetas Program sistem katedra

Valdas Undznas http://www.mif.vu.lt/~valund/

INFORMATIKA
Programavimas C++ kalba
Mokymo priemon

Dalykas skaitomas VU Fizikos fakulteto 2 kurso studentams

Vilnius - 2009

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Turinys
VADAS .......................................................................................................................................5 i. Bendrieji informatikos klausimai .................................................................................5 ii. Trumpai apie kompiuteri programin rang. C++ program apdorojimo etapai ............................................................................6 iii. Apie mokymo priemon ................................................................................................7 1. C++ programos struktra ..................................................................................................8 2. Kintamieji. Duomen tipai ................................................................................................11 2.1. Vardai (identifikatoriai) .............................................................................................11 2.2. Pagrindiniai duomen tipai ......................................................................................11 2.3. Kintamj skelbimas .................................................................................................12 2.4. Kintamj galiojimo sritis .........................................................................................12 2.5. Kintamj inicializacija.............................................................................................13 2.6. Paintis su simboli eilutmis ..................................................................................13 3. Konstantos ............................................................................................................................15 3.1. Konstant tipai ............................................................................................................15 3.2. Apibrtosios konstantos ( #define )......................................................................17 3.3. Paskelbtosios konstantos ( const )...........................................................................18 4. Operatoriai ...........................................................................................................................19 4.1. Priskyrimo operatorius ( = ) .....................................................................................19 4.2. Aritmetiniai operatoriai ( + , - , * , / , % ) ................................................................20 4.3. Sudtiniai priskyrimo operatoriai ( += , -= , *= , /= , %= , >>= , <<= , &= , ^= , |= ) ............................................................................................................20 4.4. Reikms didinimo ir mainimo operatoriai ( ++ , -- ) ........................................21 4.5. Palyginimo operatoriai ( == , != , > , < , >= , <= ) ..........................................22 4.6. Loginiai operatoriai ( ! , &&, | ) ................................................................................23 4.7. Slygos operatorius ( ? ) ............................................................................................24 4.8. Kablelio operatorius ( , ) ............................................................................................24 4.9. Bit operatoriai ( & , | , ^ , ~ , << , >> ) .............................................................25 4.10. Aikiai nurodomi duomens tipo keitimo operatoriai ..........................................25 4.11. Operatorius sizeof() ................................................................................................25 4.12. Kiti operatoriai ..........................................................................................................26 4.13. Operatori pirmumo lygiai .....................................................................................26 5. Pagrindinis duomen vedimas/ivedimas .....................................................................28 5.1. Standartinis ivedimas ( cout ) ................................................................................28 5.2. Standartinis vedimas ( cin ).....................................................................................30 5.3. cin ir simboli eiluts ................................................................................................31 5.4. stringstream funkcija ..............................................................................................32 2

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

5.5. Duomen vedimo/ivedimo funkcijos printf ir scanf ........................................33 5.6. Darbas su duomen failais........................................................................................36 6. Valdantieji sakiniai .............................................................................................................40 6.1. Slygos sakinys: if ir else .........................................................................................40 6.2. Ciklai ( while, do-while, for ) ..................................................................................41 6.3. Perokimo sakiniai ( break, continue, goto, exit() ) .........................................44 6.4. Variantinis sakinys ( switch )...................................................................................46 6.5. Paprast program pavyzdiai.................................................................................47 7. Funkcijos ..............................................................................................................................53 7.1. void tipo funkcijos .....................................................................................................55 7.2. Argument reikmi ir adres perdavimas parametrams ...................................56 7.3. Numatytj reikmi parametrai ............................................................................58 7.4. Funkcijos vienodais vardais......................................................................................59 7.5. Funkcij ablonai ( template ) ................................................................................59 7.6. inline funkcijos ..........................................................................................................62 7.7. Rekursijos ....................................................................................................................62 7.8. Funkcij skelbimas ....................................................................................................63 8. Masyvai ................................................................................................................................66 8.1. Masyv inicializacija .................................................................................................66 8.2. Kreipimasis masyvo elementus ..............................................................................67 8.3. Daugiamaiai masyvai ..............................................................................................68 8.4. Masyvai kaip funkcij parametrai ...........................................................................69 8.5. Program su masyvais pavyzdiai ...........................................................................71 9. Simboli sekos .....................................................................................................................75 9.1. Simboli sek inicializacija ......................................................................................75 9.2. Simboli sek naudojimas ........................................................................................76 10. Rodykls (pointers) ...........................................................................................................78 10.1. Adreso operatorius ( & ) ..........................................................................................78 10.2. Duomens nurodytu adresu operatorius ( * ) ........................................................79 10.3. Rodykls tipo kintamj paskelbimas ..................................................................80 10.4. Rodykls ir masyvai .................................................................................................81 10.5. Rodykli inicializacija .............................................................................................82 10.6. Rodykli aritmetika ..................................................................................................83 10.7. Rodykli rodykls .....................................................................................................84 10.8. void rodykls............................................................................................................85 10.9. null rodykl ..............................................................................................................86 10.10. Funkcij rodykls ...................................................................................................86 11. Dinamin atmintis ............................................................................................................88 11.1. Operatoriai new ir new[ ] .....................................................................................88 3

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

11.2. Operatoriai delete ir delete[ ] .............................................................................89 11.3. Dinamin atmintis ANSI-C++ standarte ............................................................91 12. Duomen struktros .........................................................................................................92 12.1. Duomen struktros ................................................................................................92 12.2. Struktr rodykls....................................................................................................95 12.3. Struktros struktrose .............................................................................................97 12.4. Dinamins duomen struktros: sraai, mediai ir kita ..................................97 13. Kiti duomen tipai .......................................................................................................... 102 13.1. Apibrtieji duomen tipai ( typedef )............................................................... 102 13.2. Bendrosios atminties sritys ( union ) .................................................................. 102 13.3. Bevards bendrosios atminties sritys union ...................................................... 104 13.4. Ivardijimai ( enum ) ............................................................................................. 105 14. Klass ir objektai ............................................................................................................. 106 14.1. Konstruktoriai ir destruktoriai .............................................................................. 109 14.2. Klass su keliais konstruktoriais .......................................................................... 111 14.3. Numatytasis ( default ) konstruktorius ............................................................... 112 14.4. Klasi rodykls ....................................................................................................... 113 14.5. Klasi skelbimas naudojant struct ir union ..................................................... 114 14.6. static nariai klasse.............................................................................................. 115 14.7. Klasi ablonai ( template ) ............................................................................... 116 15. Draugikumas ir paveldimumas ................................................................................... 118 15.1. Draugikosios funkcijos ( friend ) ....................................................................... 118 15.2. Draugikosios klass.............................................................................................. 119 15.3. Klasi paveldimumas ............................................................................................ 120 15.4. Kas nepaveldima i bazins klass? .................................................................... 123 15.5. Daugeriopas paveldimumas ................................................................................. 123 16. Polimorfizmas .................................................................................................................. 125 16.1. Bazini klasi rodykls ......................................................................................... 125 16.2. Virtuals klasi nariai ........................................................................................... 126 16.3. Abstrakiosios bazins klass ............................................................................... 128 17. Dar apie duomen fail vedim/ivedim ................................................................. 133 17.1. vedimo/ivedimo funkcijos read() ir write() ................................................... 133 17.2. vedimo/ivedimo funkcijos fscanf(), fprintf() ir kitos ................................... 134 altiniai ................................................................................................................................... 139 Priedas. C++ standartins bibliotekos. ............................................................................ 140

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

VADAS
i. Bendrieji informatikos klausimai
Kas yra informacija? Skaiiai, tekstai, garsai, vaizdai, kt. Informacijos perdavimo bdai: knygos, telefonas, radijas, televizija, kompiuteri tinklai (einama link viskam bendro duomen perdavimo tinklo). Problema - kryptingas informacijos apdorojimas: j reikia dlioti (kaupti) taip, kad galtume greiiausiai susirasti mums reikaling informacij (rikiavimas pagal autoriaus pavard, mokslo sritis, bazinius odius, kt.); kompaktikas saugojimas, greitas perdavimas. Informatika - mokslas apie informacijos apdorojimo metodus, informacijos technologijas, kompiuteri aparatins ir programins rangos krim, kt. Kompiuteri istorija: j kartos, universals ir specializuoti, skaitmeniniai ir analoginiai. Kompiuterio struktra: rengini paskirtis, ryiai tarp j, kompiuteri architektra. IBM PC sudtis, rengini charakteristikos. Duomen vaizdavimas kompiuteriuose: 2 (dvejetain) skaiiavimo sistema ir jos vartojimo prieastys. Ryys tarp 2 skai. sist. ir 10 skai. sist. Apie 8 skai. sist. ir 16 skai. sist., kodl j prireik. Skaii vaizdavimas fiksuotu ir slankiu kableliu. Simboliai ir j kodavimas. Programinis kompiuteri valdymo principas. Programa - tai mainini komand seka. Mainins komandos struktra. Algoritmas: kokie veiksmai ir kokia eils tvarka jie turi bti atlikti, norint isprsti kakok udavin. Nuosekli veiksm seka. Programavimo automatizavimas: operacins sistemos, programavimo kalbos, program paketai ir t.t. Komandin ir grafin sveikos: dialogo tarp mogaus ir kompiuterio palaikymo bdai. Pvz., MS DOS aplinka, NORTON COMMANDER, WINDOWS, LINUX. Danai sutinkama santrumpa GUI Graphic User Interface (grafin vartotojo sveika). Informatikos standartai: susitarimai laikytis vienodos tvarkos, taisykli. Pvz., OSI (Open System Interconnection) modelis - tai standart rinkinys, kurio reikia laikytis, kad skirting ri kompiuteriai galt palaikyti ry; protokolai - standart rinkiniai, kuri laikomasi perduodant duomenis kompiuteri tinklais. ISO tarptautin standartizacijos organizacija; yra ir kitos: CEN, ETSI, t.t.

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

ii. Trumpai apie kompiuteri programin rang. C++ program apdorojimo etapai
Operacin sistema (OS) - tai gatav program rinkinys, padedantis vartotojui priirti bei eksploatuoti kompiuter. Kompiuteri gamintojai, programins rangos krjai pateikia vartotojams OS urayt diske, pastoviojoje atmintyje, kt. Pvz., MS DOS, jo komponents BIOS, COMMAND.COM, AUTOEXEC.BAT, tvarkykls (draiveriai), NORTON COMMANDER; WINDOWS; UNIX; LINUX ir t.t. vairiems darbams palengvinti yra kuriama pagalbin programin ranga (programavimo kalb kompiliatoriai, duomen bazi valdymo sistemos, tekst rengimo, elektroninio pato, narymo po internet programos, kt.). ia akcentuosime tik tuos komponentus, kurie reikalingi programuojant C++ kalba. C++ kalba parayta programa - tai tekstas i vairi simboli. Pirmas udavinys mogui yra perkelti tokios programos tekst kompiuterio atmint. iam tikslui gali bti panaudota pagalbin programa - tekst rengykl (EDIT, KEDIT, NOTEPAD ar kt.; plaiai inomas WORD iems tikslams netinka). Programos tekstas turi bti uraytas fail, kurio vardo pltinys yra .c arba .cpp (pvz., abc.c arba abc.cpp). Tekst rengykli teikiamos paslaugos yra labai plaios: terpti ar itrinti simbol, eilut, perkelti teksto dal i vienos vietos kit, kopijuoti, kt. Kadangi kompiuteris gali veikti tik pagal maininmis komandomis ireikt program, todl btinas antras etapas. Jo metu vesta kompiuterio atmint teksto pavidalo C++ programa, kuri vadinama programos pradiniu moduliu (.cpp), pertvarkoma mainini komand pavidal. T atlieka kita pagalbin programa C++ kompiliatorius. Jei kompiliatorius aptiko klaid C++ programos pradiniame modulyje, reikia grti pirmj etap, tekst rengykle itaisyti program ir vl kompiliuoti j. Kompiliavimo ir redagavimo metu gaunama vykdymui parengta vartotojo programa mainine kalba - vykdomasis modulis (.exe). Pertvarkius C++ program mainin pavidal (suformavus programos kod), belieka j vykdyti. Netgi kompiuteriui dirbant pagal vartotojo sudaryt program, proces gali siterpti OS. Yra sukurtos integruotosios programavimo sistemos arba aplinkos (IDE Integrated Development Environment), kuriose galima atlikti vis aukiau mint pagalbini program veiksmus.

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

iii. Apie mokymo priemon


Programavimo kalba C ir jos modifikacija C++ pasiymi program raymo glaustumu, element vairumu. i mokymo priemon skirta skaitytojams, kurie nori imokti programuoti C++ kalba ir nra moksi kit kalb. 1-13 skyriuose aikinami C kalbos elementai, kurie yra C++ kalbos dalis. Taiau netgi skaitytojams, kurie jau yra susipain su C kalba, rekomenduojama perirti iuos skyrius, nes yra neymi C++ ir C kalbos sintakss skirtum. 14-16 skyriuose apraomos klass, supaindinama su objektiniu programavimu. Daugelyje skyri yra pavyzdiai, iliustruojantys C++ kalbos elementus. Patartina inagrinti juos, suprasti kiekvien programos eilut ir tik po to eiti prie naujos temos. C++ kalbos tarptautinis standartas ANSI-C++ buvo priimtas palyginus neseniai. Jis buvo paskelbtas 1997 metais ir perirtas 2003 metais, nors pati C++ kalba egzistuoja nuo 1980 met. Todl yra daug ankstesns laidos kompiliatori, kurie nepalaiko vis minto standarto C++ kalbos galimybi. ioje mokymo priemonje dstoma mediaga reikalauja ANSI-C++ standarto reikalavimus atitinkani kompiliatori. Yra nemaai komercini, o taip pat laisvai platinam C++ programavimo sistem (programavimo sistema apima tekst rengykl, kompiliatori, vairias standartines bibliotekas, kt.), pvz., Dev-C++ 5.0 beta 9.2 (4.9.9.2). J galima rasti adresu http://www.bloodshed.net/dev/devcpp.html . ioje mokymo priemonje pateikiami pavyzdiai yra konsols tipo programos. Tai tokios programos, kurios naudoja teksto pavidalo duomenis ryiui su vartotoju palaikyti ir savo darbo rezultatams rodyti. Konsol - tai kompiuterio valdymo pultas, turintis klaviatr ir ekran. Visi C++ kompiliatoriai gali apdoroti konsols tipo programas. Vartotojams tereikia pasiskaityti darbo su kompiliatoriumi vadov (users manual). Be C++ yra ir kitos programavimo kalbos bei sistemos (aplinkos): Java, Pascal, Perl, PHP, Visual Basic ir daugelis kit. Imokti programavimo pagrind naudojant C++ ir rayti nesudtingas kompiuteri programas yra ios mokomosios disciplinos udavinys. Mokymo priemon parengta naudojant altinius [Sou06, Vid02, BBK+01].

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

1. C++ programos struktra


Mokytis programavimo kalbos geriausia yra raant programas ir vykdant jas kompiuteriu. emiau pateikiame pirmj program C++ kalba. Kairje pusje yra rodomas programos pradinis modulis (source code), o deinje programos rezultatai, kuriuos ji iveda ekran. Kelias, kaip reikt vesti, koreguoti ir kompiliuoti program, priklauso nuo programavimo sistemos, kuri js naudojate.

// pirmoji programa C++ kalba


#include <iostream> using namespace std; int main () { cout << "Sveiki gyvi!"; return 0; } Tai paprasiausia C++ programa, taiau joje jau yra pagrindiniai elementai, kurie sutinkami kiekvienoje programoje. Inagrinkime kiekvien ios programos eilut.

Sveiki gyvi!

// pirmoji programa C++ kalba


Visa eilut arba tik jos dalis, prasidedanti dviem pasvirusiais brkniais (//), yra komentaras ir takos programos darbui neturi. Kad bt lengviau atskirti komentarus nuo programos teksto, komentarus raysime kiek kitokiu riftu. Programuotojai naudoja juos savo pastaboms ar paaikinimams programos tekst terpti. Duotoje programoje tai tik pastaba, kas tai per programa. #include <iostream> Simboliu # prasidedanti eilut yra nuoroda preprocesoriui. Preprocesorius tai kompiliatoriaus dalis. #include <iostream> nurodoma, kad preprocesorius traukt ms program priemones i standartinio <iostream> failo. Tai gatav C++ program biblioteka duomenims vesti/ivesti atitinkamu bdu. J reikia ms programoje.

Preprocesorius programoje sutiks nuorod #include (ji raoma atskiroje eilutje), programos tekst stato vis nurodyto failo turin:
#include "failo_vardas" #include <failo_vardas>

i dviej nuorod skirtumas yra toks, kad kompiliatorius ieko nurodyto failo skirtinguose disko kataloguose. Kai failo_vardas yra apkabintas dvigubomis kabutmis,
8

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

kompiliatorius vis pirma failo ieko tame kataloge, kuriame yra #include nuorod turinti programa. iame kataloge neradus nurodyto failo, paieka tsiama numatytajame (default) kataloge, kuris konfigruojant kompiliatori buvo paskirtas standartini (gatav) bibliotek failams. Jei failo_vardas yra apskliaustas enklais < ir >, jo iekoma tik kataloge, kuris paskirtas standartini bibliotek failams. alia standartini bibliotek fail programuotojai gali susikurti asmenini bibliotek failus ir #include nuorodomis traukti juos vairias savo programas kai tik to prireikia.
using namespace std; Visi standartinse bibliotekose naudojami elementai yra aprayti vard srae (namespace) std. itokia programos eilute nurodoma, kad norime naudotis to vard srao elementais. Tai daugeliui C++ program, naudojani standartines bibliotekas, reikalingas sakinys. int main () itokia eilute nurodoma programos pagrindins (main) funkcijos pradia. Kiekvienoje C++ programoje turi bti pagrindin funkcija. Nuo jos pradedamas visos programos darbas, nesvarbu kurioje programos pradinio modulio vietoje ji bt parayta. Po main raomi skliaustai (), kurie C++ kalboje nurodo, kad prie juos einantis vardas yra funkcijos, o ne kitokio tipo elemento vardas. Tarp skliaust gali bti nurodomi parametrai. Toliau raomas pagrindins funkcijos programos tekstas turi bti tarp riestini skliaust { }. cout << "Sveiki gyvi!"; i eilut yra C++ kalbos sakinys (angl. statement). Sakinys tai paprasta arba sudtinga iraika, kuria nurodomi konkrets reikiami atlikti veiksmai. cout nurodoma, kad ekran reikia ivesti simboli sek, t.y. tekst Sveiki gyvi! cout programa imama i standartinio failo <iostream>, kurios elementai yra aprayti vard srae std. Todl ioje programoje ir prireik #include <iostream> ir using namespace std; Pastebkime, kad C++ kalboje sakiniai baigiami kabliatakiu. eilui

return 0; return sakiniu baigiamas pagrindins funkcijos darbas. Po jo nurodomas programos baigimo kodas. 0 reikia, kad pagrindin funkcija veik normaliai ir baig darb be klaid. Paprastai C++ programos baigiamos tokiu sakiniu. Kadangi pagrindins funkcijos (main) pradi nurodanioje eilutje yra int, tai baigimo kodas ioje programoje yra nurodytas sveikuoju skaiiumi (integer). Pagrindins funkcijos baigimo kodas gali bti panaudotas organizuoti tolesniam kompiuterio darbui. Kai raoma void main() arba tik main(), tai pagrindin funkcija jokio baigimo kodo negrina ir return sakinys nereikalingas.

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Atkreipkime dmes tai, kad ne visos programos eiluts iaukia konkreius veiksmus vykdant sukompiliuot program. Dalis i j yra tik paaikinimai (pvz.,

// pirmoji programa C++ kalba ) arba nuorodos (pvz., #include <iostream>).


Programos tekst skaidyti eilutes galima vairiai. Svarbu, kad jis mogui bt lengvai skaitomas. Pvz., vietoje int main () { cout << "Sveiki gyvi!"; return 0; } galima rayti int main () { cout << "Sveiki gyvi!"; return 0; } arba int main () { cout << "Sveiki gyvi!"; return 0; } Preprocesoriaus nuorodoms, t.y. toms eilutms, kurios pradedamos simboliu #, i bendroji sakini taisykl netaikoma. Jos raomos atskirose eilutse, gale nededant kabliatakio. Komentarai programoje gali bti raomi dviem bdais: // komentaras eiluts pabaigoje /* komentaras bet kurioje eiluts vietoje arba apimantis kelias eilutes */ Komentarai, prasidedantys simboli pora /* ir pasibaigiantys */ , gali uimti kelias eilutes. Pailiustruokime tai modifikuodami ms pirmj program. /* pirmoji programa C++ kalba, kuri yra daugiau pakomentuota */ #include <iostream> using namespace std; int main () { cout << "Sveiki gyvi!"; return 0; } // nuoroda preprocesoriui // pagrindins funkcijos pradia // ives ekran Sveiki gyvi!

Sveiki gyvi!

10

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

2. Kintamieji. Duomen tipai


Kintamasis programoje nurodomas vardu (identifikatoriumi), ir jis programos bgyje gali keisti savo reikm. Kintamasis suprantamas kaip kompiuterio operatyviosios atminties tam tikro dydio sritis, kurioje galima siminti nustatyto tipo reikm (sveikj skaii, realj skaii, tekst, kt.). Atminties srities dydis priklauso nuo kintamojo tipo. Programoje visi kintamieji turi bti aprayti, nurodytas j tipas.

2.1. Vardai (identifikatoriai)


Vardas tai raidi, skaitmen ir pabraukimo simboli ( _ ) seka, prasidedanti raide. Varduose vartoti kitoki simboli negalima. Pabraukimo simboliu prasidedantys vardai naudojami tik kompiliatoriuje, kaip speciali paskirt turintys vardai. Kintamj vardai negali sutapti su C++ kalbos baziniais odiais asm, auto, bool, break, case, catch, char, class, const, const_cast, continue, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, operator, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_cast, struct, switch, template, this, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, o taip pat odiais and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq. Kai kurie kompiliatoriai gali turti ir kit rezervuot odi, kuri negalima vartoti kaip kintamj vard. Pastaba: C++ kalboje didiosios ir maosios raids varduose traktuojamos skirtingai. Todl, pvz., vardai ABC, Abc, aBc, abc yra skirtingi.

2.2. Pagrindiniai duomen tipai


Pagrindiniai duomen tipai nurodomi baziniais odiais. Faktikai tipas atspindi galim duomens reikmi diapazon ir kiek tokiai reikmei saugoti atmintyje skiriama bait. Tipas char short int (short) signed: unsigned: signed: unsigned: Reikmi diapazonas nuo -128 iki 127 , simbolio kodas nuo 0 iki 255 , simbolio kodas nuo -32768 iki 32767 nuo 0 iki 65535 Uima bait 1 2

11

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int

signed: nuo -2147483648 iki 2147483647 unsigned: nuo 0 iki 4294967295 signed: nuo -2147483648 iki 2147483647 0 iki 4294967295 unsigned: nuo true arba false 3.4e +/- 38 1.7e +/- 308 1.7e +/- 308 (mantisje - 7 skaitmenys) (mantisje - 15 skaitmen) (mantisje - 15 skaitmen)

long int (long) bool float double long double wchar_t

1 4 8 8 2

platusis simbolis

Pastaba: skirtinguose kompiliatoriuose duomen tipai gali bti realizuoti skirtingai, t.y. gali skirtis ioje lentelje nurodyti reikmi diapazonai, uimamos atminties dydis.

2.3. Kintamj skelbimas


Kintamasis gali bti naudojamas tik paskelbus j ir nurodius, kokio tipo duomenims jis yra skirtas. Skelbimo sintaks yra tokia: pirma nurodomas duomen tipas, o po jo - vieno arba keli kintamj vardai. int a; int b, c, d; float x, y; Sveikojo tipo kintamieji gali turti enkl (gali gyti teigiamas ir neigiamas reikmes) ir gali bti be jo (gali gyti tik teigiamas reikmes). Tai nurodoma odiais signed ir unsigned. Pavyzdiui: unsigned short int kiekis; signed int temperatura; Nurodant sveikj kintamj ilg, vietoje short int galima rayti tik short, o vietoje long int tik long. Taip pat sveikiesiems kintamiesiems vietoje signed int galima rayti tik signed, o vietoje unsigned int - tik unsigned.

2.4. Kintamj galiojimo sritis


Kintamieji gali bti globalieji ir lokalieji. Globalieji yra tie, kurie programos tekste yra aprayti dar prie pagrindin ir kitas funkcijas. Lokalieji kintamieji yra tokie, kurie paskelbti funkcijos arba programos bloko viduje, t.y. riestiniais skliaustais {} apribotame programos tekste. 12

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

#include <iostream> using namespace std; int a; char r; unsigned int c; int main () { int metai; float ada; cout << Kiek jums metu?; cin >> metai; return 0; } globaliuosius kintamuosius galima kreiptis i bet kurios programos vietos, einanios po i kintamj paskelbimo. Lokalij kintamj galiojimo sritis yra apribota riestiniais skliaustais {} , ir juos galima kreiptis nuo paskelbimo vietos iki udaranio riestinio skliausto. // // lokalieji kintamieji // // globalieji kintamieji //

2.5. Kintamj inicializacija


Paskelbto kintamojo reikm paprastai bna neapibrta (neinoma). Taiau paskelbimo metu kintamajam galima suteikti pradin reikm, t.y. inicializuoti kintamj. C++ kalboje tai galima atlikti dviem bdais: 1) po kintamojo vardo raant lygybs enkl ir nurodant pradin reikm; 2) po kintamojo vardo skliaustuose nurodant pradin reikm. Pvz., int a = 5; int b (2);

2.6. Paintis su simboli eilutmis


Kintamieji, kurie gali siminti daugiau kaip vien simbol, yra vadinami simboli eilutmis arba tiesiog eilutmis. C++ kalbos standartinje bibliotekoje <string> yra priemons, palengvinanios j naudojim. Eiluts nepriklauso pagrindini duomen tipui, taiau jos funkcionuoja panaiai, kaip daugelis pagrindinio tipo duomen. Apraant eilutes, j tipas nurodomas baziniu odiu string. Pirmas esminis eilui skirtumas nuo pagrindinio tipo duomen yra tas, kad, prie skelbiant jas, program turi bti traukta standartin biblioteka <string> ir naudojama vard sritis (namespace) std.

13

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// pirmas simboli eiluts pavyzdys #include <iostream> #include <string> using namespace std; int main () { string se = "Tai eilute"; // skelbiama ir inicializuojama eilute cout << se; return 0; } Skelbimo metu eilui tipo kintamiesiems, kaip ir skaitiniams kintamiesiems, pradins reikms gali bti suteiktos dviem bdais. Pvz., string se = "Tai eilute"; string se ("Tai eilute"); Jeigu skelbiant eilut pradin reikm jai nesuteikiama, tai, kaip ir kitokiems kintamiesiems, reikm gali bti suteikiama programos bgyje priskyrimo operatoriumi. Pvz., // programos su eilute pavyzdys #include <iostream> #include <string> using namespace std; int main () { string se; se = "Tai pirma eilutes reiksme"; // priskyrimo sakinys cout << se << endl; se = "Cia jau kita eilutei suteikiama reiksme "; cout << se << endl; return 0; } Tai eilute

14

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

3. Konstantos
Konstanta tai iraika, kurios reikm ilieka tokia pati vis programos darbo laik.

3.1. Konstant tipai


Sveikieji skaiiai. 1746 +508 -273

ia parodytos trys deimtaini skaii konstantos. Sveikj skaii konstantos gali bti raomos ir atuntaine arba eioliktaine skaiiavimo sistema. Atuntainio skaiiaus pradioje raomas 0 (nulis), o eioliktainio 0x (nulis ir x). 75 0113 0x4b // deimtainis skaiius // atuntainis // eioliktainis

iame pavyzdyje vis trij konstant reikms yra vienodos, tik jos uraytos skirtingomis skaiiavimo sistemomis. Kaip ir int tipo kintamieji, taip ir sveikj skaii konstantos gali turti poymius unsigned ir long. Jie nurodomi raidmis u ir l skaiiaus gale. u ir l gali bti maosios arba didiosios. 75 75u 75L 75ul // int tipo konstanta // unsigned int // long // unsigned long

Slankaus kablelio skaiiai. Tai deimtainiai skaiiai, turintys ir trupmenin dal. Jie gali bti raomi dvejopai: naudojant tak trupmeninei daliai atskirti nuo sveikosios arba naudojant eksponentin pavidal, t.y. su raide e. 3.14159 6.02e23 1.6e-19 3.0 // 3.14159 // 6.02 padauginta i 10, pakeltos 23 laipsniu // 1.6 padauginta i 10, pakeltos -19 laipsniu // 3.0

15

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Nesant papildom nurodym slankaus kablelio konstantos yra double tipo. Norint turti float arba long double tipo konstant, jos gale reikia rayti raid f arba l. iose konstantose raids e, f ir l gali bti maosios arba didiosios. 3.14159L 6.02E23f // long double tipo konstanta // float

Simbolis ir eilut. 'z' "Sveiki gyvi" // simbolio konstanta, char tipo // simboli eiluts konstanta, string tipo

Simbolio tipo (char) konstantos raomos tarp viengub kabui, o eilui tipo (string) konstantos - tarp dvigub kabui. Atkreipkime dmes iuos du uraus: x 'x'

Uraas x reikia kintamojo vard, o uraas 'x' simbolio konstant. Kai kurie simboliai turi tam tikr ypatum, kaip, pvz., valdantieji simboliai (kai kuriuos atitinka klaviai, pvz., Enter, Tab, kt.). Tai specials simboliai, kuriuos sunku arba nemanoma pavaizduoti programos tekste. Todl valdantieji simboliai vaizduojami j pradioje raant atgal pasvirus brkn ( \ ) ir po to vien kok nors kit simbol. tai valdanij simboli sraas: Valdantysis simbolis \n \r \t \v \b \f \a \' \" \? \\ Reikm pereiti kitos eiluts pradi (pvz., Enter klavias) grti tos paios eiluts pradi (Home klavias) tabuliacija (Tab klavias) vertikali tabuliacija (spausdintuvams valdyti) grti per vien pozicij (Backspace klavias) form feed (spausdintuvams valdyti) perspjimo signalas (pypteljimas) vienguba kabut ( ' ) dviguba kabut ( " ) klaustukas ( ? ) atgal pasvirs brknys ( \ )

16

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Konstant su valdaniaisiais simboliais pavyzdiai: '\n' '\t' "Kaire \t Desine" "vienas\ndu\ntrys" Taip pat bet kur simbol galima nurodyti jo skaitiniu ASCII kodu, prie j raant atgal pasvirus brkn. Kodas gali bti uraytas tik atuntainiu arba eioliktainiu skaiiumi. Atuntainis kodas raomas tuoj po brknio, pvz., \25 , o eioliktainis kodas dar turi x , pvz., \x4A . Simboli eiluts konstanta gali bti raoma keliose i eils einaniose puslapio eilutse. Pereinant kit puslapio eilut raomas atgal pasvirs brknys. Pvz., "simboliu eilute uzrasyta dviejose \ puslapio eilutese" Keletas eilui, tarp kuri yra tarpai, tabuliacija (buvo paspaustas klavias tab) ar perjimas nauj puslapio eilut (enter), yra sukabinamos ir reikia vien ilg eilut. Pvz., "Tai yra" "viena ilga" "simboliu eilute."

Jei norime turti eilut i plaij simboli wchar_t (t.y. simboli, kuriems atmintyje skiriama po 2 baitus), jos priekyje raoma raid L. Pvz., L"Tai placiuju simboliu eilute" Logins konstantos. Tai bool tipo reikms. Jos uraomos odiais true ir false .

3.2. Apibrtosios konstantos ( #define )


Jeigu ta pati konstanta vartojama keliuose programos sakiniuose ir yra ilgas jos uraas, patogiau j pasivadinti vardu (vardin konstanta), jam suteikti norim reikm ir vartoti vard, kur bus reikalinga tokia reikm. Be to, sumanius pakeisti konstantos reikm, tereiks taisyti vienoje programos vietoje, o ne visuose sakiniuose, kur tokia konstanta pavartota. C++ kalboje apibrtosios konstantos skelbiamos naudojant preprocesoriaus nuorod #define. ios nuorodos bendrasis pavidalas yra #define vardas reikm 17

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Pvz., #define PI 3.14159265 #define bruksnys \n------------\n Taip gavome dvi naujas apibrtsias konstantas: PI ir bruksnys. iuos vardus galima naudoti programoje kaip ir bet kuri prast konstant. Pvz., // apibrtosios konstantos programoje // apskritimo ilgiui skaiiuoti #include <iostream> using namespace std; #define PI 3.14159 #define bruksnys \n------------\n int main () { double r = 5.0; double apskrilgis; apskrilgis = 2 * PI * r; cout << apskrilgis; cout << bruksnys; return 0; } #define yra preprocesoriaus nuoroda, o ne C++ kalbos sakinys. Todl jos gale kabliatakis nededamas. // spindulys

31.4159

----------

3.3. Paskelbtosios konstantos ( const )


Bazinis odis const galina paskelbti konstantas nurodant ir j tip, kaip tai daroma kintamj atveju. Pvz., const int plotis = 100; const char tabul = '\t'; const kuku = 12440; Kai po const tipas nenurodomas (kaip paskutiniame pavyzdyje), laikoma, kad yra int.

18

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4. Operatoriai
Kadangi jau susipainome su kintamaisiais ir konstantomis, inagrinkime galimus veiksmus su jais. Veiksmai C++ kalboje nurodomi operatoriais. Operatorius tai kakoks simbolis arba j derinys, kuriuo nurodoma atlikti kakok veiksm.

4.1. Priskyrimo operatorius ( = )


Priskyrimo operatoriumi reikm priskiriama kintamajam. a = 5; iuo sakiniu sveikoji reikm 5 priskiriama kintamajam a. Pagrindin priskyrimo sakinio taisykl yra ta, kad jis vykdomas i deins kair: a = b; iuo sakiniu nurodoma, kad reikia paimti kintamojo b reikm ir priskirti j kintamajam a. Reikm, kuri iki iol turjo kintamasis a, ia nra naudojama ir ji prarandama. Ateityje, keiiant kintamojo b reikm, takos kintamajam a tai neturs. Panagrinkime toki C++ program: // priskyrimo operatoriaus iliustracija #include <iostream> using namespace std; int main () { int a, b; a = 10; b = 4; a = b; b = 7; cout cout cout cout << << << << "a="; a; " b="; b; // // // // // a=?, b=? a=10, b=? a=10, b=4 a=4, b=4 a=4, b=7

a=4 b=7

return 0; } ios programos rezultatas yra toks: kintamojo a reikm yra 4, o kintamojo b 7. Pastebkime, kad keiiant b reikm, kintamojo a reikm nekinta.

19

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

C++ kalbos ypatyb, lyginant j su kitomis programavimo kalbomis, yra ta, kad priskyrimo operacija gali bti atliekama ir priskyrimo operatoriaus deinje pusje. Pvz., a = 2 + (b = 5); Tai ekvivalentika tokiems dviems priskyrimo sakiniams: b = 5; a = 2 + b; Tai reikia, kad vis pirma kintamajam b priskiriama reikm 5, o po to, prie ios reikms pridjus 2, gauta suma 7 priskiriama kintamajam a. C++ kalboje taip pat yra teisinga tokia iraika: a = b = c = 5; iuo sakiniu reikm 5 priskiriama visiems trims kintamiesiems a, b ir c.

4.2. Aritmetiniai operatoriai ( + , - , * , / , % )


C++ kalboje yra leistinos penkios aritmetins operacijos: + * / % sudtis atimtis daugyba dalyba dalybos liekana

Sudties, atimties, daugybos ir dalybos operacijos visikai atitinka matematikoje naudojamas operacijas. Tik operatorius dviej sveikj skaii dalybos liekanai gauti yra ymimas procento enklu. Pvz., jeigu uraysime: a = 11 % 3; tai kintamasis a gis reikm 2, kadangi tai yra skaiiaus 11 padalinto i 3 dalybos liekana.

4.3. Sudtiniai priskyrimo operatoriai ( += , -= , *= , /= , %= , >>= , <<= , &= , ^= , |= )


Kintamojo reikmei pakeisti, kai reikia atlikti veiksm su jo ankstesne reikme, galima naudoti sudtin priskyrimo operatori. Pvz.:

20

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Iraika dydis += prieaugis; a -= 5; a /= b; kaina *= kiekis + 1;

Iraikos ekvivalentas dydis = dydis + prieaugis; a = a - 5; a = a / b; kaina = kaina * (kiekis + 1);

Tas pats galioja ir visiems kitiems ( % , >> , << , & , ^ , | ) operatoriams. Programos pavyzdys: // sudtinis priskyrimas #include <iostream> using namespace std; int main () { int a, b=3; a = b; a += 2; cout << a; return 0; }

// ekvivalentika a=a+2 5

4.4. Reikms didinimo ir mainimo operatoriai ( ++ , -- )


Iraik, kuriomis norima vienetu padidinti arba sumainti kintamojo reikm, trumpesnis uraas gaunamas naudojant didinimo (++) arba mainimo (--) operatori. Jie yra ekvivalentiki atitinkamai operatoriams +=1 ir -=1 . Todl sakini c++; c += 1; c = c+1;

atliekamos funkcijos yra ekvivalentikos. Visi jie kintamojo c reikm padidina vienetu. ie operatoriai gali bti raomi prie kintamojo vard arba po jo. Paprastos iraikos, kaip a++ arba ++a , duoda t pat rezultat. Taiau sudtingesnse iraikose, ++ ar -- raymas prie ir po kintamojo vardo turi svarb skirtum. Pvz., raant ++a , kintamojo a reikm vis pirma padidinama vienetu ir po to naudojama sudtingoje iraikoje, o raant a++ , sudtingoje iraikoje naudojama turima a reikm ir tik po to ji didinama vienetu. Atkreipkime dmes skirtum iuose pavyzdiuose:

21

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

1 pavyzdys B=3; A=++B; // A reikm - 4, B reikm - 4 B=3; A=B++;

2 pavyzdys

// A reikm - 3, B reikm - 4

1 pavyzdyje B reikm vis pirma padidinama vienetu ir po to priskiriama kintamajam A, o 2 pavyzdyje B turima reikm vis pirma priskiriama kintamajam A

ir tik po to padidinama vienetu.

4.5. Palyginimo operatoriai ( == , != , > , < , >= , <= )


Dviej iraik rezultatams palyginti naudojami palyginimo operatoriai. J darbo rezultatas yra loginio tipo (bool) reikm: true arba false . emiau pateikiamas C++ kalboje naudojam palyginimo operatori sraas: == != > < >= <= lygu nelygu daugiau maiau daugiau arba lygu maiau arba lygu

tai keletas palyginimo pavyzdi:


(7 (5 (3 (6 (5 == 5) > 4) != 2) >= 6) < 5) // rezultatas false // true // true // true // false

Vietoje ia palyginam skaitini konstant, inoma, gali bti bet kokios leistinos iraikos arba kintamieji. Tarkime, kad a=2, b=3 ir c=6. Todl:
(a == 5) (a*b >= c) (b+4 > a*c) ((b=2) == a) // rezultatas false, nes 2 nelygu 5 // true, ( 2*3 >= 6 ) // false, ( 3+4 > 2*6 ) // true

Bkime atids! Operatorius = (vienas lygybs enklas) nra tas pat, kaip operatorius == (du lygybs enklai). Pirmasis yra priskyrimo operatorius, o antrasis palyginimo. Todl paskutin iraika ((b=2) == a) skaiiuojama taip: vis pirma 2 priskiriamas kintamajam b , o po to i reikm palyginama su kintamojo a reikme. Taigi, rezultatas yra true.

22

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4.6. Loginiai operatoriai ( ! , &&, | )


C++ kalboje auktuku (!) nurodoma login operacija NE (anglikai NOT). Ji turi tik vien operand, kuris raomas enklo deinje, ir invertuoja jo login reikm, t.y. true keiia false ir atvirkiai. Pvz.: !(5 == 5) // rezultatas false, nors palyginimas (5 == 5) duoda true !(6 <= 4) // rezultatas true, nors palyginimas (6 <= 4) duoda false !true // rezultatas false !false // rezultatas true

Operatoriumi && (du simboliai &) nurodoma login operacija IR (anglikai AND). Jos rezultatas yra true tik tada, kai abiej operand reikms yra true. a true true false false b true false true false a && b true false false false

Operatoriumi || (du vertikals brkniai) nurodoma login operacija ARBA (anglikai OR). Jos rezultatas yra true, kai bent vieno operando reikm yra true. a true true false false Pavyzdys: ((5 == 5) && (3 > 6)) ((5 == 5) || (3 > 6)) // rezultatas false // true (true && false) (true || false) b true false true false a || b true true true false

23

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4.7. Slygos operatorius ( ? )


Slygos operatoriaus ? (klaustukas) pavidalas yra toks: iraika ? rezultatas1 : rezultatas2 Kairje operatoriaus pusje raoma login iraika, o deinje - dvitakiu atskirtos dvi reikms. Jei iraikos reikm yra true, tai slygos operatoriaus rezultatas yra rezultatas1, o prieingu atveju rezultatas2 . Pvz.: 7==5 ? 4 : 3 7==5+2 ? 4 : 3 5>3 ? a : b a>b ? a : b // gausime 3, nes 7 nelygu 5 // gausime 4, nes 7 lygu 5+2 // gausime kintamojo a reikm, nes 5 daugiau u 3 // gausime kintamojo a arba b reikm, kuri didesn

// Programos su slygos operatoriumi pavyzdys #include <iostream> using namespace std; int main () { int a,b,c; a=2; b=7; c = (a>b) ? a : b; cout << c; return 0; }

// c gis reikm 7 7

4.8. Kablelio operatorius ( , )


Kablelio operatoriumi (,) atskiriamos dvi arba daugiau iraik, kur prastai raoma tik viena. Kai reikmei apskaiiuoti naudojamas iraik rinkinys, tai, apskaiiuojant jas i kairs dein, galutin reikm duoda toliausiai deinje stovinti iraika. Pvz.: a = (b=3, b+2); Vykdant sakin, vis pirma kintamajam b priskiriama reikm 3, o po to iraikos b+2 rezultatas priskiriamas kintamajam a. Taigi, vykdius sakin a reikm bus lygi 5, o b reikm bus lygi 3.

24

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4.9. Bit operatoriai ( & , | , ^ , ~ , << , >> )


Bit operatoriais nurodomi veiksmai, kuriuos reikia atlikti su kintamaisiais, imant dvejetain j reikmi pavidal, kuriuo jie yra saugomi atmintyje. Ekvivalentas Operatorius kitose kalbose & | ^ AND OR XOR Paaikinimai Login operacija IR su atitinkamais operand bitais. Login operacija ARBA su atitinkamais operand bitais. Login operacija grietasis-ARBA su atitinkamais operand bitais. Login operacija NE (inversija) su kiekvienu operando bitu. is operatorius turi tik vien operand. Vis operando bit postmis kair (Shift Left). Vis operando bit postmis dein (Shift Right).

~ << >>

NOT SHL SHR

4.10. Aikiai nurodomi duomens tipo keitimo operatoriai


Tipo keitimo operatoriai galina keisti duomens esam tip kitokiu. C++ kalboje tam yra keletas bd. Paprasiausias i j yra paveldtas i C kalbos, prie iraik skliaustuose nurodant tip, kok turi bti pertvarkytas iraikos rezultatas: int i; float f = 3.14; i = (int) f; iame pavyzdyje float tipo kintamojo f reikm 3.14 pertvarkoma int tipo dyd 3 ir priskiriama sveikajam kintamajam i. Kitas bdas padaryti t pat C++ kalboje yra naudojant funkcijas. Po tip atitinkanios funkcijos vardo skliaustuose nurodoma iraika, kurios rezultat norime pertvarkyti reikiam tip: i = int ( f );

4.11. Operatorius sizeof()


is operatorius turi vien parametr, kuris gali bti tip nurodantis bazinis odis arba kintamasis, ir graina skaii, kiek bait atmintyje uima nurodyto tipo reikm: a = sizeof (char);

25

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

iuo sakiniu kintamajam a bus priskirtas 1, nes char tipo kintamajam atmintyje skiriamas tik vienas baitas. sizeof grainamas dydis yra konstanta, kuri visada bna apibrta prie vykdant program.

4.12. Kiti operatoriai


Vliau ioje mokymo priemonje sutiksime daugiau operatori, susijusi su rodyklmis (pointer) arba objektinio programavimo specifika. Jie nagrinjami atitinkamuose skyriuose.

4.13. Operatori pirmumo lygiai


Raant sudtingas, daug operacij turinias iraikas, gali ikilti abejoni, kurios operacijos atliekamos pirma, o kurios vliau. Pavyzdiui, iraika a = 5 + 7 % 2; gali kelti abejones, k gi i tikro gausime: a = 5 + (7 % 2); a = (5 + 7) % 2; // a reikm bus 6 // a reikm bus 0

Teisingas atsakymas yra 6, t.y. pirmos i i dviej iraik rezultatas. Yra nustatyti ne tik aritmetini, bet ir kiekvieno C++ kalboje sutinkamo operatoriaus pirmumo lygiai (prioritetai). Operatori pirmumo lygiai, pradedant aukiausiu ir baigiant emiausiu, yra ie: Pirmumo lygis
1

Operatorius

Paaikinimai Priklausymo sriiai (scope) operatorius

Atlikimo iraikoje kryptis I kairs dein

::

(du dvitakiai)

() [] . -> ++ -dynamic_cast static_cast reinterpret_cast const_cast typeid ++ -- ~ ! sizeof new delete

Raomi po vardo (postfix)

I kairs dein

Vieno operando, raomi prie vard (prefix) Netiesioginiai ir nuorodos (pointers) Operando enklo operatoriai 26 I deins kair

* +

& -

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4 5 6 7 8 9 10 11 12 13 14 15 16

(type) .* * / ->* %

Aikus tipo keitimo Rodykls nar Daugybos, dalybos Sudties, atimties

I deins kair I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I kairs dein I deins kair I deins kair I kairs dein

+ << < == & ^ | && || ?: > != >> <= >=

Postmio Palyginimo Palyginimo Loginio IR su bitais Loginio grietojo-ARBA su bitais Loginio ARBA su bitais Loginio IR Loginio ARBA Slygos

17

= *= /= %= += -= Priskyrimo >>= <<= &= ^= != , Kablelio

18

ios lentels stulpelyje Atlikimo iraikoje kryptis nurodoma tokio paties pirmumo lygio operatori atlikimo tvarka, jei iraikoje paeiliui j yra keletas. Taigi, raydami sudtingas iraikas ir nebdami tikri dl operatori pirmumo lygio, dkime skliaustus. Tokias iraikas yra lengviau skaityti.

27

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

5. Pagrindinis duomen vedimas/ivedimas


Ankstesniuose skyriuose program pavyzdiuose naudojome labai nedaug mogaus ir programos sveikos priemoni. Priemons rezultatams ivesti monitoriaus ekran ir duomenims vesti klaviatra yra laikomos standartinse bibliotekose. C++ kalboje vartojama srauto (stream) svoka, kalbant apie nuoseklios kreipties renginius, kaip monitorius ar klaviatra. Srautas yra simboli seka, prie kurios programa gali prijungti arba i kurios gali paimti simbolius. Todl mums nebtina inoti dalyk, susijusi su rengini fiziniais ypatumais; mums tereikia inoti, kad jais simboliai priimami arba perduodami nuosekliai. Standartinje C++ bibliotekoje yra failas <iostream>, kuriame laikomos duomen srauto vedimo ir ivedimo (input output stream) priemons.

5.1. Standartinis ivedimas ( cout )


prastu atveju programa iveda monitoriaus ekran standartin simboli sraut, kuris C++ kalboje vadinamas cout. cout yra naudojamas drauge su siuntimo operatoriumi << (du enklai maiau negu). cout << "Isveda teksta"; // ekrane bus: Isveda teksta cout << 120; // 120 cout << x; // kintamojo x reikm Operatorius << prijungia prie srauto nurodytus duomenis. Aukiau pateiktame pavyzdyje prie standartinio ivedimo srauto cout bus prijungta eilut "Isveda teksta", skaiius 120 ir kintamojo x reikm. Ivedant simboli eilutes, nepamirkime j apkabinti dvigubomis kabutmis. Pvz., ie du sakiniai duos skirting rezultat: cout << "Labas"; cout << Labas; // ekrane bus odis Labas // ekrane bus kintamojo Labas reikm

Viename ivedimo sakinyje operatorius << gali bti naudojamas kelet kart: cout << "Tai yra " << "C++ kalbos" << " isvedimo sakinys."; iuo sakiniu monitoriaus ekran bus ivestas tekstas: Tai yra C++ kalbos isvedimo sakinys. Imkime dar vien pavyzd, kuriuo ekran ivedama eilui ir kintamj reikmi kombinacija arba keli kintamj reikms: 28

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

cout << "Labas. Man " << amzius << " metai, " << "o mano ugis yra " << ugis << " cm."; Tarkime, kad kintamojo amzius reikm yra 24, o kintamojo ugis 195. Tuomet iuo sakiniu bus ivesta: Labas. Man 24 metai, o mano ugis yra 195 cm. Atkreipkime dmes, kad cout sakiniu ivedant duomenis nepereinama nauj eilut tol, kol aikiai to nenurodysime. Todl iais dviem sakiniais cout << "Tai yra pirmas sakinys."; cout << "Tai jau kitas sakinys."; duomenys bus ivedami vien eilut ir atrodys taip: Tai yra pirmas sakinys. Tai jau kitas sakinys. Rezultatai ivedami kelias eilutes tada, kai cout sakinyje yra aiks nurodymai. iam tikslui gali bti panaudotas specialus perjimo nauj eilut simbolis \n. Pvz., sakiniais cout << "Pirma teksto eilute.\n "; cout << "Antra eilute.\nTrecia eilute."; gausime tok rezultat ekrane: Pirma teksto eilute. Antra eilute. Trecia eilute. Pereiti nauj eilut galima ir panaudojus manipuliatori endl. Pvz.: cout << "Pirmas sakinys." << endl; cout << "Antras sakinys." << endl; ie du cout sakiniai rezultatus ives dvi atskiras eilutes: Pirmas sakinys. Antras sakinys. endl manipuliatoriaus ir specialaus perjimo nauj eilut simbolio \n skirtumas pasireikia srautuose, naudojaniuose ivedimo buferius: endl ivalo bufer. Neirint to, \n ir endl gali bti naudojami nedarant tarp j skirtumo. Ivedam rezultat formatui nustatyti naudojami standartiniame <iomanip> faile saugomi manipuliatoriai. tai du i j: setw(m), m lauko plotis reikmei ivesti; setprecision(n), n skaitmen skaiius ivedamoje reikmje. Jei setw nurodyto lauko ploio skaiiui ivesti nepakanka, is manipuliatorius ignoruojamas. Manipuliatorius setw galioja tik artimiausiai ivedamai reikmei, o setprecision iki naujo nurodymo.

29

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

emiau

pateiktoje

programoje

iliustruojamas

manipuliatori

setw

ir

setprecision veikimas: // manipuliatori setw ir setprecision naudojimas #include <iostream> // i ia ima cout #include <iomanip> using namespace std; int main() { float A = 378.236; cout << "0. A=" << A << endl; cout << "1. A=" << setw(9) << A << endl; cout << "2. A=" << setprecision(2)<< A << endl; cout << "3. A=" << setw(10) << setprecision(4) << A << endl; A = 12.345678; cout << "4. A=" << A << endl; return 0; } 0. A=378.236 1. A= 378.236 2. A=3.8e+02 3. A= 378.2 // i ia ima setw ir setprecision

4. A=12.35

5.2. Standartinis vedimas ( cin )


Klaviatra yra daniausiai naudojamas renginys simboliams vesti. Tokiam vedimui C++ kalboje yra skirtas standartinis srautas cin. cin yra naudojamas drauge su primimo operatoriumi >> (du enklai daugiau negu). Jis raomas prie kintamj, kuris simena i standartinio vedimo srauto paimtus duomenis. Pvz.: int amzius; cin >> amzius; ia pirmuoju sakiniu skelbiamas sveikojo tipo int kintamasis amzius, o sutikusi cin sakin programa sustos ir lauks, kol klaviatra bus vesta kintamojo amzius reikm. Klaviatra vesti duomenys priimami tik po to, kai paspaudiamas klavias enter (kitur jis vadinamas return klaviu). Netgi tada, kai reikia vesti tik vien simbol, dar btina paspausti enter klavi. Visada btina atsivelgti kintamojo tip, kuriam cin sakiniu vedama reikm. Jei yra sveikojo tipo kintamasis, btina vesti sveikj skaii, jei yra simbolio kintamasis - vedamas simbolis, jei simboli eiluts vedama simboli eilut. 30

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// vedimo/ivedimo pavyzdys #include <iostream> using namespace std; int main () {int i; cout << "Iveskite sveikaji skaiciu: "; cin >> i; Iveskite sveikaji skaiciu: 702 Ivestas skaicius yra

cout << "Ivestas skaicius yra " << i; cout << ", dvigubai didesnis yra " << i*2 << ".\n"; 702, dvigubai didesnis yra 1404. return 0; } Vienu cin sakiniu galima vesti reikmes daugiau kaip vienam kintamajam. cin >> a >> b; Tas pats bt jei raytume cin >> a; cin >> b; iais abiem raymo atvejais reikia vesti dvi reikmes: pirm - kintamajam a, antr kintamajam b. vedamos reikms turi bti atskirtos vienu i bd: tarpo simboliu, tabuliacijos simboliu (klavias tab) arba perjimu nauj eilut (klavias enter).

5.3. cin ir simboli eiluts


Eilui tipo (string) kintamj, kaip ir pagrindini tip kintamj, reikmms vesti galima naudoti standartin vedimo sraut cin ir primimo operatori >>. string eilkint; cin >> eilkint; Taiau btina atkreipti dmes tai, kad iuo atveju vedimas nutrksta sutikus tarpo simbol. Taigi, naudojant cin, galima vesti tik vien od. I keleto odi susidedanio sakinio vesti negalsime. Itisas teksto eilutes vesti galima funkcija getline, kuri naudoja standartin vedimo sraut cin:

31

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// cin naudojimas simboli eilutms vesti #include <iostream> #include <string> using namespace std; int main () { string eilut; cout << "Koks jusu vardas ir pavarde? "; getline (cin, eilut); cout << "Labas " << eilut << ".\n"; cout << "Kokiu menu domites? "; getline (cin, eilut); cout << "As irgi domiuosi " << eilut << "!\n"; return 0; } Pastebkime, kad abiejuose kreipiniuose funkcij getline naudojamas tas pats eiluts vardas eilut. Antro kreipinio metu anksiau vesta eilut reikm keiiama naujai vedama. Koks jusu vardas ir pavarde? Jonas Pavardenis Labas Jonas Pavardenis. Kokiu menu domites? Muzika As irgi domiuosi Muzika!

5.4. stringstream funkcija


C++ kalboje yra standartins bibliotekos failas <sstream>, kuriame laikoma standartin funkcija stringstream. i funkcija galina string tipo kintamj traktuoti kaip simboli sraut. Tokiu bdu mes galime naudoti eiluts kintamj vestiems arba ivedamiems simboliams pasidti. Tai ypa naudinga, kai eilutes turin reikia transformuoti skaitin reikm ir atvirkiai. Pvz., norint i eiluts imti simbolius ir i j gauti sveikojo tipo reikm, reikt rayti: string eilut ("1204"); int a; stringstream(eilut) >> a; ia turime paskelbt string tipo kintamj eilut, kuriam suteikta pradin reikm "1204", ir int tipo kintamj a. Toliau, stringstream funkcija, traktuojanti eilut reikm kaip simboli sraut, ir primimo operatorius >> transformuoja simboli eilut int tipo pavidal ir perduoda kintamajam a. Taip kintamasis a gyja skaitin reikm 1024. Programos su srtingstream pavyzdys:

32

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// stringstream naudojimo pavyzdys #include <iostream> #include <string> #include <sstream> using namespace std; int main () { string eilut float kaina=0; int kiekis=0; cout << "Iveskite kaina: "; getline (cin,eilut); stringstream(eilut) >> kaina; cout << "Iveskite kieki: "; getline (cin,eilut); stringstream(eilut) >> kiekis; cout << "Kaina is viso: " << kaina*kiekis << endl; return 0; } iame pavyzdyje standartiniu vedimo bdu skaitins kintamj kaina ir kiekis reikms gaunamos netiesiogiai. getline funkcija, naudodama standartin vedimo sraut cin, vest eilut patalpina kintamajame eilut. Po to stringstream funkcija ir operatorius >> transformuoja vestus simbolius int tipo reikmes (kaina, kiekis). Toks netiesioginis sveikj skaii reikmi vedimas int tipo kintamiesiems suteikia didesnes kontrols galimybes. vedus eilut, galima patikrinti, ar joje yra skaitmenys, ar nra neleistin simboli. Iveskite kaina: 22.25 // i ia ima stringstream

Iveskite kieki: 7

Kaina is viso: 155.75

5.5. Duomen vedimo/ivedimo funkcijos printf ir scanf


C++ kalboje yra vairios duomen vedimo/ivedimo standartins priemons. Jos laikomos ne vien jau mintose bibliotekose <iostream>, <iomanip>, <sstream>, bet ir bibliotekose <cstdio> (C kalboje ji vadinosi <stdio.h>), <fstream>, <istream>, <ostream>, kt. iame skyriuje susipainkime su bibliotekos <cstdio> priemonmis. Standartiniams simboli srautams (ivedamiems ekran ir vedamiems klaviatra) valdyti dar gali bti vartojamos funkcijos printf ir scanf. Kreipini jas pavidalas yra: printf ( ablonas , kintamj_sraas ); scanf ( ablonas, kintamj_adres_sraas );

33

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Pastebkime, kad duomen ivedimo funkcijoje printf po ablono nurodomi kintamj vardai, o vedimo funkcijoje scanf - kintamj adresai. Pavyzdiui, jei turime kintamj vardu a, tai jo adresas atmintyje gaunamas uraius &a. ablonas tai simboli eiluts konstanta (ji raoma tarp dvigub kabui) su joje terptais duomen formatais ir valdaniaisiais simboliais. vedamiems/ivedamiems duomenims skiriam lauk struktra arba j interpretavimo bdas nurodomas duomen formatais. Tipin formato struktra yra tokia: % [poymis] [lauko_dydis] [.tikslumas] duomen_tipas ia staiakampiais skliaustais tik nurodoma, kad to formato elemento gali ir nebti. Formate daniausiai naudojami poymiai yra tokie: (minusas) - lygiuoti ivedamus duomenis pagal kairj lauko krat; + (pliusas) - nurodyti ivedamo skaiiaus enkl, net jei jis teigiamas. Jei poymis nenurodomas, ivedama reikm lygiuojama pagal deinj lauko krat, o prie ivedam teigiam skaii pliuso enklas nededamas. Formate duomen_tipai ymimi raidmis, parodytomis ioje lentelje: Duomen tipo raid d arba i o u x c f s e p Duomen tipas sveikasis skaiius (int); atuntainis sveikasis skaiius; sveikasis skaiius be enklo; eioliktainis sveikasis skaiius; simbolis (char); slankaus kablelio skaiius (float); simboli eilut (string); rodyklins formos skaiius (float); rodykl (pointer)

Ivedimo funkcijoje printf valdantieji simboliai gali bti terpiami bet kurioje ablono vietoje. Primename, kad valdaniojo simbolio uraymo sintaks yra \simbolis, pvz., \n , \t ir kt. Jeigu norime ablone turti dvigub kabut (") arba atbulai pasvirus brkn (\), jie turi bti raomi atitinkamai \" ir \\. To prieastis yra ta, kad kabute (") nurodoma eiluts pradia ir pabaiga, o simboliu \ - valdantysis simbolis. Programa, iliustruojanti funkcijos printf veikim: #include <cstdio> using namespace std; int main() { int a = 1023; long int b = 2222; short int c = 123; 34

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

unsigned int d = 1234; char e = X; float f = 3.14159; double g = 3.1415926535898; printf("1. a=%d\n", a); // deimtainis sveikasis printf("2. a=%o\n", a); // atuntainis sveikasis printf("3. a=%x\n", a); // eioliktainis sveikasis printf("4. b=%ld\n", b); // deimtainis ilgas printf("5. d=%u\n", d); // sveikasis be enklo printf("6. e=%c\n", e); // simbolis printf("7. f=%f\n", f); // realusis skaiius printf("8. f=%e\n", c); // realusis su eile printf("\n"); // tik pereiti kit eilut printf("9. a=%7d\n", a); // 7 pozicij laukas printf("10. a=%7d\n", a); // - veda nuo kaires c = 5; d = 8; printf("11. a=%*d\n",c,a); // lauko plotis 5 poz. printf("12. a=%*d\n",d,a); // lauko plotis 8 poz. printf("13. f=%f\n", f); // realusis skaiius printf("14. f=%10f\n", f); // 10 poz. realiam printf("15. f=%10.3f\n", f); // trupmenai 3 p. printf("16. g=%11.8f\n", g); // trupmenai 8 p. printf("17. g=%+11.8f\n", g); // su + printf("18. a=%d g=%5.2f\n", a, g); return 0; } 1. a=1023 2. a=1777 3. a=3ff 4. b=2222 5. d=1234 6. e=X 7. f=3.141590 8. f=3.141590e+000 9. a= 1023 10. a=1023 11. a= 1023 12. a= 1023 13. f=3.141590 14. f= 3.141590 15. f= 3.142 16. g= 3.14159265 17. g=+3.14159265 18. a=1023 g= 3.14

vedimo funkcijos scanf ablone daniausiai nurodomi tik vedam duomen formatai. Paiuose formatuose nurodomas tik duomen tipas. Pvz.: int a; float b; scanf("%d %f", &a, &b); iuo atveju klaviatra vedami nurodyto tipo skaiiai turi bti atskirti tarpu, tabuliacijos simboliu (\t) arba perjimu kit eilut (\n). Pvz., vedus 45 8.56, kintamasis a gis reikm 45, o kintamasis b 8.56. Jei funkcijos scanf ablone prie duomen formatus bus nurodyti kakokie simboliai, tai juos taip pat reiks vesti. Pvz.: scanf("a= %d f= %f", &a, &b); ia klaviatra vedami duomenys turs atrodyti taip: a= 45 f= 8.56 .

35

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

5.6. Darbas su duomen failais


Failai (bylos, rinkmenos) - tai ioriniais kompiuterio renginiais vedami/ivedami duomen rinkiniai (tekstai, skaiiai, vaizdai, garsai). Pvz., duomenys kompiuterio atmint gali bti vedami klaviatra, i disko, kompiuteri tinklo ryio kanalu, mikrofonu, vaizdo kamera, kt. I kompiuterio atminties duomenys (skaiiavimo rezultatai) daniausiai ispausdinami, ivedami ekran, disk, garsiakalb, perduodami kompiuteri tinklo ryio kanalu. Failai egzistuoja atskirai nuo program. Sukurti failai saugomi vairiose laikmenose (diskuose, flash atminties kitukuose, kt.). Norint skaityti anksiau sukurt fail, kompiuterio programoje turi bti nurodyta, kokiu renginiu tai norima daryti. Kuomet failas yra kuriamas (raomas), kompiuterio programoje turi bti nurodyta, kuriuo renginiu (atitinkamai - laikmenoje) tai norima daryti. Taigi, kompiuterio programose turi bti kintamieji, kuriais bt paymti (atstovaujami) failai. C++ kalboje toki kintamj tipas daniausiai nurodomas baziniu odiu ifstream, ofstream. Kintamieji-failai daniausiai apraomi taip: ifstream a, b; // kai norima skaityti fail (input); ofstream x, y, z; // kai norima rayti fail (output). Prie naudojant itokio tipo kintamuosius, programoje turi bti nuoroda preprocesoriui #include <fstream>, kad jis program traukt standartin bibliotek <fstream>, kurioje laikomos duomen failuose vedimo/ivedimo priemons. Programoje apraytas kintamasis-failas turi bti susiejamas su konkreiu fiziniu failu, t.y. jis turi nurodyti rengin, kur tas failas yra ar bus kuriamas, ir failo vard. ie duomenys kintamajam-failui suteikiami inicializuojant tok kintamj #include <fstream> ofstream failas1 ("c:\\rezultatai.txt"); arba atidarant fail specialia open funkcija #include <fstream> ofstream failas1; failas1.open ("c:\\rezultatai.txt"); Failo iekojimo kelio nuorodoje reikia rayti du atbulai pasvirusius brknius (\\), o ne vien, kaip kitur yra prasta, nes specialieji simboliai pradedami \, pvz., \n, \t, \? . Baigus darb su failu, jis udaromas close funkcija: failas1.close();

36

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Pastebkime, kad tarp kintamojo-failo vardo ir funkcijos vardo dedamas takas. Taip nurodoma, kur gi fail norime atidaryti ar udaryti, nes programa gali dirbti i karto su keletu fail. Vliau, kai susipainsime su objektinio programavimo pagrindais, matysime, kad ifstream, ofstream atitinka klasi vardus, open(), close() mint klasi nari-funkcij vardus, o failas1 ms paskelbto objekto vard. Pateikiame duomen ivedimo fail itis program: // pagrindins ivedimo fail operacijos #include <iostream> #include <fstream> using namespace std; int main () { ofstream isifa; isifa.open ("c:\\rezult.txt"); isifa << "Sis tekstas rasomas i faila.\n"; isifa.close(); return 0; }

[failas c:\rezult.txt] Sis tekstas rasomas i faila.

ia ms paskelbtas isifa atitinka mums jau inom standartin cout, ivedant duomenis ekran. Analogikai yra ir su duomen vedimu i failo: // pagrindins vedimo i failo operacijos #include <iostream> #include <fstream> using namespace std; int main () { ifstream ivisfa; int a, b; ivisfa.open ("c:\\duom.txt"); ivisfa >> a >> b; // veda i failo cout << a << "+" << b << "=" << a+b << endl; ivisfa.close(); return 0; }

[failas c:\duom.txt] 27 482 [ekrane] 27+482=509

ioje programoje ivisfa atitinka standartin cin, vedant duomenis klaviatra. ia i failo vest skaii suma ivedama ekran standartiniu cout. Matome, kad prie duomen vedim ar ivedim failai turi bti atidaromi, o baigus darb - udaromi. Failo atidarymo prasm yra ta, kad, pvz., ivedant duomenis 37

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

disk, diske vis pirma turi bti parengta sritis kuriamam failui (kataloge raomas failo vardas, paskiriama jam vieta diske), programai atmintyje papildomai paskiriami laukai, kurie vadinami vedimo/ivedimo buferiais. Udarant fail, pvz., diske uraomas failo pabaigos poymis (jei failas buvo kuriamas), ilaisvinama vedimo/ivedimo buferiams skirta atminties sritis. Panagrinkime dar vien program, kuri prao nurodyti, i kurio failo norsime vesti duomenis ir kur fail norsime rayti rezultatus: #include <iostream> #include <fstream> using namespace std; int main () { ifstream aa; ofstream bb; char s [50]; int a, b; cout <<"Is kurio failo vesite duomenis?\n"; cin >> s; aa.open (s); cout <<"I kuri faila isvesite rezultatus?\n"; cin >> s; bb.open(s); aa >> a >> b; bb << a << "+" << b << "=" << a+b << endl; aa.close(); bb.close(); return 0; }

Is kurio failo vesite duomenis? c:\duom.txt I kuri faila isvesite rezultatus? C:\rez.txt [c:\duom.txt] 27 482 [c:\rez.txt] 27+482=509

Dirbant su failais gali atsitikti, kad norimo failo nepavyksta atidaryti, o vedant duomenis i fail pasiekiama failo pabaiga. ioms situacijoms kontroliuoti yra atitinkamai funkcijos is_open() ir eof(). Funkcijos is_open() reikm yra true, jei failas atidarytas, o eof() duoda false, jei dar nepasiekta failo pabaiga. i funkcij naudojimo pavyzdys: // tekstinio failo skaitymas #include <iostream> #include <fstream> #include <string> using namespace std;

38

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int main () { string eilut; ifstream manofa; manofa.open ("pavyz.txt"); if ( !manofa.is_open() ) { cout << "Failo atidaryti nepavyko"; return 1; } while ( !manofa.eof() ) { getline (manofa, eilut); cout << eilut << endl; } manofa.close(); return 0; } ia simboli eilutms vesti naudojome geltine() funkcij, tik jos argumentas yra ms paskelbtas kintamasis manofa, o ne cin, kaip t darme 5.3. cin ir simboli eiluts skyriuje. C++ kalboje yra ir daugiau priemoni duomenims vesti/ivesti. Pvz., funkcijomis read() ir write() perduodami dvejetainio (binarinio) pavidalo duomenys. vedimo/ivedimo metu jokia duomen transformacija i dvejetainio pavidalo simbolin pavidal ir atvirkiai neatliekama. Mintas funkcijas ir eil kit nagrinsime vliau, kai susipainsime su rodyklmis. Viena teksto faile eilute. Kita teksto faile eilute.

39

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

6. Valdantieji sakiniai
Programose sakiniai danai nra vykdomi tokia eils tvarka, kaip jie yra urayti. Jose galimi isiakojimai, sakini kartojimai, sprendim primimai. iam tikslui yra valdantieji sakiniai, kuriais nurodoma, kada ir k programa turi daryti esant tam tikroms aplinkybms. Prie praddami nagrinti valdaniuosius sakinius, vis pirma susipainkime su sudtinio sakinio arba bloko svoka. Blokas tai sakini grup, apkabinta riestiniais skliaustais {}. Jame sakiniai, kaip priimta C++ kalboje, vienas nuo kito skiriami kabliatakiais. Pvz.: { sakinys1; sakinys2; sakinys3; } Daugelyje valdymo sakini, kaip j sudtin dalis, yra kitas sakinys. Tas kitas sakinys gali bti paprastas (jis baigiamas kabliatakiu) arba sudtinis (keletas blok sudarani sakini). Tais atvejais, kai norime turti paprast sakin, apkabinti jo riestiniais skliaustais { } nereikia. Taiau sudtinio sakinio atveju riestiniai skliaustai { }, kuriais formuojamas blokas, btini.

6.1. Slygos sakinys: if ir else


Slygos sakinio, prasidedanio baziniu odeliu if, bendrasis pavidalas yra toks: if (slygos_iraika) sakinys Jis vykdomas taip. Vis pirma apskaiiuojama slygos_iraika. Jei jos reikm yra true, tuomet yra vykdomas nurodytas sakinys. Jei jos reikm yra false, tuomet nurodytas sakinys nevykdomas ir programa tsiama sakiniu, einaniu po slygos sakinio. Pvz., programos fragmentas if (x == 100) cout << "x yra lygus 100"; atspausdins x yra lygus 100 , jei kintamojo x reikm i tikro bus lygi 100. Taip pat yra galimyb nurodyti, k reikt daryti, kai slygos_iraikos rezultatas yra false. Tam gali bti naudojamas bazinis odis else, kuriuo ipleiamas if sakinys: if (slygos_iraika) sakinys1 else sakinys2 Pvz., sakiniais if (x == 100) cout << "x yra lygus 100"; else cout << "x nera lygus 100";

40

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

ekran bus ivesta x yra lygus 100 , jei x reikm yra 100. Kitais atvejais bus ivesta x nera lygus 100. Po else gali bti raomas naujas if sakinys. Toliau einantis pavyzdys rodo, kaip bus elgiamasi, kai x yra daugiau, lygus ir maiau u 0: if (x > 0) cout << "x yra teigiamas"; else if (x < 0) cout << "x yra neigiamas"; else cout << "x yra lygus 0"; Prisiminkime, kad akoje norint atlikti kelis sakinius, juos btina apskliausti riestiniais skliaustais {}.

6.2. Ciklai ( while, do-while, for )


Cikl paskirtis yra kartoti sakin (paprast arba sudtin) tam tikr kiek kart arba kol nebus vykdyta tam tikra slyga. while ciklas. io ciklo bendrasis pavidalas yra while (slygos_iraika) sakinys Jame nurodytas sakinys turi bti kartojamas tol, kol prie tai apskaiiuota slygos_iraika duoda rezultat true. emiau pateikiama programa while ciklui pailiustruoti: // programa su while ciklu #include <iostream> using namespace std; int main () { int n; cout << "Iveskite pradini skaiciu: "; cin >> n; while (n>0) { cout << n << ", "; --n; // n reikm mainama vienetu } cout << "\n Pirmyn!"; return 0; }

Iveskite pradini skaiciu: 8

8, 7, 6, 5, 4, 3, 2, 1,

Pirmyn!

41

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

ios programos vykdymo pradioje vartotojui ekran ivedamas priminimas Iveskite pradini skaiciu. vedus skaii, while ciklo blokas (sudtinis sakinys) kartojamas tol, kol n>0. Pirmyn! Atkreipkime dmes tai, kad while ciklo bloke turi bti sakinys, turintis tak tam, kad ciklo slygos_iraikos rezultatas tapt false. Kitokiu atveju turtume nesibaigiant cikl. Todl ms turtoje programoje yra sakinys --n; Pastebkime, kad while ciklas gali bti neatliktas n karto, pvz., jei vestume neigiam n reikm. do-while ciklas. io ciklo bendrasis pavidalas yra toks: do sakinys while (slygos_iraika); Jis vydomas taip pat, kaip ir while ciklas. Skirtumas yra tik toks, kad ia slygos_iraika apskaiiuojama po to, kai vykdomas sakinys. Taip garantuojama, kad sakinys bus vykdytas bent vien kart. Pvz., emiau pateikiama programa prays vesti skaiius tol, kol nevesime 0. // programa su do-while ciklu #include <iostream> using namespace std; int main () { unsigned long n; cout << "Darbui baigti iveskite 0. \n"; do { cout << "Iveskite skaiciu: "; cin >> n; cout << "Jus ivedete: " << n << "\n"; } while (n != 0); return 0; } Kai tik n pasidaro lygus 0, ciklas nutraukiamas ir ekran ivedama

Darbui baigti iveskite 0. Iveskite skaiciu: 12345 Jus ivedete: 12345 Iveskite skaiciu: 160277 Jus ivedete: 160277 Iveskite skaiciu: 0 Jus ivedete: 0

do-while cikl nutraukimo slyga suformuojama ciklo bloke. Ms pavyzdyje tai vestas skaiius 0. for ciklas. io ciklo bendrasis pavidalas yra: for (inicializacija; slyga; reikms_keitimas) sakinys Jame sakinys kartojamas tol, kol slyga duoda reikm true. Kaip matome, jame dar yra inicializacijos sakinys ir reikms_keitimo sakinys. itoks ciklas specialiai yra sukurtas pakartotinam veiksm vykdymui vadovaujantis skaitikliu. Skaitiklis vis 42

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

pirma yra inicializuojamas (jam suteikiama pradin reikm), o vliau jo reikm keiiama nurodytu dydiu kiekvienos iteracijos metu. for ciklo veiksm sekos punktai yra tokie: 1. Atliekama inicializacija. Paprastai tai pradins reikms suteikimas skaitiklio kintamajam. is veiksmas atliekamas tik vien kart. 2. Tikrinama slyga, ar skaitiklio kintamojo reikm nra didesn (maesn) u nurodyt dyd. Jei gaunama reikm true, ciklo sakinys yra vykdomas. Prieingu atveju ciklas baigiamas ir sakinys nebevykdomas. 3. Vykdomas ciklo sakinys. Tai gali bti paprastas arba sudtinis sakinys (blokas). 4. Atlikus sakin, vykdomas reikms_keitimo sakinys. Daniausia keiiama skaitiklio kintamojo reikm (didinama arba mainama) ir grtama ciklo veiksm sekos 2 punkt. emiau pateikiama programa su for ciklu, kuriame kintamojo-skaitiklio n reikm yra mainama: // programa su for ciklu #include <iostream> using namespace std; int main () { for ( int n=10; n>0; n-- ) cout << n << ", "; cout << "\n Pirmyn!"; return 0; } for cikle inicializacijos ir reikms_keitimo sakini gali ir nebti. Jie gali bti tuti, taiau laukus skiriantys kabliatakiai (;) turi bti raomi. Pvz., gali bti raoma for ( ; n<10 ; ), jei nereikia inicializacijos ir reikms_keitimo sakini, arba for ( ; n<10; n++ ), jei nereikia tik inicializacijos sakinio. Galbt inicializacija buvo atlikta dar iki for ciklo. for cikle inicializacija ir reikms_keitimas gali susidti i keleto iraik. Iraikos skiriamos kableliu (,). Pvz., tarkime, cikle norime inicializuoti daugiau kaip vien kintamj: for ( n=0, i=100; n!=i; n++, i-- ) { // bloko sakiniai ... } is ciklas bus kartojamas 50 kart, jei n ir i reikms nebus keiiamos bloko sakiniais. 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, Pirmyn!

43

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

6.3. Perokimo sakiniai ( break, continue, goto, exit() )


break sakinys. Cikle sutikus break sakin, ciklas nutraukiamas, nors jo tsimo slyga ir yra vykdyta. break gali bti naudojamas begaliniams ciklams nutraukti arba nutraukti ciklams dar jiems normaliai nepasibaigus. Pavyzdys: // break sakinio naudojimo pavyzdys #include <iostream> using namespace std; int main () { int n; for (n=10; n>0; n--) { cout << n << ", "; if (n==3) // slyga ciklui nutraukti { cout << "\n Ciklas nutrauktas!"; break; } } return 0; }

10, 9, 8, 7, 6, 5, 4, 3,

Ciklas nutrauktas!

ioje programoje for ciklas nutraukiamas, kai kintamojo-skaitiklio n reikm lygi 3. continue sakinys. continue sakinys galina nutraukti tik ciklo iteracij jos nebaigus, perokti kitos teracijos pradi ir tsti cikl, kol jis nesibaigs normaliai. Pavyzdys: // continue sakinio naudojimo pavyzdys #include <iostream> using namespace std; int main () { for ( int n=10; n>0; n-- ) { if (n==5) continue; cout << n << ", "; } cout << "\n Pirmyn!"; return 0; }

10, 9, 8, 7, 6, 4, 3, 2, 1, Pirmyn!

ia for ciklo iteracija, kai n lygu 5, nutraukiama, bet ciklas vykdomas toliau.

44

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

goto sakinys. goto sakiniu beslygikai perokama kit programos viet. Perokimo vieta nurodoma yme, kuri kaip argumentas nurodoma goto sakinyje. yms raomos tik prie tuos programos sakinius, kuriuos norsime perokti goto sakiniais. Tarp yms ir sakinio dedamas dvitakis. goto sakinyje po nurodytos yms dvitakis nededamas. Apskritai, struktriniame Pavyzdys: // goto sakinio vartojimo pavyzdys #include <iostream> using namespace std; int main () { int n=10; zym1: cout << n << ", "; n--; if (n>0) goto zym1; cout << "\n Pirmyn!"; return 0; } ir objektiniame programavime goto sakiniai

nevartotini. Juos naudoja maiau iprus programuotojai.

10, 9, 8, 7, 6, 5, 4, 3, 2, 1,

Pirmyn!

ioje programoje ciklas yra suorganizuotas naudojant if ir goto sakinius. exit() funkcija. Atkreipkime dmes, kad exit() yra gatava funkcija ir laikoma bibliotekoje <cstdlib>. exit() funkcijos paskirtis yra stabdyti programos darb, nurodant specifin stabdymo kod. ios funkcijos prototipas (C++ kalboje prototipas tai funkcijos pirmasis sakinys- antrat) yra: void exit (int isejimokodas); isejimokodas reikm naudoja kai kurios operacins sistemos, ir ji gali bti naudojama kitose kvieiamose programose. Pagal susitarim isejimokodas lygus 0 (sakinys exit(0);) reikia, kad programa baig darb normaliai. Kitokios isejimokodas reikms rodo, kad programoje buvo klaid arba gauti nenumatyti rezultatai.

45

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

6.4. Variantinis sakinys ( switch )


Variantinio sakinio switch struktra yra kakiek savita. Priklausomai nuo jame esanios iraikos reikms, vykdoma viena i sakini grupi, kuri gali bti norimas kiekis. Tai iek tiek panau if ir else if sakinius. switch sakinio pavidalas yra toks: switch (iraika) { case konstanta1: sakini_grup_1; break; case konstanta2: sakini_grup_2; break; ... default: default_sakini_grup } Jis vykdomas taip: vis pirma apskaiiuojama iraika ir tikrinama, ar gauta reikm lygi konstantai1. Jeigu taip, vykdoma sakini_grup_1 iki sutinkamas break sakinys. Sutikus break, perokama switch sakinio gal. Jei iraikos reikm nra lygi konstantai1, tuomet tikrinama, ar ji nra lygi konstantai2. Jei lygu, tai vykdoma sakini_grup_2 iki break ir tuomet perokama switch sakinio gal. Gal gale, jei iraikos reikm nra lygi n vienai i nurodyt konstant (case konstant gali bti tiek, kiek mums reikia), vykdomi sakiniai, esantys po yms default, jei ji yra. default dalis switch sakinyje nebtina. Abu emiau pateikti program fragmentai duoda tok pat rezultat: switch pavyzdys switch (x) { case 1: cout << "x lygu 1"; break; case 2: cout << "x lygu 2"; break; default: cout << "x nezinomas"; } if-else ekvivalentas if (x == 1) { cout << "x lygu 1"; } else if (x == 2) { cout << "x lygu 2"; } else { cout << "x nezinomas"; }

switch sakinys yra kakiek neprastas C++ kalboje, nes jame vartojamos yms, o ne blokai (sudtiniai sakiniai). Tai veria mus naudoti break po kiekvienos 46

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

sakini_grups, kuri reikia atlikti esant specifinei slygai. Praleidus break bt vykdoma ir kita i eils einanti sakini_grup, kol nepasiektume switch sakinio galo arba nesutiktume break. Pvz., jei mes neraysime break po pirmos sakini grups, tai programa automatikai neperoks switch sakinio pabaig, o vykdys toliau i eils einanius sakinius. Tokiu bdu ivengiama bereikaling riestini skliaust {} kiekvieno varianto sakini grupei. Taip pat tai gali bti naudinga norint vykdyti t pai sakini grup, esant vairioms iraikos reikmms. Pvz.: switch (x) { case 1: case 2: case 3: cout << "x lygu 1, 2 arba 3"; break; default: cout << "x nelygu 1, 2 nei 3"; } Pastebkime, kad switch sakinyje vietoje konstant negalima vartoti kintamj, pvz., n, arba reikmi interval, pvz., (1..5). Jei reikalingi skaiiavimai tikrinant reikmes i kakurio intervalo, naudokime if arba else if sakinius.

6.5. Paprast program pavyzdiai


Prie raant program vis pirma reikia sudaryti sprendiamo udavinio algoritm, t.y. plan, kokius veiksmus ir kokia eils tvarka numatome atlikti. emiau pateiktuose pavyzdiuose, kur veiksm atlikimo tvarka yra aiki i udavinio slygos, algoritmo neapraome. Kai kuriuose i j, programavimo niuansams suprasti, algoritmai aikinami plaiau.

47

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

1 pavyzdys.

Ispausdinkime sveikj skaii nuo 1 iki N ingsniu 1 kvadrat, kb ir kvadratini akn lentel. N reikm veskime klaviatra.

/* Programa skaii laipsni lentelei ivesti. Autorius - V.Pavardenis, tel. 222555, data - 2007 06 26 */ #include <iostream> // i ia ims cin ir cout #include <cmath> // matematini funkcij biblioteka. Ims sqrt #include <cstdlib> // i ia ims funkcij system using namespace std; #define bruksnys "\n-----------------------------------\n" main () { int n, j, kvadratas, kubas; float saknis; cout << "Iveskite sveikaji skaiciu N: "; cin >> n ; // vedame skaii, iki kurio skaiiuosime laipsnius // toliau ivedame lentels antrat

cout << bruksnys; cout << "Skaic. Kvadr. Kubas Saknis \n"; cout << bruksnys; // toliau skaiiuojame ir ivedame rezultatus for ( j = 1; j <= n; j++ ) { kvadratas = j*j; kubas = kvadratas*j ; saknis = sqrt(j) ; // sqrt kvadr. aknies traukimo funkcija cout << j << "\t" << kvadratas << "\t" << kubas << "\t" << saknis << endl; } cout << bruksnys; system ("PAUSE"); // stabdo program rezultatams pairti return 0; }

48

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

2 pavyzdys.

Apskaiiuoti sum ir faktorial

S=

N k =1

1 1 1 1 + + ++ , 1 2 3 N

N! = 1 * 2 * 3 * * N ,

kur N > 0. N reikm veskime klaviatra.

/* programa skaiiuoja sum ir faktorial; autorius - V.Pavardenis; tel. 2144555; data 2007 06 26 */ #include <iostream> #include <cstdlib> using namespace std; // i ia ims funkcij system

main () { int k, n; float suma; long fakt; cout << "Iveskite sveikaji skaiciu N: "; cin >> n; // toliau parengiami kintamieji suma ir fakt sumai ir faktorialui kaupti suma = 0 ; fakt = 1 ; for (k=1; k<=n; k++) { suma = suma + 1.0/k ; // 1.0, kad dalybos rezultatas btu float tipo fakt = fakt * k ; } // toliau ivedami skaiiavimo rezultatai cout << "Kai N = " << n << ", suma = " << suma << endl; cout << "Faktorialas = " << fakt << endl; system ("PAUSE"); // stabdoma programa rezultatams pairti return 0; }

49

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

3 pavyzdys.

Apskaiiuoti funkcij x + ( x + 1) 2 + ( x + 2)3 , F(x)= 1+


1 1 1 1 + 2 + 3 + + 10 , x x x x

kai x < 1 , kai 1 <= x <= 3 , kai x > 3 .

1 + sin ( x ) , x reikm veskime klaviatra.

/* programa isiakojanios funkcijos reikmei apskaiiuoti */ #include <iostream> #include <cmath> #include <cstdlib> using namespace std; // matematini funkcij biblioteka. Ims sin // i ia ims funkcij system

main () { float a, x, f; int k; cout << Iveskite x reikme: ; cin >> x; if (x < 1) f = x + (x+1)*(x+1) + (x+2)*(x+2)*(x+2); if ((1 <= x) && (x <= 3)) { f = 1; a = 1; for ( k=1; k<=10; k++ ) { a = a/x; f = f+a; } // vardiklyje augs x laipsnis

} if (x > 3) f = 1 + sin(x); // toliau ivedame skaiiavimo rezultatus cout << Kai x = << x << , funkcijos reiksme = << f << endl; system ("PAUSE"); // stabdoma programa rezultatams pairti return 0;
}

50

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

4 pavyzdys.

Trigonometrins funkcijos cos ( x ) , kai x ireikiamas radianais, reikm randama sumuojant tokios matematins eiluts narius: x2 x4 x6 cos( x ) 1 + + 2! 4! 6! Neirint to, kad C++ kalboje matematini funkcij bibliotekoje <cmath> yra cos(x) standartin funkcija, kosinusui apskaiiuoti sudarykime program patys. x reikm veskime klaviatra, o kosinus skaiiuokime tikslumu = 0.00001. Algoritmas. Matematins eiluts, kurios narius sumuojant gaunama cos(x) reikm, k-tasis x2 narys, remiantis prie buvusiu nariu, randamas taip: a k = a k 1 * , kur 2 k ( 2 k 1)

a0 =1; k =1, 2, ...


Taigi, reikia apskaiiuoti sum cos( x ) a 0 + a 1 + a 2 + ... ia sumuojam nari kiekis i anksto nra inomas. Skaiiavimai nutraukiami tada, kai tik eilinis (paskutinis) sumos narys absoliutiniu dydiu tampa maesnis u pasirinkt . Jeigu vesta x reikm yra didel, ji redukuojama keletu period 2. Taip pat palyginimui iveskime kosinuso reikm, gaut standartine funkcija. // programa kosinusui apskaiiuoti; autorius V.Pavardenis; tel. 2222228 #include <iostream> #include <cmath> // matematini funkcij biblioteka. Ims fabs, cos #include <cstdlib> // i ia ims funkcij system using namespace std; #define eps 0.00001 // tokiu tikslumu skaiiuosime #define PI 3.14159 main () { float a, s, x; int k; cout << Iveskite x reiksme: ; cin >> x; while (fabs(x) > 2*PI) // redukuojam x reikm, atimdami period 2*PI { if (x>0) x-=2*PI; else x+=2*PI; } /* toliau pasiruoiam kintamj pradines reikmes: k matem.eiluts nario numeriui, a nulinis narys, s nari sumai kaupti */

51

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

k = 0; a = 1 ; s = 1 ; do {k=k+1; a = -a*x*x/(2*k*(2*k-1)); s=s+a; } while (fabs(a) > eps);

// didinamas matem.eiluts nario numeris // gaunama eilinio sumos nario a reikm // kaupiama nari suma // fabs duoda a absoliutin dyd float tipo

cout << Musu programa gautas cos(x)= << s << endl; cout << Standart. f-ja gautas cos(x)= << cos(x) << endl; system ("PAUSE"); return 0; } // stabdoma programa rezultatams pairti

52

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

7. Funkcijos
Funkcijos galina skaidyti sudtingas programas atskiras dalis - modulius. Naudodami jas galime inaudoti vis C++ kalbos struktrinio programavimo potencial, geriau organizuoti programuotoj kolektyvo darb. Funkcija tai sakini grup, kuri gali bti vykdoma kreipusis j i bet kurios programos vietos. Bendrasis jos pavidalas yra toks: tipas vardas ( parametras1, parametras2, ...) { sakiniai } kur: tipas tai bazinis odis, nurodantis funkcijos apskaiiuotos ir grinamos reikms tip. Jis yra nebtinas (optional); - vardas, kur duodam funkcijai ir kuriuo reiks kreiptis j; - parametrai tai kintamieji (j gali bti tiek, kiek reikia), nurodant kiekvieno j tip (pvz., int a). ie kintamieji yra lokals ir galioja tik funkcijos ribose. Parametrai galina perduoti funkcijai argument reikmes, kai yra kreipiamasi j. Parametrai vienas nuo kito skiriami kableliu; - sakiniai, apkabinti riestiniais skliaustais {}. Jie dar vadinami funkcijos knu. tai pirmasis funkcijos pavyzdys:
-

// funkcijos pavyzdys #include <iostream> using namespace std; int sudetis (int a, int b) { int r; r=a+b; return (r); } int main () { int z; z = sudetis (5,3); cout << "Rezultatas yra " << z; return 0; }

Rezultatas yra 8

Praddami nagrinti pavyzd prisiminkime, kad C++ programa visada pradedama vykdyti nuo main funkcijos. ia main funkcija prasideda int tipo kintamojo z paskelbimu. Po to, priskyrimo sakinio deinje pusje yra kreipinys

53

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

funkcij sudetis. Pastebkime, kad kreipinys funkcij ir funkcijos antrat (pirmasis funkcijos sakinys) yra panas: int sudetis ( int a , int b ) z = sudetis ( 5, 3 ); Funkcijos antrats parametrai ir kreipinio funkcij argumentai turi aik atitikim. main funkcijoje kreipusis funkcij sudetis, programos vykdymas i main funkcijos persikelia funkcij sudetis, o abiej argument reikms 5 ir 3 atitinkamai perduodamos parametrams a ir b. Funkcijoje sudetis yra paskelbtas lokalus kintamasis int r , kuris priskyrimo sakiniu r=a+b; gyja kintamj a ir b sumos reikm, t.y. 8, nes kreipimosi funkcij sudetis metu a gijo reikm 5, o b reikm 3. Sakiniu return (r); baigiamas funkcijos sudetis darbas ir grtama t programos viet, i kur buvo kreiptasi (iuo atveju main funkcijos atitinkam viet). Tuo paiu kreipinio viet grinama return sakinyje nurodyto kintamojo r reikm 8. Pastaroji reikm main funkcijoje priskiriama kintamajam z ir ivedama ekran. Panagrinkime dar vien funkcijos pavyzd: // kitas funkcijos pavyzdys #include <iostream> using namespace std; int atimtis (int a, int b) { int r; r=a-b; return (r); } int main () { int x=5, y=3, z; z = atimtis(7,2); cout << "Pirmas rezultatas: " << z << '\n'; cout << "Antras rezultatas: " << atimtis(7,2) << '\n'; cout << "Trecias rezultatas:" << atimtis(x,y) << '\n'; z= 4 + atimtis(x,y); cout << "Ketvirtas rezultatas: " << z << '\n'; return 0; }

Pirmas rezultatas: 5 Antras rezultatas: 5 Trecias rezultatas: 2 Ketvirtas rezultatas: 6

54

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

iame pavyzdyje turime funkcij atimtis. Ji skaiiuoja abiej parametr gaunam reikmi skirtum, kuris ir grinamas kaip rezultatas. Nagrindami pagrindin funkcij main pastebsime, kad joje yra keletas kreipini funkcij atimtis. Kreipinys funkcij pakeiiamas reikme, kuri ji grina return() sakiniu. Matome, kad kreipiniai funkcijas gali bti vairiose programos vietose, kur leistina rayti iraikas: cout sakinyje, priskyrimo sakinyje ir daug kur kitur.

7.1. void tipo funkcijos


Prisiminkime bendrj funkcijos pavidal: tipas vardas ( parametras1, parametras2, ... ) { sakiniai } Matome, kad pradioje nurodomas tipas, t.y. funkcijos grinamos reikms tipas. Bet k daryti, jei mums nereikia grinamos reikms? Tarkime, mes norime sudaryti funkcij, kuri tik ivest praneim ekran. Mums nereikia jokios jos grainamos reikms. Tokiais atvejais funkcijos tipas nurodomas baziniu odiu void (angl. void tuias, neturintis). // void funkcijos pavyzdys #include <iostream> using namespace std; void pranesu () { cout << "As taip pat esu funkcija!"; } int main () { pranesu (); return 0; } Bazinis odis void taip pat gali bti funkcijos parametr srae, kai norime aikiai parodyti, kad jokie parametrai kreipiantis funkcij nereikalingi. Pvz., funkcija pranesu galt bti paskelbta taip: void pranesu (void) { cout << "As taip pat esu funkcija!"; } Taiau rayti void parametr srae nebtina. C++ kalboje funkcijos parametr sraas tiesiog gali bti tuias, jei nereikia parametr. Taip pat btina atsiminti, kad kreipinio void tipo funkcij pavidalas yra atskiras sakinys, susidedantis tik i funkcijos vardo ir suskliaust parametr. Nesant

As taip pat esu funkcija!

55

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

parametr, skliaustai vis viena turi bti raomi. Todl kreipinys funkcij pranesu yra toks: pranesu (); Skliaustai aikiai parodo, kad tai yra kreipinys funkcij, o ne C++ kalbos kintamasis. Kreipinys pranesu; yra klaidingas.

7.2. Argument reikmi ir adres perdavimas parametrams


Lig iol nagrintose funkcijose j parametrams bdavo perduodamos kreipini argument reikms. Kitaip tariant, reikms i argumentams skirtos vietos atmintyje buvo nukopijuojamos parametrams paskiriamas atskiras atminties vietas. Pvz., tarkime, kad mes kreipiams ms anksiau turt funkcij sudetis tokiu bdu: int x=5, y=3, z; z = sudetis (x, y); Jos parametrams perduodamos kreipinio argument x ir y reikms, t.y. 5 ir 3 a, 3 atitinkamai. Kadangi funkcijos antrat yra int sudtis ( int a, int b ), tai 5 b. iuo atveju jokie funkcijos sudetis lokalij kintamj a ir b reikmi keitimai neturi takos kintamj x ir y reikmms, kurie yra ioriniai funkcijos atvilgiu. Bet kartais bt naudinga, jei funkcija galt pakeisti iorini kintamj reikmes. iam tikslui pasiekti kreipimosi funkcij metu parametrams reikia paskirti ne atskir viet atmintyje, bet t pai, kuri jau paskirta argumentams. Tokiu bdu parametr patalpinus argumento adresu, keiiant vieno reikm, natralu, keisis ir kito reikm. Pvz.: // argument adreso perdavimas funkcijos parametrams #include <iostream> using namespace std; void dvigub (int& a, int& b, int& c) { a*=2; // prisiminkime, kad tai a = a*2; b*=2; c*=2; } int main () { int x=1, y=3, z=7;
56

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

dvigub (x, y, z); cout << "x=" << x << ", y=" << y << ", z=" << z; return 0; }

x=2, y=6, z=14

Pirmas dalykas, k ia reikt atkreipti dmes, kad skelbiant funkcij dvigub, parametro tip nurodanio bazinio odio gale pridedamas simbolis &. Tai reikia, kad kreipiantis funkcij parametras atmintyje bus talpinamas tuo paiu adresu kaip ir kreipinio argumentas. Kadangi sutapatinamos argumento ir parametro atminties sritys, tai keiiant parametro reikm keisis ir argumento reikm. Taigi, turint toki funkcijos antrat ir kreipin j void dvigub ( int& a, int& b, int& c ) dvigub ( x, y, z ); reikmi perdavimas tarp argument ir parametr vyks abiem kryptimis: x a, y b, z c. Tai ir yra prieastis, kodl aukiau pateiktos programos main funkcijos kintamiesiems x, y ir z pradioje priskyrus reikmes 1, 3 ir 7 atitinkamai, po kreipinio funkcij dvigub ekran ivedami dvigubai didesni skaiiai. Jei funkcij dvigub btume paskelb po parametr tipo neraydami &, void dvigub (int a, int b, int c) tai main funkcijoje po kreipinio funkcij dvigub ekran bt ivestos nepakeistos kintamj x, y ir z reikms. Argument ir parametr atminties sutapatinimas yra efektyvus bdas pasiekti, kad funkcija apskaiiuot daugiau kaip vien reikm. emiau pateikiamoje programoje yra funkcija priespo, apskaiiuojanti prie ir po einanius skaiius duotam skaiiui. // daugiau kaip vien reikm apskaiiuojanti funkcija #include <iostream> using namespace std; void priespo (int x, int& pries, int& po) { pries = x-1; po = x+1; } int main () { int x=100, y, z; priespo (x, y, z); cout << "Skaicius=" << x << endl;

Skaicius=100

57

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

cout << "Ankstesnis=" << y << endl; << "Kitas=" << z; return 0; }

Ankstesnis=99 Kitas=101

7.3. Numatytj reikmi parametrai


Skelbiant funkcij, kiekvienam jos parametrui galima nurodyti numatytj (default) reikm. Funkcijos antratje tokiems parametrams numatytoji reikm suteikiama priskyrimo operatoriumi. i reikm naudojama tada, jei kreipinyje funkcij nra parametr atitinkanio argumento. Jei kreipinyje funkcij yra tok parametr atitinkantis argumentas, numatytoji reikm ignoruojama ir parametrui perduodama argumento reikm. Pvz.: // numatytosios funkcij parametr reikms #include <iostream> using namespace std; int dalyba (int a, int b=2) { int r; r=a/b; return (r); } int main () { cout << dalyba (12) << endl; cout << dalyba (20,4); return 0; } ioje programoje yra du kreipiniai funkcij dalyba. Pirmajame kreipinyje dalyba (12) yra tik vienas argumentas, nors pagal funkcijos apra galt bti du. Taigi, funkcijai dalyba pradjus darb, jos antrojo parametro reikm bus lygi 2, o rezultatas bus 6. Antrajame kreipinyje dalyba (20,4) yra du argumentai. Todl funkcijos dalyba antrojo parametro b ( int b=2 ) numatytoji reikm 2 ignoruojama, o b gyja kreipinio argumento reikm 4. Funkcijos rezultatas bus 5.
58

6 5

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

7.4. Funkcijos vienodais vardais


C++ kalboje dvi skirtingos funkcijos gali turti tok pat vard, jei j parametr tipai arba kiekis skiriasi. Pvz.: // funkcijos vienodais vardais #include <iostream> using namespace std; int daryk (int a, int b) { return (a*b); } float daryk (float a, float b) { return (a+b); } int main () { int n=5, m=2; float x=5.0, y=2.0; cout << daryk (x,y) << endl; cout << daryk (n,m) << endl; return 0; }

7
10

iame pavyzdyje yra apibrtos dvi funkcijas tokiu paiu vardu daryk. Taiau vienos i j parametrai yra int tipo, o kitos - float tipo. kuri i j reikia kreiptis, kompiliatorius nustato inagrinjs kreipinio argument tipus. Pirmo kreipinio rezultatas yra argument reikmi suma 7, o antro sandauga 10. Atkreipkime dmes tai, kad negalima naudoti tokio paties vardo dviem funkcijoms, jei skiriasi tik j grainam reikmi tipai.

7.5. Funkcij ablonai ( template )


Funkcijos ablonas tai specialus funkcijos pavidalas, kuris galina pritaikyti vien funkcij darbui su vairaus tipo kintamaisiais. Tai padeda ivengti pakartotino funkcijos programos raymo skirtingo tipo duomenims. itokia funkcij savyb gaunama panaudojus ablono parametrus. Tai specials parametrai, kuriais galima perduoti funkcijai informacij apie duomen tip. Funkcijos ablono bendrasis pavidalas yra toks: template <typename vardas> funkcijos_programa; arba template <class vardas> funkcijos_programa;
59

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

ablono parametras gali bti apibdinamas baziniu odiu typename arba class. Pvz., sudarykime ablon funkcijos, kuri i gaut dviej skaii graina didesnj: template <typename tpv> tpv didesnis (tpv a, tpv b) { tpv x; if (a>b) x=a; else x=b; return (x); } ia panaudotas ablono parametras tpv, skirtas duomen tipui nurodyti, taiau konkreti jo reikm dar nra aiki. Ji tampa aiki tik po kreipinio funkcij. Bendrasis kreipinio ablonu apibrt funkcij pavidalas yra: funkcijos_vardas <tipas> (argumentai); Todl ms funkcijos didesnis ablon turi bti kreipiamasi, pvz., taip: int j=5, k=6, m; m = didesnis <int> (j,k); Kompiliatorius, sutiks tok kreipin, funkcijos ablone automatikai vietoje parametro tpv stato ms atveju int ir tik tada kreipiasi funkcij. Imkime itisos programos pavyzd: // funkcijos ablonas #include <iostream> using namespace std; template <typename tpv> tpv didesnis (tpv a, tpv b) { tpv x; if (a>b) x=a; else x=b; return (x); } int main () { int j=5, k=6, m; float p=13.83, q=5.47, r; m = didesnis <int> (j,k); r = didesnis <float> (p,q); cout << m << endl;

6
60

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

cout << r << endl; return 0; }

13.83

ia funkcijos didesnis ablon kreipiamasi du kartus. Pirmo kreipinio argumentai yra int tipo, o antro float tipo. Todl kompiliatorius parengia dvi funkcijos versijas ir kiekvien kart kreipiamasi reikiam funkcijos versij. Turto pavyzdio atveju kompiliatorius sugeba parengti dvi funkcijos didesnis versijas, netgi jei kreipiniuose jas akivaizdiai nenurodysime tipo parametro, t.y. jei vietoje didesnis<int>(j,k) raysime tiesiog didesnis(j,k), o vietoje didesnis<float>(p,q) raysime didesnis(p,q). Jei kreipinyje yra, pvz., int tipo argumentai j ir k, tai ir funkcijos ablone juos atitinkantys parametrai a ir b taip pat turi bti int tipo. Todl ablono parametras tpv tampa int. Kadangi ms funkcijos ablone yra tik vienas ablono parametras tpv, o pati funkcija turi du parametrus a ir b, kurie yra vienodo tipo, mes negalime kreiptis funkcij naudodami skirtingo tipo argumentus. Pvz., int k; float p; q = didesnis (k,p);

// neleistinas kreipinys

Taiau galima apibrti funkcijos ablon, kuriame bt daugiau kaip vienas ablono parametras. Pvz.: // funkcijos ablonas su dviem ablono parametrais #include <iostream> using namespace std; template <typename t1, typename t2> t2 mazesnis (t1 a, t2 b) { float x; t2 y; if (a<b) x=a; else x=b; y=t2(x); // tam atvejui, kai t2 tampa int, nes x float tipo return (y); } int main () { int j=5, k=6, m, n; float p=13.83, q=5.47, r, v; r = mazesnis <int,float> (j,p);
61

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

m = mazesnis <float,int> (q,k); v = mazesnis <float,float> (p,q); n = mazesnis <int,int> (j,k); cout << r << endl; cout << m << endl; cout << v << endl; cout << n << endl; return 0; } iame pavyzdyje funkcijos mazesnis ablone yra du ablono parametrai t1 ir t2. Kreipiniai funkcij mazesnis taip pat gali bti raomi ir paprasiau, t.y. akivaizdiai nenurodant tip ablono parametrams: r = mazesnis(j,p); k = mazesnis(q,k); v = mazesnis(p,q); n = mazesnis(j,k); Pastebkime, kad funkcijos mazesnis grainamos reikms tipas sutampa su antro argumento tipu. Taip pat atkreipkime dmes funkcijos mazesnis ablono sakin y=t2(x); Jame t2 panaudotas kaip funkcijos vardas, kuri konvertuoja argumento x reikm i float tipo t2 tip (ir. 4.10 skyri Aikiai nurodomi duomens tipo keitimo operatoriai).

7.6. inline funkcijos


Funkcijos aprae inline baziniu odiu nurodoma kompiliatoriui, kad jis funkcijos sakinius (funkcijos kn) terpt kiekvien programos viet, kur yra kreipinys t funkcij. inline nuoroda nekeiia funkcijos elgesio. Ji tik padeda ivengti kintamj steko sudarymo ir okinjim programoje i vienos vietos kit. inline funkcijos yra makrokomand ekvivalentas. Patartina inline naudoti tik trumpoms funkcijoms. Bendrasis inline funkcij pavidalas: inline tipas vardas(parametras1,parametras2,){sakiniai} jas kreipiamasi taip pat, kaip ir kitas funkcijas.

7.7. Rekursijos
Rekursija tai funkcijos savyb jos viduje esaniais sakiniais kreiptis save pai. Tai gali bti naudinga vairiuose udaviniuose, pvz., skaiiaus n faktorialui n! gauti:
62

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

n! = 1*2*3*(n-1)*n. Tai galima urayti ir taip: n! = n*(n-1)! Rekursyvi funkcija skaiiaus faktorialui skaiiuoti atrodo taip: // faktorialo skaiiavimas rekursyviai #include <iostream> using namespace std; long faktorialas (long a) { if (a > 1) return (a * faktorialas (a-1)); else return (1); } int main () { long skaicius; cout << "Iveskite skaiciu: "; cin >> skaicius; cout << skaicius << "! = " << faktorialas (skaicius); return 0; } Pastebkime, kad funkcijoje faktorialas kreipiamasi save pai, jei argumento reikm yra didesn u 1. Prieingu atveju funkcijos reikm bt lygi 0 ir turtume nesibaigiant cikl, nes toliau vykt daugyba i neigiam skaii, kol nevykt steko perpildymas. Apskritai, faktorialo skaiiavimo funkcijos ribotumas yra tas, kad ja, naudojant netgi long tipo kintamuosius, galima gauti rezultat, ne didesn kaip 15!.

Iveskite skaiciu: 9

9! = 362880

7.8. Funkcij skelbimas


Lig iol ms nagrintose programose funkcijos buvo paskelbtos anksiau, negu sutikdavome pirm kreipin jas. ie kreipiniai buvo pagrindinje main funkcijoje, kuri rame programos pabaigoje. Bet jeigu main funkcij raytume anksiau nei kitas programos funkcijas, tai gautume kompiliavimo klaid. Prieastis yra ta, kad funkcija turi bti paskelbta anksiau, nei sutinkamas pirmas kreipinys j. Yra bdas leidiantis nerayti viso funkcijos programos teksto (kno) anksiau u main ar kitoki funkcij, kuriose yra kreipiniai pirmj. Iki kreipinio funkcij utenka paskelbti tik funkcijos prototip, o ne vis funkcijos tekst. Funkcijos

63

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

prototipe nurodomas tik jos tipas, vardas ir parametr tipai. To visikai pakanka kompiliatoriui. Taigi, bendrasis funkcijos prototipo pavidalas yra: tipas vardas ( parametro1_tipas, parametro2_tipas, ); Funkcijos prototipas - tai tik funkcijos antrat, kurioje gali bti praleisti parametr vardai (parametr tipai turi bti). Kadangi funkcijos sakiniai (knas) praleidiami, tai prototipo gale raomas kabliatakis (;). Pvz., funkcijos daugyba, turinios du int tipo parametrus a ir b, prototipas gali bti raomas vienu i dviej bd: int daugyba (int a, int b); int daugyba (int, int); Raant ir parametr vardus, funkcijos prototipas bna aikesnis. emiau pateikiamas C++ programos pavyzdys, kurioje naudojami funkcij prototipai, o patys funkcij tekstai raomi po pagrindins funkcijos main: // funkcij prototip naudojimas #include <iostream> using namespace std; void nelyg (int a); void lyg (int a); // funkcijos nelyg prototipas // funkcijos lyg prototipas

int main () { int i; cout << "Darbui baigti iveskite 0.\n" << endl; do { cout << "Iveskite skaiciu: "; cin >> i; nelyg (i); } while (i!=0); return 0; } void nelyg (int a) // visas funkcijos nelyg tekstas { if ((a%2)!=0) cout << "Skaicius nelyginis.\n"; else lyg (a); } void lyg (int a) // visas funkcijos lyg tekstas { if ((a%2)==0) cout << "Skaicius lyginis.\n"; else nelyg (a); }

Darbui baigti iveskite 0. Iveskite skaiciu: 9 Skaicius nelyginis. Iveskite skaiciu: 6 Skaicius lyginis. Iveskite skaiciu: 1030 Skaicius lyginis. Iveskite skaiciu: 0 Skaicius lyginis.

64

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Savo esme i programa nra efektyvi. Ja tik norta pailiustruoti prototip veikim. I pradi akis krenta funkcij nelyg ir lyg paskelbimas: void nelyg (int a); void lyg (int a); Tai galina kreiptis ias funkcijas, pvz., pagrindinje main funkcijoje. Daugumai moni atrodo logikiau, kai main funkcija, nuo kurios pradedamas visos programos darbas, yra priekyje. Vis programoje naudojam funkcij prototip skelbimas programos pradioje praktikai yra naudingas. Taip elgiasi dauguma programuotoj.

65

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

8. Masyvai
Masyvas tai tokio paties tipo element visuma, talpinam gretimose atminties srityse. Atskiras masyvo elementas nurodomas po masyvo vardo raant indeksus. Pvz., masyvas vardu skaiciai, turintis penkis int tipo elementus, gali bti pavaizduotas tokia schema:
0 1 2 3 4

skaiciai
int

ia kiekvienas staiakampis atitinka masyvo element, kuris ms atveju yra int tipo. Masyvo pirmojo elemento indeksas visada yra lygus 0, nepriklausomai nuo masyvo dydio. Kaip ir visi kintamieji, taip ir masyvai turi bti paskelbti prie naudojant juos. C++ kalboje bendrasis masyv paskelbimo pavidalas yra toks: tipas vardas [kiekis]; Staiakampiuose skliaustuose nurodoma, kiek element norime turti masyve. Aukiau schemoje pavaizduotas masyvas skaiciai turi bti skelbiamas taip: int skaiciai [5]; Atkreipkime dmes, kad masyvo element kiekis turi bti nurodomas konstanta. Apie kitokias galimybes ioje mokymo priemonje raoma vliau.

8.1. Masyv inicializacija


prastu bdu paskelbus lokalj (pvz., galiojant tik funkcijos ribose) masyv, jo element reikms yra neapibrtos. Kita vertus, globalieji ir statiniai masyvai automatikai upildomi nuliais. Lokalij ir globalij masyv atvejais yra galimyb suteikti j elementams pradines reikmes, t. y. inicializuoti masyvus, raant tas reikmes tarp riestini skliaust {}. Pvz., int skaiciai [5] = { 16, 2, 77, 40, 1207 }; iuo skelbimu sukuriamas masyvas, kur schematikai galima pavaizuoti taip:
0 1 2 2 77 3 40 4 1207

skaiciai

16

Reikmi kiekis tarp riestini skliaust {} turi bti ne didesnis, nei tarp staiakampi skliaust [] nurodytas masyvo element kiekis.
66

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Kai yra nurodomos masyvo element pradins reikms, masyvo element kiekio tarp staiakampi skliaust [ ] galima ir nenurodyti. Tokiu atveju kompiliatorius laikys, kad masyvo dydis yra toks, kiek pradini reikmi nurodyta riestiniuose skliaustuose {}: int skaiciai [] = { 16, 2, 77, 40, 1207 }; Taip paskelbtame masyve skaiciai bus 5 elementai, nes tiek pradini reikmi nurodme.

8.2. Kreipimasis masyvo elementus


Bet kurioje programos vietoje, kur yra masyvo galiojimo sritis, galima kreiptis jo elementus individualiai, kaip tai daroma su prastais kintamaisiais. Atskiras masyvo elementas nurodomas taip: vardas [indeksas] Remiantis anksiau turtu pavyzdiu, kur masyvas skaiciai turi penkis int tipo elementus, kiekvienas i j gali bti nurodomas taip: skaiciai [0], skaiciai [1],, skaiciai [4]. Norint priskirti reikm 97 treiam masyvo skaiciai elementui, reikt rayti tok sakin: skaiciai [2] = 97; o norint treio elemento reikm priskirti, pvz., kintamajam a, reikt rayti taip: a = skaiciai [2]; Taigi, iraika skaiciai [2] visais atvejais traktuojama kaip int tipo kintamasis. Pastebkime, kad paskelbus 5 element masyv, paskutinio jo elemento indeksas yra vienetu maesnis, pvz., skaiciai [4]. Jeigu uraysime skaiciai [5], tai ieisime u masyvo rib. C++ kalbos sintakss prasme tai yra leistina, kreipiantis elementus u masyvo rib kompiliatorius klaidos nefiksuos, taiau programos rezultatai gali bti klaidingi. Viso to prieast pamatysime vliau, kai susipainsime su rodyklmis (pointer). Taip pat atkreipkime dmes du staiakampi skliaust [ ] naudojimo atvejus dirbant su masyvais. Pirma, skelbiant masyv tarp j nurodomas masyvo dydis, antra juose nurodomas iraikose naudojamo atskiro masyvo elemento indeksas. To nereikt painioti. int skaiciai [5]; skaiciai [2] = 97; // skelbiamas masyvas // kreipiamasi masyvo element

Skelbiant masyv, pradioje raomas tip nurodantis bazinis odis, o prie atskir masyvo element tokio odio niekada nebna.
67

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Toliau pateikama keletas su masyvais leistin veiksm: skaiciai [0] = a; skaiciai [a] = 75; b = skaiciai [a+2]; skaiciai [ skaiciai [a] ] = skaiciai [2] + 5; // programa su masyvu #include <iostream> using namespace std; int skaiciai [] = {16, 2, 77, 40, 1207}; int n, rezult=0; int main () { for ( n=0 ; n<5 ; n++ ) rezult += skaiciai [n]; cout << rezult; return 0; } i programa suskaiiuoja vis masyvo skaiciai element sum.

1342

8.3. Daugiamaiai masyvai


Daugiamaiai masyvai gali bti apibdinami kaip masyv masyvai. Pvz., dvimat masyv galime sivaizduoti kaip vienodo tipo element lentel.
0 0

ruta

1 2

ia pavaizduotas dvimatis 3 i 5 masyvas ruta. Toks int tipo skaii masyvas C++ kalboje skelbiamas taip: int ruta [3] [5]; Jo antros eiluts ketvirtas (ketvirto stulpelio) elementas nurodomas kaip ruta [1] [3] Atsiminkime, kad indeksai visada prasideda nuo 0. Daugiamaiai masyvai neapsiriboja dviem indeksais. J gali bti tiek, kiek reikia. Bet bkime atids. Masyvui reikalingas atminties dydis greitai didja sulig kiekvienu nauju indeksu.
68

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Daugiamaiai masyvai yra tik programuotoj abstrakcija. Tok pat rezultat galima gauti su vienmaiu masyvu, kurio dydis bt lygus daugiamaio masyvo indeks sandaugai: int ruta [3] [5]; int ruta [15]; // ekvivalentiki masyvai // 3 * 5 = 15

Panagrinkime toliau du program fragmentus, duodanius tok pat rezultat. Viename i j naudojamas dvimatis masyvas, kitame vienmatis masyvas. Dvimatis masyvas #define plotis 5 #define aukstis 3 int ruta [aukstis] [plotis]; int n,m; int main () { for (n=0; n<aukstis; n++) for (m=0; m<plotis; m++) ruta [n] [m] = (n+1)*(m+1); return 0; } Vienmatis masyvas #define plotis 5 #define aukstis 3 int ruta [aukstis * plotis]; int n,m; int main () { for (n=0; n<aukstis; n++) for (m=0; m<plotis; m++) ruta [n*plotis+m] = (n+1)*(m+1); return 0; }

N viena i i program neiveda rezultat ekran, taiau patalpina juos masyvui ruta skirtoje atmintyje tokia tvarka:
0 0 1 2 3

1
2 4 6

2 3 6 9

3 4 8 12

4 5 10 15

ruta

1 2

iose programose apibrtosios konstantos (#define) pavartotos tam, kad bt paprasiau modifikuoti program. Pvz., prireikus masyvo indekso aukstis reikm 3 pakeisti 4, tai galima padaryti labai paprastai. Tereikia programos eilut #define aukstis 3 pakeisti #define aukstis 4 Daugiau joki pakeitim programoje daryti nereikia.

8.4. Masyvai kaip funkcij parametrai


Funkcij parametrais gali bti ir masyvai, neirint to, kad C++ kalboje nra galimybs perduoti itis masyv. Todl funkcijos parametrai-masyvai patalpinami
69

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

atmintyje tik kreipinio funkcij argumentams-masyvams skirtais adresais, t.y. vyksta tik argumento-masyvo adreso perdavimas funkcijai. Masyvas, kaip funkcijos parametras, skelbiamos funkcijos antratje nurodomas po jo vardo raant staiakampius skliaustus [] , taiau juose nieko nenurodant. Pvz.: void procedura ( int para [] ) ia parametras vardu para yra int tipo masyvas. Norint iai funkcijai perduoti masyv, paskelbt kaip int mas[40]; , pakanka tokio kreipinio: procedura (mas); emiau pateikiama programa, kurioje yra funkcija su parametru-masyvu: // masyvai kaip funkcij parametrai #include <iostream> using namespace std; void masyvo_isvedimas (int para [], int ilgis) { for ( int n=0; n<ilgis; n++ ) cout << para [n] << " "; cout << "\n"; } int main () { int mas1 [] = {5, 10, 15}; int mas2 [] = {2, 4, 6, 8, 10}; masyvo_isvedimas (mas1, 3); masyvo_isvedimas (mas2, 5); return 0; }

5 10 15 2 4 6 8 10

ia funkcijos masyvo_isvedimas pirmas parametras ( int para [] ) gali priimti bet kokio ilgio int tipo masyv. Tam yra vestas antras parametras, kuriuo funkcijai perduodamas apdorojamo masyvo ilgis. Tai galina for ciklu ivesti ekran tiek element, kokio dydio masyvas buvo kreipinyje funkcij masyvo_isvedimas. Funkcijos parametru gali bti ir daugiamatis masyvas. Pvz., trimaio masyvo, kaip parametro, formatas yra: tipas vardas [] [skaiius] [skaiius] Funkcijos su daugiamaiu masyvu kaip parametru antrats pavyzdys: void procedura ( int trimas [] [3] [4] ) Pastebkime, kad tarp pirmj staiakampi skliaust neraoma nieko, kai tuo tarpu kituose skliaustuose turi bti sveikieji skaiiai.
70

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

8.5. Program su masyvais pavyzdiai


1 pavyzdys.

Turime 20 skaii masyv. Klaviatra veskime juos kompiuterio atmint, o po to apskaiiuokime vest skaii vidurk bei raskime didiausi ir maiausi skaiius. Rezultatus iveskime monitori taip: vis pirma iveskime vis masyv po 8 skaiius kiekvienoje eilutje, o po to vidurk, didiausi ir maiausi skaiius. Algoritmas. Iekant didiausio elemento, vis pirma daroma prielaida, kad pirmas masyvo elementas (arba bet kuris kitas masyvo elementas) yra didiausias. Jis simenamas atskirame kintamajame. Po to io atskiro kintamojo reikm lyginama su visais masyvo elementais. Kai tik randamas dar didesnis masyvo elementas, atskirame kintamajame simenama jo reikm. Analogikai randamas ir maiausias elementas.
/* Skaii masyvo vidurkio, didiausio ir maiausio element radimas */ #include <iostream> #include <cstdlib> // i ia ima funkcij system using namespace std; #define KIEKIS 20 #define BRUKSNYS -------------------------------- float mas [KIEKIS]; float did, maz, vid; main () { int j; cout << Iveskite << KIEKIS << skaiciu: << endl; for (j=0; j<KIEKIS; j++) cin >> mas [j]; vid = 0; // skaii sumai kaupti did = mas [0]; // prielaida, kad didiausias elementas yra mas[0] maz = mas [0]; // prielaida, kad maiausias elementas yra mas[0] for ( j=0; j<KIEKIS; j++ ) { vid += ma s[j]; if (mas [j]>did) did = mas [j]; if (mas [j]<maz) maz = mas [j]; } vid /= KIEKIS; // gaunamas skaii vidurkis // toliau ivedame ekran masyv po 8 elementus eilutse cout << Skaiciu masyvas: << endl; cout << BRUKSNYS << BRUKSNYS << endl;

71

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

for (j=0; j<KIEKIS; j++) { if ( (j % 8) == 0 ) cout << endl; // pereinam nauj eilut cout << mas [j] << \t; } cout << endl << BRUKSNYS << BRUKSNYS << endl; // toliau ivedami rezultatai cout << Skaiciu vidurkis: << vid << endl; cout << Diziausias skaicius: << did << endl; cout << Maziausias skaicius: << maz << endl; system ("PAUSE"); // stabdo program rezultatams pairti return 0; }

2 pavyzdys.

Tarkime, turime ne didesn kaip 100 skaii masyv. veskime norim masyvo element kiek, o po to iveskime juos monitori, surikiuotus nemajimo tvarka (tolesnis elementas turi bti didesnis arba lygus prie buvusiam). Prie vedant masyvo elementus, vis pirma veskime masyvo element kiek nurodant skaii. Algoritmas. Masyvo elementams rikiuoti yra daug algoritm. Imkime vien i paprastesni burbulo algoritm. Rikiuojant lyginami du gretimi masyvo elementai ir, jeigu reikia, jie sukeiiami vietomis. Tokiu bdu prabgus vis masyv, didiausias elementas perkeliamas masyvo gal. Po to viskas daroma i naujo, ir antr viet nuo masyvo galo perkeliamas antras pagal dyd masyvo elementas, ir t.t. Tam programoje reikia ciklo cikle.
// skaii masyvo element rikiavimas #include <iostream> #include <cstdlib> // i ia ima funkcij system using namespace std; #define BRUKSNYS "--------------------------------" float skm [100]; main () { float t; int k, m, n;

72

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

cout << Kiek skaiciu noresite ivesti: ; cin >> k; cout << Iveskite << k << skaiciu: << endl; for (m=0; m<k; m++) cin >> skm [m]; // toliau rikiuojame masyvo skm elementus nemajimo tvarka for (m=0; m<(k-1); m++) for (n=0; n<(k-1-m); n++) if (skm [n] > skm [n+1]) { t = skm [n]; // masyvo element skm [n] = skm [n+1]; // keitimas skm [n+1] = t; // vietomis } // toliau ekran ivedamas surikiuot skaii masyvas cout << \nSurikiuoti skaiiai:\n; for (m=0; m<k; m++) cout << skm [m] << ; cout << endl; system ("PAUSE"); // stabdo program rezultatams pairti return 0; }

ios programos if sakinyje pakeitus palyginimo enkl prieingu, masyvo elementai bt rikiuojami nedidjimo tvarka.

3 pavyzdys.

Turime 6 x 8 dydio matric (dvimat masyv). Raskime jos didiausi element ir ekran iveskime visus to stulpelio ir tos eiluts elementus, kuriuose yra didiausias matricos elementas. Algoritmas. Matricos didiausias elementas iekomas panaiai, kaip ir vienmaio masyvo atveju (ir. 1 pavyzd iame skyriuje). Skirtumas toks, kad matricos atveju reikia ciklo cikle. ia mums rpi ne pati didiausio elemento reikm, bet jo vieta matricoje, t.y. indeksai. Todl pradioje, papildomam kintamajam suteikus kurio nors matricos elemento reikm (prielaida, kad jis yra didiausias), btina ufiksuoti ir jo indeksus. Tikrinimo metu radus didesn element, ufiksuojami ir jo indeksai.

73

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// matrica #include <iostream> #include <cstdlib> // i ia ima funkcij system using namespace std; #define STULP 8 #define EILUT 6 float matr [EILUT] [STULP]; main () { float t; int st, eil, m, n; cout << Iveskite << EILUT << x << STULP << dydzio matricos elementus:\n; for (m=0; m<EILUT; m++) for (n=0; n<STULP; n++) cin >> matr [m] [n]; cout << "\nIvesta matrica\n"; for (m=0; m<EILUT; m++) { for (n=0;n<STULP; n++) cout << matr [m] [n] <<"\t"; cout << endl; } // iekome didiausio elemento matricoje matr t = matr [0] [0]; // prielaida, kad didiausias elementas yra matr[0][0] st = 0; eil = 0; // didiausio elemento indeks reikmms for (m=0; m<EILUT; m++) for (n=0; n<STULP; n++) if (matr [m] [n] > t) { t = matr [m] [n]; st = n; eil = m; } // ivedame atitinkamo matricos matr stulpelio ir eiluts elementus cout << \nStulpelis su didz. matricos elementu:\n; for (m=0; m<STULP; m++) cout << matr [m] [st] << ; cout << \nEilute su didz. matricos elementu:\n; for (m=0; m<EILUT; m++) cout << matr [eil] [m] << ; cout << endl; system ("PAUSE"); // stabdo program rezultatams pairti return 0; }

74

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

9. Simboli sekos
C++ kalboje yra galinga standartin biblioteka <string>, kurioje yra patogios priemons darbui su simboli eilutmis. Apie tai trumpai rayta 2.6 skyriuje. Kadangi eiluts i tikro yra simboli sekos, jas galima pavaizduoti kaip char tipo element masyvus. Pvz., masyvas char mikas [20]; gali siminti 20 simboli. J galima pavaizduoti taip: mikas

Taigi, tokiame masyve galsime saugoti iki 20 simboli ilgio sekas. Kadangi simboli masyve galima saugoti ir trumpesnes simboli sekas nei nurodytas masyvo dydis, yra naudojamas specialus simbolis \0 (null) sekos pabaigai nurodyti. Ms char tipo 20 element dydio masyvui mikas priskirtas simboli sekas Labas ir Su sventemis galima bt pavaizduoti taip: mikas L S a u b a s s v \0 e n t e m i s \0

Pastebkime, kad priskirtos simboli sekos gale terpiamas null simbolis (\0). Po jo likusiuose baituose yra neapibrta informacija.

9.1. Simboli sek inicializacija


Simboli masyvams yra taikomos prastos masyv taisykls. Tokiam masyvui norint suteikti pradin reikm (norint inicializuoti j) jo skelbimo metu, turtume elgtis taip pat, kaip ir su kitokio tipo masyvais. Riestiniuose skliaustuose {} reikt nurodyti kiekvieno masyvo elemento reikm: char zodis [] = { 'L', 'a', 'b', 'a', 's', '\0' }; char tipo masyvo atveju pradins reikms simboli gale dar reikt nurodyti ir null simbol \0. Taiau char tipo masyvams yra dar vienas bdas pradinei reikmei nurodyti. Tai simboli eiluts. Ankstesniuose ios mokymo priemons skyriuose jau daug kart naudojome eilutes. J tekstas buvo apkabinamas dvigubomis kabutmis (), pvz., Labas.
75

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Dvigubomis kabutmis apkabinta eilut yra ne kas kita, kaip simboli seka, kurios pabaiga automatikai nurodoma null simboliu (\0). Todl turt char tipo masyv zodis lengviau yra inicializuoti taip: char zodis [] = "Labas"; Abiem inicializavimo atvejais masyvas zodis paskelbiamas 6 element dydio: 5 elementai odiui Labas plius jo pabaig nurodaniam null simboliui (\0). Pastebkime, kad po char tipo masyvo paskelbimo priskyrimas jam reikms priskyrimo sakiniu skiriasi nuo inicializacijos skelbimo metu. char tipo masyvai ir simboli eiluts yra itisi duomen blokai, o priskyrimo operatoriumi kopijuoti blok negalima. Todl tokie priskyrimo sakiniai, kaip zodis = "Labas"; zodis [] = "Labas"; zodis = { 'L', 'a', 'b', 'a', 's', '\0' }; yra neleistini. Viso to prieastis taps aikesn, kai susipainsime su rodyklmis (pointer).

9.2. Simboli sek naudojimas


Natralu, kad C++ kalboje eiluts yra traktuojamos kaip simboli sekos, pasibaigianios null simboliu (\0). Todl jos gali bti naudojamos daug kur. Faktikai eiluts yra char tipo element masyvai ir taip pat gali bti naudojamos daugeliu atvej. Pvz., vedimo/ivedimo sakiniai cin ir cout palaiko null simboliu pasibaigianias simboli sekas, todl jos gali bti naudojamos iuose sakiniuose. Pvz.: // null simboliu pasibaigianios simboli sekos #include <iostream> using namespace std; int main () { char klausk [] = "Iveskite savo varda: \n"; char atsakyk [] = "Labas, "; char vardas [80]; cout << klausk; cin >> vardas; cout << atsakyk << vardas << "!"; return 0; }

Iveskite savo varda: Ona Labas, Ona!

76

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Kaip matome, ioje programoje yra paskelbti trys char tipo masyvai. Pirmieji du yra inicializuoti panaudojus eilutes, o treias paliktas neinicializuotas. Taiau bet kuriuo atveju turi bti nurodomas masyvo dydis. Pirm dviej masyv klausk ir atsakyk dydis nustatomas pagal inicializacijai panaudotas eilutes, o treio masyvo vardas dydis nurodytas aikiai 80. Belieka pridurti, kad char tipo masyvuose saugomos simboli sekos lengvai gali bti konvertuojamos eilutes, t.y. string tipo objektus, priskyrimo operatoriais: string eilut; char masyv [] = "kazkoks tekstas"; eilut = masyv;

77

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

10. Rodykls (pointers)


Lig iol kintamuosius irjome kaip atminties sritis. jas galjome kreiptis kintamj vardais. Mums nereikjo rpintis fiziniu ms duomen idstymu atmintyje, o prireikus j kreipms tiesiog kintamj vardais. Kompiuterio atmint galima sivaizduoti kaip bait sek. Kiekvienas baitas turi savo numer, kuris vadinamas adresu. Adresai eina i eils: 0, 1, 2, ... .

10.1. Adreso operatorius ( & )


Kai tik paskelbiame kintamj, jam numatoma reikiamo dydio atminties sritis (kakiek bait). Paleidus program, j automatikai paskiria operacin sistema. Tam tikrais atvejais mus gali dominti, nuo kurio adreso atmintyje yra patalpintas ms kintamasis programos vykdymo metu. To gali reikti, norint paslinkti kintamj atmintyje. Kintamojo adresui gauti naudojamas adreso operatorius (& - ampersendo enklas), kuris raomas kintamojo vardo priekyje. Pvz.: tom = &alge; iuo sakiniu kintamojo alge adresas priskiriamas kintamajam tom. Atkreipkime dmes, kad ia kalbame ne apie kintamojo alge turin, o apie jo adres, nes vardo priekyje yra &. Tarkime, vykdant program kintamasis alge atmintyje buvo patalpintas adresu 2476. is skaiius (2476) yra tik atsitiktinai sugalvotas, kad bt lengviau aikinti kai kurias idjas. I tikro iki programos vykdymo pradios mes negalime inoti kintamojo tikrojo adreso. Tarkime yra toks programos fragmentas: alge = 25; pran = alge; vyt = &alge; Jis duoda tokias kintamj reikmes: alge 25, pran 25, vyt 2476. Pirmose dviejose io programos fragmento eilutse yra standartiniai priskyrimo sakiniai. Pirmuoju kintamajam alge priskiriama reikm 25 (jo adresas, tarme, yra 2476). Antrajame sakinyje imama kintamojo alge reikm ir priskiriama kintamajam pran. Na o treiajame sakinyje imamas kintamojo alge adresas ir jis priskiriamas kintamajam vyt. Kintamasis, kuris gali siminti kito kintamojo adres, yra vadinamas rodykle (pointer). Rodykls yra labai galinga C++ kalbos priemon, ir programuojant jos

78

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

daug kur naudojamos. Kaip itokie kintamieji paskelbiami ir naudojami, suinosime truput vliau.

10.2. Duomens nurodytu adresu operatorius ( * )


Naudodami rodykles mes galime tiesiogiai kreiptis duomenis, kurie atmintyje laikomi jose nurodytais adresais. Tam prie rodykls vard turi bti raoma vaigdut (*), kuri atlieka duomens mimo/siminimo nurodytu adresu operatoriaus vaidmen. Todl, pratsdami aukiau turt programos fragment sakiniu beta = *vyt; gausime tok rezultat: kintamasis beta gis reikm 25, nors vyt reikm yra 2476. Taip yra todl, kad atmintyje adresu 2476 yra uraytas skaiius 25. sidmkime skirtum: uraas vyt atitinka reikm 2476 (tai adresas), o uraas *vyt atitinka 25 (tai reikm, urayta nurodytu adresu). Todl beta = vyt; beta = *vyt; // beta pasidaro lygi vyt ( 2476 )

// beta igyja duomens reikm ( 25 )

Atkreipkime dmes adreso operatoriaus (&) ir duomens nurodytu adresu operatoriaus (*) skirtum: jie yra vienas kit papildantys ir kartu vienas kitam prieingi. Imkime tok atvej: a = 25; b = a; c = *&a; ia kintamieji a, b ir c gyja toki pai reikm. Uraas *&a reikia, kad operatoriumi & pirmiausiai gaunamas kintamojo a adresas, o po to operatoriumi * paimama reikm, urayta tuo adresu. Taigi, uraas *&a duoda t pat kaip ir a. Imkime dar vien pavyzd. Anksiau turjome tokius du priskyrimo sakinius: alge = 25; vyt = &alge; kur tarme, kad kintamojo alge adresas atmintyje yra 2476. vykdius juos, visos emiau parodytos palyginimo iraikos duos rezultat true. alge == 25 &alge == 2476 vyt == 2476 *vyt == 25

79

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

10.3. Rodykls tipo kintamj paskelbimas


Kadangi rodykls galina tiesiogiai kreiptis duomenis jose nurodytais adresais, paskelbiant jas btina nurodyti, kokio tipo duomenys bus laikomi tais adresais. Rodykli paskelbimo bendrasis pavidalas yra: tipas *vardas; ia tipas nurodo duomen tip, kurie bus saugomi rodykle nurodomu adresu, o ne paios rodykls tip. Pvz.: int *skaicius; char *simbolis; double *didelissk; Tai trij rodykli apraai. Kiekvien i j ketinama naudoti skirtingo tipo duomenims nurodyti, bet visos jos yra rodykls ir kiekviena i j atmintyje uims tok pat bait kiek (jis priklauso nuo skaiiavimo platformos, naudojamos programai vykdyti; daniausiai 4 baitai). Taiau patiems duomenims, kuri adresus nurodys ios rodykls, atmintyje reiks skirtingo dydio srii: int tipo duomuo uims 4 baitus, char 1 bait, double 8 baitus. Todl ir sakoma, kad rodykls yra skirtingo tipo. Pastebkime, kad vaigduts simbolis (*) aprae rodo tik tai, kad paskelbtas vardas yra rodykl. Nepainiokime jo su ankstesniame skyriuje nagrintu duomens nurodytu adresu operatoriumi, kuris taip pat ymimas vaigdute (*). Panagrinkime toki program: // pirmoji programa su rodyklmis #include <iostream> using namespace std; int main () { int sk1, sk2; int *rod; rod = &sk1; *rod = 10; rod = &sk2; *rod = 20; cout << "Pirmas skaicius " << sk1 << endl; cout << "Antras skaicius " << sk2 << endl; return 0; }

Pirmas skaicius 10 Antras skaicius 20

Nors tiesiogiai n vinam i kintamj sk1 ir sk2 reikms nesuteikme, abu jie reikmes gijo netiesiogiai, naudojant rodykl rod.
80

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Imkime sudtingesn pavyzd: // programa su daugiau rodykli #include <iostream> using namespace std; int main () { int sk1 = 5, sk2 = 15; int *p1, *p2; p1 = &sk1; // p1 = sk1 adresas p2 = &sk2; // p2 = sk2 adresas *p1 = 10; // 10 raso adresu p1 *p2 = *p1; // ima reikm adresu p1 ir raso adresu p2 p1 = p2; // kopijuoja rodykls reikm *p1 = 20; // 20 rao adresu p1 cout << "Pirmas skaicius " << sk1 << endl; cout << "Antras skaicius " << sk2 << endl; return 0; } Atkreipkime dmes i eilut: int *p1, *p2; Joje yra paskelbtos dvi rodykls. Jei raytume int *p1, p2; p1 bt rodykl, o p2 int tipo kintamasis. Skelbiant rodykles, prie kiekvien btina rayti vaigdut (*).

Pirmas skaicius 10 Antras skaicius 20

10.4. Rodykls ir masyvai


Masyvai turi glaud ry su rodyklmis. Masyvo vardas faktikai atitinka pirmo jo elemento adres ir jis yra traktuojamas kaip rodykl. Tarkime, turime tokius apraus: int skaiciai [20]; int *p; Todl priskyrimo sakinys p = skaiciai; yra teisingas. Taiau prieingas priskyrimas skaiciai = p; // konstantai negalima priskirti kintamojo reikms

yra neleistinas, nes masyvo vardas traktuojamas kaip rodykls konstanta.


81

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Toliau pateikiamame programos pavyzdyje visos iraikos, kuriose naudojamos rodykls, yra teisingos: // dar apie rodykles #include <iostream> using namespace std; int main () { int skaiciai [5]; int *p; p = skaiciai; *p = 10; p++; *p = 20; p = &skaiciai [2]; *p = 30; p = skaiciai + 3; *p = 40; p = skaiciai; *(p+4) = 50; for ( int n=0; n<5; n++ ) cout << skaiciai [n] << ", "; return 0; } Priskyrimo sakinyje p = skaiciai; uraas skaiciai atitinka &skaiciai [0], t. y. masyvo vardas reikia pirmojo elemento adres. Sakinio p++; rezultatas yra kito elemento adresas. Kadangi rodykl p yra int tipo, tai adreso skaitin reikm padidinama 4, nes int tipo kintamieji atmintyje uima 4 baitus. Iraikomis skaiciai+3 ir p+4 adresai padidinami tiek, kad gautume reikiamo masyvo elemento adres. Prisiminkime, kad masyvo elementas nurodomas po vardo staiakampiuose skliaustuose [] raant indeks. Todl iuos skliaustus galima traktuoti kaip reikms mimo/siminimo nurodytu adresu operatori, kuris, kaip inome, ymimas vaigdute (*). Pvz., iraikos a [5] = 0; *(a+5) = 0; yra ekvivalentikos, jei a yra rodykl arba masyvas.

10, 20, 30, 40, 50,

10.5. Rodykli inicializacija


Skelbiant rodykles yra galimyb aikiai nurodyti kintamj, kurio adres ji turt siminti vis pirma. Pvz., int skaic; int *tom = &skaic; Ekvivalentik rezultat gautume ura taip:
82

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int skaic; int *tom; tom = &skaic; Masyv atveju inicializuoti rodykl galima priskiriant konstant. char *vera = "Labas"; ia vis pirma rezervuojama atminties sritis konstantai Labas saugoti, o po to jos pirmo simbolio adresas priskiriamas rodyklei vera. Rodykl vera nurodo simboli sekos (eiluts) pradi ir todl traktuojama kaip masyvas (prisiminkime, kad masyvas traktuojamas kaip rodykls konstanta). Todl turimos eiluts penkt element galima kreiptis tokiais bdais: *(vera+4) vera [4] Abiem atvejais gausime reikm s (penktoji eiluts Labas raid).

10.6. Rodykli aritmetika


Aritmetins operacijos su rodyklmis atliekamos iek tiek kitaip, nei su prastais sveikaisiais skaiiais. Su jomis leistini tik sudties ir atimties veiksmai. Taiau ir jie atliekami kitaip, priklausomai nuo duomens tipo, kuriam rodykl yra skirta, uimam bait kiekio. Nagrindami pagrindinius duomen tipus matme (ir. 2.2 skyri), kad vieni uima daugiau, kiti maiau bait atmintyje. Pvz., char tipo duomuo atmintyje uima 1 bait, short int 2 baitus, long int 4 baitus. Tarkime, turime tris rodykles char *simb; short *trump; long *ilg; kurios yra gij tokias atminties adres reikmes atitinkamai: 1000, 2000 ir 3000. Taigi, jei raysime simb++; trump++; ilg++; tai simb reikm pasidarys lygi 1001, trump 2002, o ilg 3004. Prieastis yra ta, kad didindami rodykls reikm vienetu mes siekiame, kad ji gyt adreso reikm kito i eils einanio tokio paties tipo elemento. T pat gautume, jei raytume
83

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

simb = simb + 1; trump = trump + 1; ilg = ilg + 1; Visi ie samprotavimai tinka ir atimties operacijos atveju. Reikms didinimo (++) ir mainimo (--) operatori prioritetas yra emesnis u duomens nurodytu adresu mimio/siminimo operatori (*). Taiau abu jie turi specifini ypatybi, kai raomi po kintamojo vardo (juk galime rayti a++ ir ++a). Taigi, uraas *p++ yra ekvivalentikas uraui *(p++) Tai reikia, kad pirma pasinaudojama esama rodykls reikme ir tik po to jos reikm yra didinama. Atkreipkime dmes tok ura: (*p)++ iuo atveju yra imamas duomuo nurodytu adresu, jis panaudojamas ir po to jo reikm didinama vienetu. Rodykls reikm lieka nepakitusi. Imkime dar vien pavyzd. Uraai *p++ = *q++; ir *p = *q; ++p; ++q; yra ekvivalentiki. Tokiais atvejais rekomenduojama naudoti skliaustus, kad ivengtume klaid.

10.7. Rodykli rodykls


C++ kalboje galima naudoti rodykles, kuriose bt saugomi adresai kit rodykli, skirt konkretiems duomenims. Apraant tokias rodykles tereikia pridti papildom vaigdut (*). Pvz.:

84

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

char a, *b, **c; a = 'z'; b = &a; c = &b;

ia sakiniu b = &a; suinojome, kokiu adresu atmintyje patalpintas char tipo kintamasis a, o sakiniu c = &b; gavome atminties adres, kur laikoma rodykl b.

10.8. void rodykls


C++ kalboje void tipo rodykls gali siminti vairaus tipo duomen adresus. Taiau j naudojimas yra smarkiai apribotas. duomenis, kuri adres nurodo tokios rodykls, negali bti kreipiamasi tiesiogiai, t.y. naudojant duomen nurodytu adresu mimo/siminimo operatori (*). Tai yra logika, nes iuo atveju mes neinome, kiek bait uima duomuo pradedant nurodytu adresu. Todl void tipo rodykl prie kreipiantis konkretaus tipo duomenis visada turi bti pakeista konkretaus tipo rodykl. Tai daroma tip suderinimo bdu. Vienas i void tipo rodykli panaudojim yra funkcijos parametro, kuris tikt vairaus tipo duomenims, nurodymas. Panagrinkime tok programos pavyzd:
// void tipo rodykls naudojimo pavyzdys #include <iostream> using namespace std; void didink (void *duomuo, int dydis) { switch (dydis) { case sizeof(char) : (*((char*)duomuo))++; break; case sizeof(int) : (*((int*)duomuo))++; break; } } int main () { char a = 'x'; int b = 1602; didink (&a, sizeof(a) ); didink (&b, sizeof(b) ); cout << a << ", " << b << endl; return 0; }

y, 1603

ia standartine sizeof() funkcija gaunamas jos argumento uimamos atminties srities dydis baitais. Pagrindinio tipo duomenims ie dydiai yra konstantos. Pvz., sizeof(char) reikm yra 1, nes char tipo duomuo atmintyje uima 1 bait. Funkcijos didink() parametras duomuo, kuris yra void tipo rodykl, prie naudojim iraikomis (char*)duomuo ir (int*)duomuo pakeiiamas reikiamo tipo rodykl.
85

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

10.9. null rodykl


null rodykl yra tokia, kurios reikm yra lygi 0. Sakoma, kad tokia rodykl dar nra gijusi reikms. Tai jokio kintamojo adresas. Pvz.:
int *p; int a; if (p = 0) p = &a; p = 0; // paskelbus, p bna null rodykl // p igijo reikm // p vl tapo null rodykle

10.10. Funkcij rodykls


C++ kalboje rodykl gali siminti ir funkcijos adres. Tipikas tokios rodykls panaudojimo atvejis yra funkcijos vardo, kaip argumento, perdavimas kreipiantis kit funkcij. Funkcijos rodykls skelbimo bendrasis pavidalas yra toks: tipas (*vardas) (parametro1_tipas, parametro2_tipas, ); Matome, kad funkcijos rodykl skelbiama kaip funkcijos prototipas (antrat), iskyrus tai, kad funkcijos vardas dar suskliaudiamas ir prie j yra vaigdut (*): // funkcij rodykls naudojimo pavyzdys #include <iostream> using namespace std; int sudek (int a, int b) { return (a+b); } int atimk (int a, int b) { return (a-b); } int (*minus) (int, int) = atimk; int veiksmas ( int x, int y, int (*funkc)(int,int) ) { int g; g = (*funkc)(x,y); return (g); } int main () { int m,n; m = veiksmas (7, 5, sudek); n = veiksmas (20, m, minus); cout << n; return 0; }

// rezultatas - 12 // rezultatas - 8

86

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

iame pavyzdyje minus yra globalioji du int tipo parametrus turinios funkcijos rodykl. Jai ia i karto suteikiama pradin reikm (ji inicializuojama), kuri lygi funkcijos atimk adresui. int (*minus) (int,int) = atimk; Pastebkime, kad funkcij vardai yra traktuojami kaip rodykls. Prisiminkime, kad panaiai yra ir su masyv vardais.

87

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

11. Dinamin atmintis


Lig iol visoms ms paraytoms programoms vykdyti skiriamos atminties dydis ymia dalimi priklaus nuo to, kiek jos reikjo paskelbtiems kintamiesiems. Tas atminties dydis bdavo apibrtas programos tekste (source code) dar prie jos vykdym. Bet k daryti, jei kintamajam reikalingos atminties dyd manoma apibrti tik programos vykdymo eigoje? Pvz., kai vis pirma reikia vesti kakokius duomenis, kad galtume apibrti reikiamos atminties srities dyd. Atsakymas klausim yra toks: naudokime dinamin atmint. Dinamine atmintimi vadinama ta operatyviosios atminties dalis, kuri programos vykdymo metu yra laisva ir prireikus gali bti paskiriama kintamiesiems ir ilaisvinama, kai jos nebereikia. C++ kalboje tam yra operatoriai new ir delete.

11.1. Operatoriai new ir new[ ]


Dinamin atminties sritis paskiriama operatoriumi new, kuris raomas prie kintamojo tip nurodant bazin od. new grina naujai paskirtos atminties srities adres, kuris priskiriamas rodyklei. Bendrasis sakini new pavidalas: rodykl = new tipas; arba rodykl = new tipas [kiekis]; Pirmasis naudojamas paskirti atminties srit pavieniam nurodyto tipo elementui, o antrasis nurodyto tipo ir nurodyto element kiekio masyvui. Pvz.: int *bob; bob = new int [5]; iuo atveju sistema dinamikai (programos eigoje) paskirs atminties srit penkiems int tipo elementams ir jos adres simins rodyklje bob. pirmj element dinamikai paskirtoje atmintyje galima kreiptis bob[0] arba *bob, antrj bob[1] arba *(bob+1) ir t.t. Dinaminis atminties skyrimo bdas element masyvui turi t privalum prie prast masyv skelbim, kad ia element kiekis gali bti nurodomas konstanta arba kintamuoju (skelbiant masyv, jo dydis nurodomas tik konstanta). Pvz.: int *bob; int a; cin >> a; bob = new int [a];

88

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Reikiamas dinamins atminties sritis sistema skiria laisvoje atminties dalyje (j dar vadina heap atmintim). Taiau kompiuterio atmintis yra riboto dydio, ir ji gali bti visa uimta. Todl svarbu turti tikrinimo priemon, ar praomo dydio atminties sritis i tikro buvo paskirta. C++ kalboje yra du standartiniai dinamins atminties skmingo paskyrimo kontrols bdai. Vienas i j yra neskming arba ypating situacij (exceptions) apdorojimas. Negaldama paskirti dinamins atminties srities, sistema suformuoja bad_alloc tipo situacij, susidarius kuriai programuotojas gali numatyti savo veiksmus. Ypating situacij apdorojimo ioje mokymo priemonje mes plaiau nenagrinsime. Taiau inokime, kad programuotojui nenumaius savo veiksm ypatingos situacijos atveju, programa nutraukiama. Programos nutraukimas yra ypatingos situacijos, skiriant dinamin atmint new operatoriumi, apdorojimo numatytasis (default) bdas. Jis naudojamas tokiuose sakiniuose, kaip, pvz., bob = new int [5]; Kitas dinamins atminties paskyrimo kontrols bdas yra inomas vardu nothrow. Neskms atveju new operatorius grina adres lyg 0 (null) ir programa tsiama. is kontrols bdas pradeda veikti, jei po new raomas parametras nothrow. Pvz: bob = new (nothrow) int [5]; Ar iuo sakiniu dinamin atmintis sritis nurodytam element kiekiui i tikro buvo paskirta, galima sitikinti patikrinus rodykls bob reikm: int *bob; bob = new (nothrow) int [5]; if (bob == 0) { // atminties nepaskyr. Reakcija tai. };

11.2. Operatoriai delete ir delete[ ]


Dinamin atminties sritis paprastai bna reikalinga tik tam tikrais programos vykdymo momentais. Kai tik jos nebereikia, turta atminties sritis gali bti ilaisvinta ir panaudota kitiems reikalams. iam tikslui yra operatorius delete, kurio pavidalai: delete rodykl; delete [] rodykl;

89

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Pirmoji iraika naudojama pavieniam elementui, o antroji element masyvui paskirtai dinaminei atminiai ilaisvinti. Iraikose nurodoma rodykl anksiau turi bti gijusi reikm new operatoriumi arba ji gali turti null reikm (esnt null rodyklei, operatorius delete nieko nedaro). Pavyzdys: // dinamins atminties skyrimas ir ilaisvinimas #include <iostream> using namespace std; int main () { int k,n; int * p; cout << "Kiek skaiciu vesite? "; cin >> k; p = new (nothrow) int [k]; // paskiria atmint if (p == 0) { cout << "Klaida: atmintis nepaskirta"; exit(0); } else { for (n=0; n<k; n++) { cout << "Iveskite skaiciu: "; cin >> p [n]; } cout << "Jus ivedete: "; for (n=0; n<k; n++) cout << p [n] << ", "; delete [] p; // ilaisvina atmint } return 0; } Atkreipkime dmes sakin p = new (nothrow) int [k]; Jame masyvo dydis nurodytas kintamuoju k, kuriam reikm vedama programos vykdymo metu. vedus didel kintamojo k reikm, gali trkti dinamins atminties ir ji nebus paskirta. Tai kontroliuojama nothrow metodu.

Kiek skaiciu vesite? 4

Iveskite skaiciu: 75 Iveskite skaiciu: 436 Iveskite skaiciu: 1067 Iveskite skaiciu: 8 Jus ivedete: 75, 436, 1067, 8,

90

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

11.3. Dinamin atmintis ANSI-C++ standarte


C++ kalboje operatoriai new ir delete yra atsirad neseniai. J nra C kalboje. Taiau C kalboje darbui su dinamine atmintimi yra funkcijos malloc, calloc, realloc ir free. Pastarasios yra laikomos <cstdlib> bibliotekoje. Kadangi C++ yra C kalbos viraibis, mintos funkcijos yra ir C++ kalboje. Int *x; x = (int *) malloc (n * sizeof (int) ); x = new (nothrow) int [n]; Dinamins atminties srii skyrimas mintomis funkcijomis kakiek skiriasi nuo atminties skyrimo new operatoriumi. Todl programuojant reikia naudoti vien kur nors funkcij ar operatori rinkin, bet ne j kombinacij. inotina, kad C ir C++ kalbose kai kuri standartini bibliotek pavadinimai skiriasi. Pvz., C++ kalbos bibliotek <cstdlib> atitinka C kalbos biblioteka <stdlib.h>. arba

91

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

12. Duomen struktros


Mes jau nagrinjome, kaip C++ kalboje naudojami duomen rinkiniai (pvz., masyvai), kuri visi elementai yra tokio paties tipo. Taiau labai danai yra reikalingi rinkiniai, kuriuose bt vairaus tipo duomenys.

12.1. Duomen struktros


Duomen struktra tai vairaus tipo duomen grup, turinti vien vard. C++ kalboje duomen struktros skelbimo sintaks yra tokia: struct struktros_vardas { tipas1 elemento_vardas1; tipas2 elemento_vardas2; tipas3 elemento_vardas3; ... } objekt_vardai; ia struktros_vardas tai struktros tipo vardas, objekt_vardai tai objekt vard rinkinys, kuriuos norime paskelbti kaip nurodyto tipo duomen struktras. Riestiniuose skliaustuose ivardinami duomen elementai, kuri kiekvienas turi savo tip ir vard. Vis pirma reikt atkreipti dmes tai, kad skelbiant struktr sukuriamas naujas duomen tipas, kurio vardas bus struktros_vardas. Toliau programoje j galima bus naudoti kaip ir bet kur kit tip. Pvz.: struct produktas { int svoris; float kaina; }; produktas suris; produktas desra, zuvis; ia mes pirma paskelbme i dviej element svoris ir kaina susidedanios struktros tip, kur pavadinome produktas. Po to naudodami tipo vard paskelbme tris objektus: suris, desra ir zuvis. Po io paskelbimo produktas tapo nauju galiojaniu duomen tipo vardu, kaip ir mums inomi pagrindini tip vardai int, char, float ar kt. Taip mes gijome galimyb skelbti io naujo sudtinio tipo objektus (kintamuosius) kaip suris, desra ir kt. Struktros skelbimo pabaigoje po udaranio riestinio skliausto i karto galima nurodyti objektus. Todl ms turt pavyzd galima rayti ir taip:

92

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

struct produktas { int svoris; float kaina; } suris, desra, zuvis; Svarbu yra skirti, kur yra struktros tipo vardas ir kur yra tokios struktros objektas (kintamasis). Vieno struktros tipo objekt galime paskelbti daug. Kadangi mes paskelbme tris apibrtos struktros tipo objektus suris, mesa ir zuvis, tai galime tiesiogiai dirbti su kiekvieno i j elementais. Tam tarp objekto vardo ir elemento turi bti dedamas takas. Pvz., mes galime dirbti su bet kuriuo elementu, nes jie yra standartinio tipo kintamieji: suris.svoris suris.kaina desra.svoris desra.kaina zuvis.svoris zuvis.kaina

Kiekvieno i duomen tipas atitinka struktros elementui nurodyt tip. suris.svoris, desra.svoris ir zuvis.svoris yra int tipo, o suris.kaina, desra.kaina ir zuvis.kaina yra float tipo. Inagrinkime pavyzd, kuriame struktros tipas naudojamas lygiai taip pat, kaip ir pagrindiniai duomen tipai. // pavyzdys su struktromis #include <iostream> #include <string> #include <sstream> using namespace std; struct knyg_t { string pavadinimas; int metai; } mano, tavo; void spausdink (knyg_t knyga); // funkcijos prototipas

int main () { string eilut; mano.pavadinimas = "Odisejo keliones"; mano.metai = 1968; cout << "Iveskite pavadinima: "; getline (cin, tavo.pavadinimas); cout << "Iveskite metus: "; getline (cin, eilut);

Iveskite pavadinima: Pelene Iveskite metus: 1979


93

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

stringstream (eilut) >> tavo.metai; cout << "Mano megiama knyga yra:\n "; spausdink (mano); cout << "Jusu megiama knyga yra:\n "; spausdink (tavo); return 0; } void spausdink (knyg_t knyga) { cout << knyga.pavadinimas; cout << " (" << knyga.metai << ")\n"; }

Mano megiama knyga yra: Odisejo keliones (1968) Jusu megiama knyga yra: Pelene (1979)

is pavyzdys rodo, kad objekt elementai gali bti naudojami kaip paprasti kintamieji. Pvz., tavo.metai yra int tipo kintamasis, o mano.pavadinimas yra string tipo kintamasis. Objektai mano ir tavo gali bti traktuojami kaip knyg_t tipo kintamieji. Pvz., mes juos, kaip ir prastus kintamuosius, naudojome kreipdamiesi funkcij spausdink. Taiau viena i svarbiausi duomen struktr savybi yra ta, kad mes galime kreiptis kiekvien jos element individualiai arba kreiptis vis struktr tik vienu vardu. Duomen struktros ypatingos tuo, kad jos gali bti naudojamos duomen bazms pavaizduoti, ypa jei tursime galvoje galimyb sudaryti duomen struktr masyvus: // struktr masyvas #include <iostream> #include <string> #include <sstream> using namespace std; #define N_KNYGU 3 struct knyg_t { string pavadinimas; int metai; } knygos [N_KNYGU]; void spausdink (knyg_t kng); // f-jos prototipas int main () { string eilut; int n;

94

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

for (n=0; n<N_KNYGU; n++) { cout << "Iveskite pavadinima: "; getline (cin,knygos [n].pavadinimas); cout << "Iveskite metus: "; getline (cin,eilut); stringstream(eilut) >> knygos [n].metai; } cout << "\n Jus ivedete siu knygu duomenis:" << endl; for (n=0; n<N_KNYGU; n++) spausdink (knygos [n]); return 0; } void spausdink (knyg_t kng) { cout << kng.pavadinimas; cout << " (" << kng.metai << ")\n"; }

Iveskite pavadinima: Kopos Iveskite metus: 1982 Iveskite pavadinima: Matrica Iveskite metus: 1999 Iveskite pavadinima: Taksi vairuotojas Iveskite metus: 1976 Jus ivedete siu knygu duomenis: Kopos (1982) Matrica (1999) Taksi vairuotojas (1976)

12.2. Struktr rodykls


Struktr, kaip ir kitokio tipo duomen adresui atmintyje nurodyti gali bti naudojamos rodykls:
struct knyg_t { string pavadinimas; int metai; }; knyg_t aknyga; knyg_t *pkn;

ia aknyga yra knyg_t tipo objektas, o pkn yra knyg_t tipo struktros rodykl. Todl sakinys pkn = &aknyga; yra teisingas. Rodyklei pkn bus priskirtas objekto aknyga adresas atmintyje. Panagrinkime programos su struktr rodyklmis pavyzd, kuris pads susipainti su nauju operatoriumi, t.y. rodykls operatoriumi (->): // struktr rodykls #include <iostream> #include <string> #include <sstream> using namespace std;
95

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

struct knyg_t { string pavadinimas; int metai; }; int main () { string eilut; knyg_t aknyga; knyg_t *pkn; pkn = &aknyga; cout << "Iveskite pavadinima: "; getline (cin, pkn->pavadinimas); cout << "Iveskite metus: "; getline (cin, eilut); stringstream(eilut) >> pkn->metai; cout << "\nJus ivedete:\n"; cout << pkn->pavadinimas; cout << " (" << pkn->metai << ")\n"; return 0; } iame pavyzdyje naudojamas rodykls operatorius (->) yra reikms nurodytu adresu mimo/siminimo operatorius, kuris iimtinai naudojamas tik struktr elementams. Rodykls operatoriumi kreipiamasi element to objekto, kurio adres turi siminusi struktros rodykl. Nepainiokime savok rodykls operatorius (->) ir rodykl (pointer). Pavyzdyje mes naudojome iraik pkn->pavadinimas kuri yra ekvivalentika tokiai iraikai: (*pkn).pavadinimas ios abi iraikos yra teisingos ir jomis kreipiamasi element pavadinimas tos struktros, kurios adres yra siminusi rodykl pkn. Btina aikiai skirti mintas iraikas nuo i dviej ekvivalentik iraik: *pkn.pavadinimas *(pkn.pavadinimas) Pastarosios reikalauja, kad pavadinimas bt rodykl (o ne string, kaip esame paskelb), ir todl bt kreipiamasi duomen, kurio adres ji nurodyt. Iveskite pavadinima: Altoriu sesely Iveskite metus: 1978

Jus ivedete: Altoriu sesely (1978)

96

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

emiau lentelje reziumuojamos rodykli ir struktros element galimos kombinacijos: Iraika a.b a->b *a.b k kreipiamasi objekto a element b objekto, kurio adresas yra rodyklje a, element b duomen, kurio adresas yra objekto a elemente b (elementas b turt bti rodykl) (*a).b *(a.b) Ekvivalentas

12.3. Struktros struktrose


Viena struktra gali bti kitos struktros elementu. Pvz.: struct knyg_t { string pavadinimas; int metai; }; struct draugai_t { string vardas; string epastas; knyg_t mkn; } kostas, morta; draugai_t *pdraug = &kostas; Turint taip paskelbtas struktras, galima bet kuri i i iraik: kostas.vardas morta.mkn.pavadinimas kostas.mkn.metai pdraug->mkn.metai ia paskutins dvi iraikos nurodo t pat element.

12.4. Dinamins duomen struktros: sraai, mediai ir kita


Sraas tai atitinkamai sudlioti duomenys. Paprasiausias pavyzdys yra masyvas, kuriame nuosekliai vienas po kito (vientisoje atminties srityje) yra talpinami jo elementai. Masyvo svyb yra ta, kad apraant j btina nurodyti element kiek (indeks kitimo ribos nurodomos konstantomis). Tuo tarpu sraai neturi fiksuoto ilgio, j elementai gali bti imtyti atmintyje (laikomi ne vientisoje srityje). Todl jiems organizuoti reikia lankstesnio bdo. Lankstum duoda dinaminiai kintamieji ir

97

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

rodykls, galinantys kurti vairias dinamines duomen struktras: tiesinius sraus, iedinius sraus, eiles, stekus, medius, piramides. Tiesinis sraas. Paprasiausio vienos krypties tiesinio srao elemente turi bti du laukai: duomenys (elemento informacija) ir rodykl (kur atmintyje laikomas kitas i eils srao elementas). Srao ilgis gali bti keiiamas terpiant bet kurioje srao vietoje nauj element arba paalinant bet kur esant. Nupiekime vienos krypties tiesin sra grafikai.
Pirmas elementas Duomenys Rodykl elementas Duomenys Rodykl elementas Duomenys Rodykl Paskutinis elementas Duomenys Rodykl null

inant kur yra pirmas srao elementas (ufiksavus atitinkamos rodykls reikm), galima susirasti bet kur srao element. Paskutiniame elemente esaniai rodyklei priskiriama null reikm, kaip poymis, kad sraas baigsi. Pavyzdiui, sudarykime C++ program gyventoj, kuri pavard prasideda raide A, telefon numeri sraui kaupti: // vienos krypties duomen srao sudarymas
#include <iostream> #include <string> using namespace std; struct telsar { string pavarde, adresas, tnr; telsar *kitorod; }; main() { telsar *p1, *x, *y; p1 = 0; do { x = new telsar; getline (cin, (*x).pavarde); // galima rayti ir x->pavarde getline (cin, (*x).adresas); getline (cin, (*x).tnr); (*x).kitorod = 0; if (p1 == 0) p1 = x; // ufiksuojam pirmo elemento adres p1 else (*y).kitorod = x; y = x; } while ( (*x).pavarde [0] == A );

98

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

if (y == p1) // jei nra n vieno elemento su A pavarde { cout << Nera ne vieno elemento << endl; exit(1); } x = p1; // toliau ivedame ekran srao elementus do { cout << (*x).pavarde << \t << (*x).adresas << \t << (*x).tnr << endl; x = (*x).kitorod; } while ( x != 0); return 0; }

Sudarykime kit program, kuri i sudaryto srao alina element su nurodyta pavarde. Pavard veskime klaviatra. // vienos krypties duomen srao elemento alinimas #include <iostream> #include <string> using namespace std; struct telsar { string pavarde, adresas, tnr; telsar *kitorod; }; main() { telsar *p1, *x, *y; p1 = 0; string salinti; // toliau vedam sra kaip ir prie buvusioje programoje do { x = new telsar; getline (cin, (*x).pavarde); getline (cin, (*x).adresas); getline (cin, (*x).tnr); (*x).kitorod = 0; if (p1 == 0) p1 = x; // p1 ufiksuojam viso srao pradios adres else (*y).kitorod = x; y = x; } while ( (*x).pavarde [0] == A ); if (y == p1) p1=0; // jei nra n vieno elemento su A pavarde

99

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// toliau i sukaupto srao aliname nurodyt element x = p1; y = 0; if (x == 0) { cout << Sarase nera ne vieno elemento << endl; system (PAUSE); exit(1); } cout << Iveskite pavarde, kurio duomenis salinsite: ; getline (cin, salinti); // vedame, ka reikes alinti do // iekom alinamojo elemento adreso { if ( (*x).pavarde != salinti ) { y = x; x = (*x).kitorod; } } while ( (x != 0) && ( (*x).pavarde != salinti) ); if ( (*x).pavarde == salinti ) // jei alinam: { if ( (*x).kitorod == 0 ) (*y).kitorod = 0; // paskutin else if (x == p1) p1 = (*x).kitorod; // pirm else (*y).kitorod = (*x).kitorod; // vidurin } else cout << Tokios pavardes sarase nera << endl; // ivedame ekran sra be jau paalinto elemento x = p1; do { cout << (*x).pavarde << \t << (*x).adresas << \t << (*x).tnr << endl; x = (*x).kitorod; } while ( x!=0); return 0; } Tiesinio srao elemente pavartojus dvi rodykles, kuri viena bt skirta nurodyti kitam i eils einaniam srao elementui, o antra - prie einaniam srao elementui, turtume dviej krypi tiesin sra. Pavaizduokime j grafikai.
Pirmas elementas Duomenys Rodykl-p null Rodykl-a elementas Duomenys Rodykl-p Rodykl-a elementas Duomenys Rodykl-p Rodykl-a Paskutinis elementas Duomenys Rodykl-p Rodykl-a null

100

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Trumpai apibdinkime kitokias dinamines duomen struktras: iedinis sraas yra panaus tiesin sra, taiau jame yra papildomas ryys (nuoroda) tarp paskutinio ir pirmo element; eil vienos krypties tiesinio srao variantas, kuriam leistini tik du veiksmai: naujo elemento pridjimas tik srao gale ir elemento alinimas tik nuo srao pradios; stekas vienos krypties tiesinio srao variantas, kuriame naujas elementas gali bti pridtas tik gale, o paalintas taip pat tik nuo galo. is elementas vadinamas steko virne; medis - tai pasirinktos konfigracijos hierarchin duomen struktra. Medio elementai vadinami virnmis (mazgais); piramid (surikiuotas medis) tai medis, kurio virni reikms visada nemaja arba nedidja pereinant kit lyg.

101

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

13. Kiti duomen tipai


13.1. Apibrtieji duomen tipai ( typedef )
C++ kalba leidia programuotojams apsibrti savus duomen tipus, remiantis esamais pagrindiniais ar sudtiniais tipais. Tai galima padaryti naudojant bazin od typedef: typedef esamas_tipas naujo_tipo_vardas; Pvz.: typedef typedef typedef typedef char SIMBOLIS; unsigned int ZODIS; char *pChar; char laukas [50];

ia mes apibrme keturis duomen tipus tokias vardais: SIMBOLIS, ZODIS, pChar ir laukas, kurie reikia char, unsigned int, char* ir char [50] tipus atitinkamai. Juos toliau galima naudoti skelbiant kintamuosius: SIMBOLIS raid, sp, *ptc1; ZODIS pavad; pChar ptc2; laukas vrd; iame pavyzdyje paskelbtas kintamasis ptc2 bus char tipo rodykl, o kintamasis vrd bus char tipo masyvas, turintis 50 element. typedf sakiniu nekuriami nauji tipai. Juo kuriami tik sinonimai esamiems tipams. Todl, pvz., ZODIS ir unsigned int faktikai nurodo tok pat duomen tip. typedef gali bti naudojamas duomen tipui pavadinti slaptaodiu, kas danai daroma programose. Jis taip pat gali bti naudingas, kai reikia suderinti duomen tipus skirtingose programos versijose arba kai vietoje pernelyg ilgo arba painaus tipo norime sukurti patogesn.

13.2. Bendrosios atminties sritys ( union )


union baziniu odiu nurodoma, kad ta pati atminties sritis gali bti naudojama keliems skirtingo tipo kintamiesiems. Tokios srities skelbimo sintaks yra panai duomen struktros (struct) skelbim, taiau savo esme jie yra visikai skirtingi dalykai:

102

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

union bendros_srities_vardas { tipas1 elemento_vardas1; tipas2 elemento_vardas2; tipas3 elemento_vardas3; ... } objekt_vardai; Visi union sakinyje paskelbti elementai atmintyje bus talpinami toje paioje srityje. Jos dydis yra lygus didiausiam bait kiekiui, kuris reikalingas kakuriam i vardint kintamj. Pvz.: union mantip { char c; int k; float f; } mt; Apibria tris elementus: mt.c mt.k mt.f

kurie yra skirting tip. Kadangi j reikms saugomos toje paioje atminties vietoje, tai keiiant vieno elemento reikm keisis ir kit element reikms. Pastebkime, kad mantip yra bendros atminties srities tipo vardas, o mt io tipo kintamojo vardas. Tokio tipo kintamj galime paskelbti ir daugiau, pvz.: mantip dsa, laukas; Vienas i union naudojimo pavyzdi: union svk { long k; struct { short virs; short apat; } s; char c [4]; } mix; ia paskelbti trys elementai mix.k, mix.s ir mix.c, kurie naudos t pai 4 bait dydio atminties srit. Vienu atveju juose laikysime long tipo kintamj, kitu du

103

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

short tipo kintamuosius, o treiu char element masyv. Schemikai tai galima bt pavaizduoti taip: mix mix.k mix.virs mix.c [0] mix.c [1] mix.apat mix.c [2] mix.c [3]

ia dert prisiminti tai, kad simenant sveikuosius skaiius j dvejetainio pavidalo jauniausios skiltys dedamos kairje esant bait, o vyriausios skiltys deinje esant. Todl, pvz., priskyrus mix.k = 97, taiau ivedant mix.c [0], ekrane matysime raid a (raids a kodo skaitin reikm yra lygi 97). Ir atvirkiai, priskyrus mix.c [0] = a, taiau ivedant mix.k, ekrane gausime 97.

13.3. Bevards bendrosios atminties sritys union


C++ kalboje yra galimyb skelbti bevardes union atmities sritis. Turint toki, jos elementus galima kreiptis tiesiog naudojant j vardus. Pvz., atkreipkime dmes i dviej duomen struktr skelbimus: Struktra su prastu union struct { char pavadinimas [50]; char autorius [50]; union { float litai; int eurai; } kaina; } knyga; Struktra su bevardiu union struct { char pavadinimas [50]; char autorius [50]; union { float litai; int eurai; }; } knyga;

Skirtumas tarp i dviej programos fragment yra tas, kad kairiajame yra nurodytas union srities vardas kaina, o deiniajame ne. Todl i srii elementus litai ir eurai kreipiamasi nevienodai. Kairje esanio programos fragmento atveju kreipiamasi knyga.kaina.litai knyga.kaina.eurai o deinje esanio fragmento atveju knyga.litai knyga.eurai

104

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Prisiminkime, kad union nra tas pat kaip struct. Elementai litai ir eurai uims fizikai t pai atminties srit. Todl kain galima bus nurodyti arba litais, arba eurais, bet ne abiem valiutomis i karto.

13.4. Ivardijimai ( enum )


Ivardijimai tai dar vienas duomen tipas. Jo aprao pavidalas: enum ivardijimo_vardas { reikm1, reikm2, reikm3, --} objekto_vardas; Pvz., mes galime paskelbti kintamj tip spalv pavadinimams saugoti: enum spalvos { juoda, melyna, zalia, cyan, raudona, purpurine }; Pastebkime, kad ia nenaudojami jokie pagrindiniai duomen tipai. Ivardijimo tipo kintamieji skelbiami prastu bdu: spalvos mikosp, roze, batosp; Reikms, kurias gali gyti tokie kintamieji yra pastovs dydiai, ivardinti tipo aprae tarp riestini skliaust. Pvz., naudojant ms paskelbt tip spalvos, galima rayti tokius sakinius:
spalvos roze; roze = melyna; if (roze == purpurine) roze = raudona;

Ivardintj reikmi tipas atitinka skaitinio tipo kintamuosius, todl ioms reikmms visada priskiriama ir skaitin reikm. Nesant papildom nurodym, pirmos reikms ekvivalentas yra 0, antros 1 ir t. t. Ms pavyzdyje ivardijimo tipe spalvos ivardintosios reikms gyja tokius skaitinius atitikmenis: juoda 0, melyna 1, zalia 2 ir t.t. Bet kuriai ivardintjai reikmei galima aikiai nurodyti j atitinkant sveikj skaii. Jei po ivardintosios reikms sveikasis skaiius nenurodomas, tai tokios ivardintosios reikms skaitinis atitikmuo yra vienetu didesnis nei prie buvusios ivardintosios reikms. Pvz.:
enum menesiai { sausis=1, vasaris, kovas, balandis, geguze, birzelis, liepa, rugpjutis, rugsejis, spalis, lapkritis, gruodis } m2007;

105

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

14. Klass ir objektai


Klas tai iplsta duomen struktra, kurioje laikomi ne tik duomenys, bet dar gali bti ir funkcijos. Objektai yra klasi atstovai. Kalbant kintamj terminais, klas atitinka tip, o objekt kintamasis. Klass skelbiamos naudojant bazin od class. J pavidalas: class klass_vardas { kreipties_atributas1: narys1; // kreipties = prieigos

kreipties_atributas2: narys2; ... } objekto_vardas; ia klass_vardas tai klass pavadinimas, o objekto_vardas tai ios klass objekt vard sraas (ioje vietoje jo gali ir nebti). Klass nariai tai kintamj ir funkcij apraai, prie kuriuos nurodomi kreipties atributai. Kreipties (prieigos) atributas nurodomas baziniu odiu private, public arba protected. Juo apibriama klass nario galiojimo sritis:
- private narius gali kreiptis tik kiti tos klass nariai arba j draugai (friend,

apie juos vliau); - protected narius gali kreiptis tik kiti tos klass nariai arba j draugai, o taip pat ta klase paremt ivestini klasi nariai; - public narius galima kreiptis i bet kurios vietos, kur yra objekto galiojimo sritis. Kai kreipties atributas nenurodomas, numatytasis yra private. Pvz.: class Cstaciakampis { int x, y; public: void nurodyk_krastines (int, int); int plotas (void); } sta; ia apibrme klas (kitaip tariant tip), kuri pavadinome Cstaciakampis, ir ios klass objekt (kitaip tariant kintamj) sta. ioje klasje yra keturi nariai: du int tipo kintamieji (x ir y) ir dvi public kreipties funkcijos (nurodyk_krastines ir plotas). ia nurodme tik funkcij prototipus (antrates), nors galima bt rayti ir vis funkcijos programos tekst. Kadangi kintamiesiems x ir y kreipties atributo nenurodme, tai jiems galioja numatytasis private.

106

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Cstaciakampis klass sta objekto narius programoje galima kreiptis kaip prastus kintamuosius ar funkcijas, inoma, prie j vard dar nurodant objekto vard. Tarp i vard dedamas takas. Pvz.: sta.nurodyk_krastines (3,4); mapl = sta.plotas(); Tiesiogiai kreiptis ms pavyzdio narius x ir y negalsime, nes jie yra private kreipties. Panagrinkime sudtingesn programos su Cstaciakampis klase pavyzd: // Programos su klase pavyzdys #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: void nurodyk_krastines (int,int); int plotas () { return (x*y); } }; void Cstaciakampis :: nurodyk_krastines (int a, int b) { x = a; y = b; } int main () { Cstaciakampis sta; sta.nurodyk_krastines (3,4); cout << "plotas: " << sta.plotas(); return 0; }

plotas: 12

ioje programoje nauja yra tai, kad joje pavartotas priklausymo klasei operatorius ( :: - du dvitakiai) funkcijos nurodyk_krastines aprae. Pastarasis operatorius naudojamas tada, kai klass nario apraas yra u klass rib, ir jis padeda atskirti klasms priklausanias funkcijas nuo prast globali funkcij. Pastbkime, kad ioje programoje klass Cstaciakampis viduje yra visas funkcijos plotas tekstas, nes jis labai paprastas, o funkcijos nurodyk_krastines - tik prototipas.

107

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Priklausymo klasei operatorius (::) nurodo, kuriai klasei aprayta funkcija priklauso. Todl tokioje funkcijoje galima naudoti tos klass private kreipties narius, kaip kad x ir y ms pavyzdyje. Jei klasje yra private kreipties nari, tai jiems reikms gali bti priskiriamos ir keiiamos tik tos klass funkcijomis. Tokiu bdu likusiose programos vietose tiesiogiai j reikmi keisti negalima. Tai padeda apsaugoti toki nari reikmes nuo nenumatyto pakeitimo. Didelis klasi privalumas yra tas, kad, kaip ir kitoki tip atveju, mes galime paskelbti kelet vienos klass objekt. Pvz., emiau pateikiamoje programoje klass Cstaciakampis objekt turime du: stc1 ir stc2: // viena klas, du objektai #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: void nurodyk_krastines (int,int); int plotas () {return (x*y);} }; void Cstaciakampis :: nurodyk_krastines (int a, int b) { x = a; y = b; } int main () { Cstaciakampis stc1, stc2; stc1.nurodyk_krastines (3,4); stc2.nurodyk_krastines (5,6); cout << "stc1 plotas: " << stc1.plotas() << endl; cout << "stc2 plotas: " << stc2.plotas() << endl; return 0; }

stc1 plotas: 12 stc2 plotas: 30

Pastebkime, kad kreipiniai stc1.plotas() ir stc2.plotas() duoda skirtingus rezultatus. Taip yra todl, kad kiekvienas Cstaciakampis klass objektas operuoja su jam paskirtais kintamaisiais x ir y bei funkcijomis nurodyk_krastines ir plotas. Tai yra pagrindin objektinio programavimo idja, kai duomenys ir funkcijos yra objekto nariai. Pastebkime, kad kreipiniuose stc1.plotas() ir stc2.plotas() jau nebereikjo argument. ios funkcijos atitinkamai naudojo sav objekt stc1 ir stc2 duomenis.
108

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

14.1. Konstruktoriai ir destruktoriai


Objekt sudtyje esanius kintamuosius reikia inicializuoti (priskirti jiems reikmes), kad nebt operuojama su neapibrtomis reikmmis. Pvz., kas bt atsitik, jei prie buvusiame ms pavyzdyje btume kreipsi funkcij plotas anksiau, negu funkcij nurodyk_krastines? Tikriausiai btume gav neapibrt rezultat, nes nariams x ir y dar nebuvo priskirtos reikms. Tokiems dalykams ivengti klasse gali bti speciali funkcija, kuri vadinama konstruktoriumi. toki funkcij kreipiamasi automatikai, duotos klass naujo objekto skelbimo metu. Konstruktoriaus vardas turi bti toks pat kaip ir klass vardas, ir jis kaip funkcija negrina jokios reikms. Prie j nenurodomas joks tipas, netgi void. Pakeiskime anksiau turt klas Cstaciakampis traukdami konstruktori: // klass konstruktoriaus pavyzdys #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: Cstaciakampis (int, int); int plotas () { return (x*y); } }; Cstaciakampis :: Cstaciakampis (int a, int b) { x = a; y = b; } int main () { Cstaciakampis stc1 (3,4); Cstaciakampis stc2 (5,6); cout << "stc1 plotas: " << stc1.plotas() << endl; cout << "stc2 plotas: " << stc2.plotas() << endl; return 0; }

stc1 plotas: 12 stc2 plotas: 30

Matome, kad io pavyzdio programa duoda tokius paius rezultatus kaip ir ankstesnioji. Taiau ia mes paalinome funkcij nurodyk_krastines ir vietoje jos traukme konstruktori, kuris atlieka panaius veiksmus: inicializuoja x ir y, priskirdamas objekt stc1 ir stc2 aprauose nurodytas reikmes.
109

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Atkreipkime dmes tai, kaip nurodytos reikms perduodamos konstruktoriui skelbiant objekt:
Cstaciakampis stc1 (3,4); Cstaciakampis stc2 (5,6);

konstruktori, kaip funkcij, atvirai kreiptis negalima. Jis savo vaidmen atlieka tik tuomet, kai skelbiamas naujas duotos klass objektas. Tikriausiai pastebjote, kad prie konstruktoriaus prototip klass aprae ir konstruktoriaus aprae void nevartojamas. Destruktorius atlieka prieing vaidmen nei konstruktorius. j kreipiamasi automatikai, kai norima paalinti nebereikaling objekt (pvz., baigus darb kuriai nors programos funkcijai, naudojaniai lokaliuosius objektus). Destruktoriaus vardas turi bti toks pat, kaip ir klass vardas, taiau prie j dar turi bti bangels simbolis (~). Destruktoriai ypa naudingi yra tuomet, kai objektai naudoja dinamin atmint. Kai paskelbtas objektas tampa nebereikalingas, objekto uimama atmitis ilaisvinama. Pvz.:
// konstruktoriaus ir destruktoriaus pavyzdys #include <iostream> using namespace std; class Cstaciakampis { int *x, *y; public: Cstaciakampis (int,int); ~Cstaciakampis (); int plotas () { return (*x * *y); } }; Cstaciakampis :: Cstaciakampis (int a, int b) //konstruktorius { x = new int; y = new int; *x = a; *y = b; } Cstaciakampis :: ~Cstaciakampis () { delete x; delete y; } // destruktorius

int main () { Cstaciakampis stc1 (3,4), stc2 (5,6); cout << "stc1 plotas: " << stc1.plotas() << endl; cout << "stc2 plotas: " << stc2.plotas() << endl; return 0; }

stc1 plotas: 12 stc2 plotas: 30

110

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

14.2. Klass su keliais konstruktoriais


Prisiminkime, kad kelios skirtingos funkcijos gali turti tok pat vard, jei skiriasi j parametr tipai arba kiekiai. I kreipinio pavidalo kompiliatorius nustato, kuri i j kreipiamasi. Konstruktori, kuri vardas turi bti toks pat kaip ir klass vardas, taip pat gali bti ne vienas, o keli. Skelbiant objekt bus pasirinktas tas konstruktorius, kuris atitinka skelbime nurodytus argumentus: // pasirinktiniai konstruktoriai #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: Cstaciakampis (); Cstaciakampis (int,int); int plotas () { return (x*y); } }; Cstaciakampis :: Cstaciakampis () { x = 5; y = 5; } Cstaciakampis :: Cstaciakampis (int a, int b) { x = a; y = b; } int main () { Cstaciakampis stc1 (3,4); Cstaciakampis stc2; cout << "stc1 plotas: " << stc1.plotas() << endl; cout << "stc2 plotas: " << stc2.plotas() << endl; return 0; }

stc1 plotas: 12 stc2 plotas: 25

ia objektas stc2 paskelbtas nenurodant argument. Todl jis inicializuojamas parametr neturiniu konstruktoriumi, kuris x ir y priskiria reikm 5. Pastebkime, kad skelbiant nauj objekt ir naudojant numatytj (default) konstruktori (pastarasis neturi parametr), skliaust () rayti nereikia: Cstaciakampis stab; Cstaciakampis stab (); // teisingai // neteisingai!

111

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

14.3. Numatytasis ( default ) konstruktorius


Jeigu klass aprae mes nenurodome jokio konstruktoriaus, tai kompiliatorius laiko, kad yra numatytasis (default) konstruktorius be parametr. Paskelbus toki klas kaip i: class Cpavyzdys { public: int a,b,c; void daugyba (int n, int m) { a=n; b=m; c=a*b; }; }; kompiliatorius laikys, kad Cpavyzdys klas turi numatytj konstruktori. ios klass objektai skelbiami nenurodant joki argument. Pvz.: Cpavyzdys abc; Bet kai tik mes nurodome klasei jos konstruktori, kompiliatorius daugiau nebepripasta numatytj konstruktori. Todl visiems ms skelbiamiems tos klass objektams galios ms nurodytas tos klass konstruktorius: class Cpavyzdys { public: int a, b, c; Cpavyzdys (int n, int m) { a=n; b=m; }; void daugyba () { c=a*b; }; }; ia mes paskelbme konstruktori su dviem int tipo parametrais. Todl is objekto skelbimas Cpavyzdys abc (2,3); bus teisingas, o skelbimas Cpavyzdys abc; // neteisingas skelbimas // teisingas skelbimas

jau bus neteisingas, nes klas turi aikiai nurodyt konstruktori, kuris pakeiia numatytj. Taiau kompiliatorius sukuria ne tik numatytj konstruktori, kai jo mes nenurodome, bet dar pateikia tris specialias funkcijas: kopijuojantj konstruktori, kopijuojantj priskyrimo operatori ir numatytj (default) destruktori. Kopijuojantysis konstruktorius ir kopijuojantysis priskyrimo operatorius nukopijuoja

112

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

visus kito objekto duomenis ir perkelia einamj objekt. Klasei Cpavyzdys kompiliatorius netiesiogiai sukurs kopijuojantj konstruktori pana : Cpavyzdys :: Cpavyzdys (const Cpavyzdys& rv) { a=rv.a; b=rv.b; c=rv.c; } Todl toliau parodyti du objekt skelbimai yra teisingi: Cpavyzdys abc1 (2,3); Cpavyzdys abc2 (abc1); /* kopijuojantysis konstruktorius duomenis kopijuos i abc1 */

14.4. Klasi rodykls


Kaip ir kitoki tip atvejais (int, char, t.t.), taip ir klasms gali bti kuriamos rodykls. Jei jau turime paskelb klas, tai jos vardas gali bti naudojamas rodykls tipui nurodyti. Pvz.: Cstaciakampis * psta; psta yra rodykl, kuri gals siminti Cstaciakampis klass objekto adres. Kaip ir duomen struktr (struct) atveju, nordami tiesiogiai kreiptis rodykle nurodyto objekto nar, mes galime naudoti rodykls operatori (->). tai galim kombinacij pavyzdys: // klasi rodykli pavyzdys #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: void nurodyk_krastines (int, int); int plotas (void) { return (x * y); } }; void Cstaciakampis :: nurodyk_krastines (int a, int b) { x = a; y = b; } int main () { Cstaciakampis a, *b, *c; Cstaciakampis *d = new Cstaciakampis[2]; b= new Cstaciakampis;
113

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

c= &a; a.nurodyk_krastines (1,2); b->nurodyk_krastines (3,4); d->nurodyk_krastines (5,6); d [1].nurodyk_krastines (7,8); cout << "a plotas: " << a.plotas() << endl; cout << "*b plotas: " << b -> plotas() << endl; cout << "*c plotas: " << c -> plotas() << endl; cout << "d [0] plotas: " << d [0].plotas() << endl; cout << "d [1] plotas: " << d [1].plotas() << endl; return 0; } Toliau pateikiama suvestin lentel, kaip reikt suprasti kai kuriuos rodykli ir klasi operatorius ( *, &, ., ->, [ ] ), panaudotus ankstesniame pavyzdyje: iraika *x &x x.y x->y (*x).y x [0] x [1] x [n] reikm esanti adresu x x adresas objektui x priklausantis narys y objektui, kurio adresas yra rodyklje x, priklausantis narys y objektui, kurio adresas yra rodyklje x, priklausantis narys y ( ekvivalentika iraikai x->y ) pirmasis objektas, kurio adresas yra rodyklje x antrasis objektas, kurio adresas gaunamas remiantis rodyklje x esaniu adresu (n+1)-sis objektas, kurio adresas gaunamas remiantis rodyklje x esaniu adresu reikm a plotas: 2 *b plotas: 12 *c plotas: 2 d [0] plotas: 30 d [1] plotas: 56

14.5. Klasi skelbimas naudojant struct ir union


Klases galima paskelbti naudojant ne tik bazin od class, bet ir bazinius odius struct ir union. Klasi ir duomen struktr idjos yra tiek panaios, kad abiej bazini odi paskirtis C++ kalboje yra beveik vienoda. Skirtumas yra toks, kad paskelbus klas struct baziniu odiu, jos nariai bna public kreipties, o paskelbus class baziniu odiu private kreipties. Kitais poiriais struct ir class yra ekvivalentiki.

114

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Bendrosios atminties srii union idja skiriasi nuo struct ir class, nes union saugo tik vien duomen nar duotu metu. Taiau union taip pat yra klas ir jis gali saugoti narius-funkcijas. Numatytoji kreiptis union klass narius yra public.

14.6. static nariai klasse


Klasse bet kuris narys duomuo (kintamasis) ar funkcija - gali turti static poym. poym turintys duomenys dar vadinami klasi kintamaisiais. Jie yra unikals tuo, kad j reikm prieinama visiems tos klass objektams, t.y. visiems tos klass objektams j reikm bus ta pati. Pvz., toks kintamasis gali bti naudojamas kaip skaitliukas, kiek gi tos klass objekt programoje buvo sukurta: // static nariai klasse #include <iostream> using namespace std; class Cpypke { public: static int n; Cpypke () { n++; }; ~Cpypke () { n--; }; }; int Cpypke :: n = 0; int main () { Cpypke a; Cpypke b[5]; Cpypke * c = new Cpypke; cout << a.n << endl; delete c; cout << Cpypke :: n << endl; return 0; }

7 6

Faktikai static nariai turi tokias paias savybes kaip ir globalieji kintamieji, taiau j galiojimo sritis yra tik vienos klass objektai. Dl ios prieasties mes galime skelbti juos klasje, bet be inicializavimo. static poym turintys klass kintamieji inicializuojami u klass rib esaniu formaliu apibrimu, kaip parodyta turtame pavyzdyje: int Cpypke :: n=0;

115

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Kadangi n yra unikalus kintamasis, galiojantis visuose tos klass objektuose, j galima kreiptis dvejopai: kaip kakurio objekto nar arba kaip klass nar: cout << a.n; cout << Cpypke :: n; // kreipiamasi kaip objekto a nar // kreipiamasi kaip klass Cpypke nar

Klasse static poym gali turti ir funkcijos. Taiau tokios funkcijos gals operuoti tik su tos klass static kintamaisiais.

14.7. Klasi ablonai ( template )


C++ kalboje klasi ablonai, panaiai kaip ir funkcij ablonai (ir. 7.5 skyri), galina pritaikyti klas darbui su vairaus tipo kintamaisiais. Pvz., apibrkime klas, kuri gali siminti por skaii: // klass ablonas template <class T> class pora { T reiksmes[2]; public: pora (T r1, T r2) { reiksmes[0]=r1; reiksmes[1]=r2; } }; Jei mes norime paskelbti ios klass objekt sveikiesiems int tipo skaiiams 115 ir 36 siminti, turtume rayti taip: pora <int> aobj (115, 36); i klas taip pat gali bti panaudota kuriant objektus ir kitokio tipo reikmms siminti: pora <float> bobj (3.0, 2.18); iame klass ablono pavyzdyje jos nario-funkcijos programos tekstas yra klass aprao viduje. Jei nario-funkcijos programos tekstas bt klass aprao iorje, tuomet prie tokios funkcijos programos tekst reikt nurodyti tok pat template < ... >, kok urame klass ablono pradioje:

116

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// klasi ablonai #include <iostream> using namespace std; template <class T> class pora { T a, b; public: pora (T r1, T r2) { a=r1; b=r2; } T didesnis (); }; template <class T> T pora<T>::didesnis() { T gr; gr = a>b? a : b; return gr; } int main () { pora <int> aobj (100, 75); cout << aobj.didesnis(); return 0; } Atkreipkime dmes klass nario-funkcijos didesnis() apra template <class T> T pora<T>::didesnis() Jame yra net trys duomens tipo nuorodos T. Pirmasis T yra klass ablono parametras. Antruoju T nurodomas funkcijos grainamos reikms tipas. Treiasis T, kuris apskliaustas enklais <>, nurodo, kad is klass ablono parametras taip pat yra ir funkcijos ablono parametras.

100

117

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

15. Draugikumas ir paveldimumas


15.1. Draugikosios funkcijos ( friend )
Kreipiniai klasi private ir protected kreipties narius galimi tik tos paios klass funkcijose. Taiau i taisykl negalioja draugikosioms (friend) funkcijoms ir klasms. Iorin duotai klasei, taiau jai draugikoji funkcija gali kreiptis tos klass private ir protected narius. Tokios funkcijos prototipas turi bti paskelbtas toje klasje, priekyje raant bazin od friend, o pati funkcija skelbiama prastu bdu: // friend funkcijos #include <iostream> using namespace std; class Cstaciakampis { int x, y; public: void nurodyk_krastines (int, int); int plotas () { return (x * y); } friend Cstaciakampis keturgubas (Cstaciakampis); }; void Cstaciakampis :: nurodyk_krastines (int a, int b) { x = a; y = b; } Cstaciakampis keturgubas (Cstaciakampis stapar) { Cstaciakampis starez; starez.x = 2*stapar.x; starez.y = 2*stapar.y; return (starez); } int main () { Cstaciakampis stc1, stc2; stc1.nurodyk_krastines (2,3); stc2 = keturgubas (stc1); cout << stc2.plotas(); return 0; }

24

118

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Funkcija keturgubas yra draugika klasei Cstaciakampis. ioje funkcijoje mes galime kreiptis vairi tos klass objekt narius x ir y, kurie yra private kreipties. Pastebkime, kad funkcijos keturgubas skelbime ir kreipinyje j pagrindinje funkcijoje (main) nra joki nuorod, kad ji bt klass Cstaciakampis narys. Ji paprastai kreipiasi private ir protected duomenis, nebdama tos klass narys. Draugikosios (friend) funkcijos gali praversti, pvz., atliekant operacijas su dviej skirting klasi objektais. Apskritai, draugikj funkcij naudojimas ieina u objektinio programavimo metodologijos rib, todl, jei tik manoma, geriau yra naudoti tos paios klass narius atliekant operacijas. Ms turtas programos pavyzdys bt trumpesnis, jei funkcija keturgubas bt klass Cstaciakampis narys.

15.2. Draugikosios klass


C++ kalboje yra galimyb apibrti klas, kuri bt draugika kitai. Taip pasiekiama, kad viena klas gali kreiptis kitos klass private ir protected kreipties narius. // friend klass #include <iostream> using namespace std; class Ckvadratas; class Cstaciakampis { int x, y; public: int plotas () { return (x * y); } void konvertuok (Ckvadratas a); }; class Ckvadratas { int sonas; public: void nurodyk_sona (int a) { sonas = a; } friend class Cstaciakampis; }; void Cstaciakampis :: konvertuok (Ckvadratas a) { x = a.sonas; y = a.sonas; }

119

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int main () { Ckvadratas kva; Cstaciakampis sta; kva.nurodyk_sona(4); sta.konvertuok(kva); cout << sta.plotas(); return 0; } iame pavyzdyje mes paskelbme klas Cstaciakampis, kuri yra draugika klasei Ckvadratas. Todl klass Cstaciakampis funkcija konvertuok gijo galimyb kreiptis klass Ckvadratas duomen sonas, kuris yra numatytosios private kreipties. Nauja ioje programoje yra dar ir tai, kad matome tui klass Ckvadratas skelbim, t.y. class Ckvadratas; Jis yra btinas, nes skelbiamos klass Cstaciakampis funkcijoje konvertuok() yra nuoroda Ckvadratas, o pati klas Ckvadratas aprayta vliau. Draugikumo tarp klasi nebus, jei to aikiai nenurodysime. Ms pavyzdyje Cstaciakampis yra draugikas klasei Ckvadratas, taiau Ckvadratas nra draugikas klasei Cstaciakampis. Jeigu reikt, tai ir pastarj draugikum galima bt nurodyti. Kita draugikumo savyb yra ta, kad jis nra perduodamas. Draugo draugas nra laikomas draugu, kol to aikiai nenurodysime. 16

15.3. Klasi paveldimumas


Paveldimumas yra labai svarbi klasi savyb. Jis leidia kurti klases, kurios yra ivestins i kit klasi. Taip automatikai perimami t kit klasi nariai, papildomai pridedant naujus. Pvz., mes norime paskelbti serij klasi, kurios aprao vairius daugiakampius, kaip Cstaciakampis ar Ctrikampis. Jie tikriausiai turi bendr savybi, pvz., gali bti apraomi dviem dydiais: auktine ir pagrindu. Tai gali bti atspindta panaudojus klas Cdaugiakampis, i kurios bt ivedamos kitos dvi klass: Cstaciakampis ir Ctrikampis. Klas Cdaugiakampis galt turti savyje bendras abiej daugiakampi savybes, pvz., ms atveju plot ir aukt. Tuo tarpu Cstaciakampis ir Ctrikampis galt bti ivestins klass su savo specifinmis savybmis, padedaniomis atskirti vieno tipo daugiakamp nuo kito. Klass, kurios gaunamos i kit klasi, vadinam bazinmis klasmis, paveldi t bazini klasi narius. Tai reikia, kad jeigu bazin klas turi nar A, o ivestin klas turi nar B, tai ivestin klas turs abu narius A ir B. Ivestinei klasei gauti remiantis bazine, skelbime reikia rayti dvitak (:) tarp i klasi vard:
120

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

class ivestins_klass_vardas : public bazins_klass_vardas { ivestins_klass_nariai } ia parodytas kreipties atributas public gali bti pakeistas private ar protected. Jais nurodomas minimalus kreipties lygis, kuris bus taikomas i bazins klass paveldtiems nariams. // ivestins klass #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x plotis, y - auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b;} }; class Cstaciakampis : public Cdaugiakampis { public: int plotas () { return ( x * y ); } }; class Ctrikampis : public Cdaugiakampis { public: int plotas () { return ( x * y / 2 ); } }; int main () { Cstaciakampis sta; Ctrikampis trk; sta.nurodyk_matavimus (4,5); trk.nurodyk_matavimus (4,5); cout << sta.plotas() << endl; cout << trk.plotas() << endl; return 0; }

20 10

Klasi Cstaciakampis ir Ctrikampis objektai sta ir trk turi paveldtus narius i klass Cdaugiakampis. Tai duomenys x, y ir funkcija nurodyk_matavimus.

121

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Kreipties atributas protected yra panaus private. Skirtumas tarp j atsiranda tik paveldjimo atveju. Kai viena klas paveldi kitos klass narius, ivestins klass nariai gali kreiptis bazins klass protected narius, bet ne private narius. Kadangi mums reikjo, kad x ir y bt prieinamas ne tik bazins klass Cdaugiakampis nariams, bet ir ivestini klasi Cstaciakampis ir Ctrikampis nariams, vietoje private (jis yra numatytasis, kai nieko nenurodoma) panaudojome protected. Apibendrindami skirtingus kreipties tipus, emiau lentelje pateikiame, kas ir kokiu atveju gali kreiptis klass nar: Kas kreipiasi tos paios klass narys ivestins klass narys ne nariai public taip taip taip protected taip taip ne private taip ne ne

ioje lentelje ne nariai reikia bet kok kreipin i u klass rib, kaip i main() funkcijos, kitos klass ar funkcijos. Ms pavyzdyje narius, kuriuos paveldjo klass Cstaciakampis ir Ctrikampis, vienodas kreipimosi teises turi visos trys paskelbtos klass. Cdaugiakampis :: x // protected kreiptis Cstaciakampis :: x // protected kreiptis Cdaugiakampis :: nurodyk_matavimus() // public kreiptis Cstaciakampis :: nurodyk_matavimus() // public kreiptis Taip yra todl, kad ivestini klasi skelbimuose prie bazin klas rame public: class Cstaciakampis : public Cdaugiakampis { ... } Baziniu odiu public, raomu po dvitakio (:), paymimas minimalus kreipties lygis bazins klass narius, leistinas ivestinei klasei. Kadangi public reikia aukiausi kreipties lyg, todl ivestins klass kreipties bazins klass narius lygis yra toks pat kaip ir bazins klass. Jei ivestins klass skelbime prie bazin klas nurodytume protected kreipties lyg, visi bazins klass public nariai ivestinei klasei pasidaro protected lygio. Analogikai, jei nurodytume labiausiai apribojant kreipties lyg private, tai visi bazins klass nariai pasidaryt private lygio. Jei paveldint kreipties lygis prie bazin klas nenurodomas, kompiliatorius laiko, kad class baziniu odiu paskelbtoms klasms jis yra private, o struct baziniu odiu paskelbtoms public.

122

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

15.4. Kas nepaveldima i bazins klass?


Ivestin klas paveldi visus bazins klass narius, iskyrus: - konstruktori ir destruktori; - operator=() narius (apie juos ioje mokymo priemonje neraoma); - draugikuosius (friend) narius.

15.5. Daugeriopas paveldimumas


C++ kalboje manoma, kad viena ivestin klas paveldt keleto bazini klasi narius. Ivestins klass skelbime tai nurodoma, bazines klases atskiriant kableliu. Pvz., jei mes turime kakoki klas duomenims ivesti ekran (Cisved) ir norime, kad j paveldt ms turtos klass Cstaciakampis ir Ctrikampis, reikt rayti: class Cstaciakampis : public Cdaugiakampis, public Cisved; class Ctrikampis : public Cdaugiakampis, public Cisved; Toliau pateikiamas isamesnis pavyzdys: // daugeriopas paveldimumas #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x plotis, y - auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b;} }; class Cisved { public: void isved (int i); }; void Cisved :: isved (int i) { cout << i << endl; } class Cstaciakampis : public Cdaugiakampis, public Cisved { public: int plotas () { return (x * y); } };
123

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

class Ctrikampis : public Cdaugiakampis, public Cisved { public: int plotas () { return (x * y / 2); } }; int main () { Cstaciakampis sta; Ctrikampis trk; sta.nurodyk_matavimus (4,5); trk.nurodyk_matavimus (4,5); sta.isved (sta.plotas()); trk.isved (trk.plotas()); return 0; }

124

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

16. Polimorfizmas
Skaitantieji skyri turt bti gerai susipain su rodyklmis ir klasi paveldimumu. Jei kurio nors i emiau pateikt ura prasm yra neaiki, perirkite nurodytus ios mokymo priemons skyrius: Uraas int a::b(c) {}; a->b class a : public b; irkite skyri
14. Klass ir objektai 10. Rodykls (pointers) 15. Draugikumas ir paveldimumas

16.1. Bazini klasi rodykls


Ivestini klasi viena i pagrindini savybi yra ta, kad ivestins klass rodykls tipas yra suderinamas su bazins klass rodykls tipu. Polimorfizmas yra pagrstas ia paprasta, taiau galinga ir lanksia savybe, kuri suteikia objektiniam programavimui vis potencial. Toliau mes perraysime ankstesni ios mokymo priemons skyri program apie staiakamp ir trikamp, atsivelgdami mint rodykli suderinamumo savyb. // bazini klasi rodykls #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x plotis, y - auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } }; class Cstaciakampis : public Cdaugiakampis { public: int plotas () { return (x * y); } };

125

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

class Ctrikampis : public Cdaugiakampis { public: int plotas () { return (x * y / 2); } }; int main () { Cstaciakampis sta; Ctrikampis trk; Cdaugiakampis * rodgk1 = &sta; Cdaugiakampis * rodgk2 = &trk; rodgk1->nurodyk_matavimus (4,5); rodgk2->nurodyk_matavimus (4,5); cout << sta.plotas() << endl; cout << trk.plotas() << endl; return 0; } Pagrindinje funkcijoje main mes paskelbme dvi Cdaugiakampis tipo rodykles rodgk1 ir rodgk2. Joms priskyrme objekt sta ir trk adresus. Kadangi ie abu objektai yra ivestini i Cdaugiakampis klasi tipo, tai abu priskyrimai yra teisingi. Vienintelis rodgk1 ir rodgk2 naudojimo vietoje sta ir trk ribotumas yra tas, kad rodgk1 ir rodgk2 yra Cdaugiakampis tipo, ir todl ias rodykles galima naudoti tik nariams, kuriuos Cstaciakampis ir Ctrikampis yra paveldj i Cdaugiakampis. Dl ios prieasties, kuomet programos pabaigoje mes kreipms narius plotas(), turjome tiesiogiai nurodyti objektus sta ir trk, o ne naudoti rodykles rodgk1 ir rodgk2. Kad funkcij plotas() galima bt naudoti drauge su Cdaugiakampis tipo rodyklmis, ji turt bti paskelbta bazins klass Cdaugiakampis viduje, o ne ivestinse klasse Cstaciakampis ir Ctrikampis. Bet problema yra ta, kad klasse Cstaciakampis ir Ctrikampis yra skirtingos funkcij plotas() versijos, todl perkelti j bazin klas negalima. Tokiais atvejais labai praveria virtuals klasi nariai.

20 10

16.2. Virtuals klasi nariai


Bazins klass narys, kuris gali bti i naujo apibriamas ivestinje klasje, vadinamas virtualiu nariu. Virtualus klass narys skelbiamas jo priekyje raant bazin od virtual:
126

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

// virtuals nariai #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x plotis, y auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } virtual int plotas () { return (0); } }; class Cstaciakampis : public Cdaugiakampis { public: int plotas () { return (x * y); } }; class Ctrikampis : public Cdaugiakampis { public: int plotas () { return (x * y / 2); } }; int main () { Cstaciakampis sta; Ctrikampis trk; Cdaugiakampis dgk; Cdaugiakampis * rodgk1 = &sta; Cdaugiakampis * rodgk2 = &trk; Cdaugiakampis * rodgk3 = &dgk; rodgk1->nurodyk_matavimus (4,5); rodgk2->nurodyk_matavimus (4,5); rodgk3->nurodyk_matavimus (4,5); cout << rodgk1->plotas() << endl; cout << rodgk2->plotas() << endl; cout << rodgk3->plotas() << endl; return 0; }

20 10 0

127

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Dabar visos trys klass (Cdaugiakampis, Cstaciakampis, Ctrikampis) turi tuos paius narius: x, y, nurodyk_matavimus() ir plotas(). Funkcija plotas() yra paskelbta kaip virtualus bazins klass narys, nes vliau ji i naujo apibriama ivestinse klasse. Taigi, odis virtual galina kreiptis ne tik bazins klass nar, bet ir ivestins klass nar, kurio vardas sutampa su bazins klass nario vardu. kurios klass nar bus kreipiamasi priklausys nuo to, kokios klass objekto adresas priskirtas bazins klass rodyklei. Klass, kuriose yra paskelbtos arba kurios paveldi virtualias funkcijas, vadinamos polimorfinmis klasmis. Neirint virtualumo, mes taip pat galime skelbti klass Cdaugiakampis tipo objektus ir kreiptis jos nuosav funkcij plotas(), kuri visada grina 0.

16.3. Abstrakiosios bazins klass


Abstrakioji bazin klas yra labai panai klas Cdaugiakampis ms turtame pavyzdyje. Vienintelis skirtumas yra tas, kad ms turtame pavyzdyje yra paskelbta prasto pavidalo virtuali funkcija plotas() ir ji atlieka minimalias funkcijas Cdaugiakampis klass objektams (pvz., dgk), o abstrakiosiose bazinse klasse virtuali funkcij plotas() galtume rayti be jos gyvendinamosios dalies. Tam funkcijos skelbimo gale reikia prirayti =0 (lygu nuliui). Abstrakioji bazin klas Cdaugiakampis atrodyt taip: // abstrakioji bazin klas class Cdaugiakampis { protected: int x, y; public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } virtual int plotas() =0; }; Pastebkime, kad po virtual int plotas() vietoje funkcijos gyvendinamosios dalies urame =0. itokio tipo funkcijos yra vadinamos grynosiomis virtualiomis funkcijomis, o visos klass, turinios bent vien grynj virtuali funkcij, vadinamos abstrakiosiomis bazinmis klasmis. Pagrindinis skirtumas tarp abstrakiosios bazins klass ir prastos polimorfins klass yra tas, kad abstrakiojoje bazinje klasje bent vienas jos narys neturi gyvendinamosios dalies, dl ko negalima skelbti toki klasi objekt.

128

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Taiau klass, kuri objektai negalimi, nra visikai beprasms. Mes galime kurti tokio tipo rodykles ir gauti naudos i polimorfikumo galimybi. Taigi, skelbimas pavidalo: Cdaugiakampis dgk; naudojant abstrakij bazin klas nra leistinas, nes juo norime paskelbti objekt. Taiau rodykli skelbimai: Cdaugiakampis * rodgk1; Cdaugiakampis * rodgk2; yra visikai leistini. Be to, klas Cdaugiakampis turi grynj virtuali funkcij ir todl ji yra abstrakioji bazin klas. Taiau ios bazins klass tipo rodykls gali bti naudojamos ivestini klasi objekt adresams siminti. Panagrinkime sudtingesn pavyzd: // abstrakioji bazin klas #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } virtual int plotas (void) =0; }; class Cstaciakampis : public Cdaugiakampis { public: int plotas (void) { return (x * y); } }; class Ctrikampis : public Cdaugiakampis { public: int plotas (void) { return (x * y / 2); } };

129

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int main () { Cstaciakampis sta; Ctrikampis trk; Cdaugiakampis * rodgk1 = &sta; Cdaugiakampis * rodgk2 = &trk; rodgk1->nurodyk_matavimus (4,5); rodgk2->nurodyk_matavimus (4,5); cout << rodgk1->plotas() << endl; cout << rodgk2->plotas() << endl; return 0; }

20 10

Pasigilin i program pamatysime, kad mes kreipms skirting, bet susijusi klasi objektus, naudodami vien rodykls tip (Cdaugiakampis*). Tai gali duoti didiul naud. Pvz., dabar mes galime paskelbti abstrakiosios bazins klass Cdaugiakampis nauj nar-funkcij, kuri ivest ekran funkcijos plotas() rezultatus, netgi jei plotas() gyvendinamosios dalies klasje Cdaugiakampis nra. /* abstrakioji bazin klas gali kreiptis grynuosius virtualius narius */ #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x- plotis, y auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } virtual int plotas (void) =0; void isved (void) { cout << this->plotas() << endl; } }; class Cstaciakampis : public Cdaugiakampis { public: int plotas (void) { return (x * y); } }; class Ctrikampis: public Cdaugiakampis { public: int plotas (void) { return (x * y / 2); } };
130

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int main () { Cstaciakampis sta; Ctrikampis trk; Cdaugiakampis * rodgk1 = &sta; Cdaugiakampis * rodgk2 = &trk; rodgk1->nurodyk_matavimus (4,5); rodgk2->nurodyk_matavimus (4,5); rodgk1->isved(); rodgk2->isved(); return 0; } Bazins klass Cdaugiakampis naryje-funkcijoje isved() pavartotas bazinis odis this, atitinkantis rodykl. Jis gyja to objekto rodykls reikm, kuris yra apdorojamas. Virtuals nariai ir abstrakiosios klass suteikia C++ kalbai polimorfines charakteristikas ir daro objektin programavim labai naudingu instrumentu dideliuose projektuose. inoma, ia mes susipainome tik su paprastu i savybi panaudojimu. ios savybs gali bti taikomos objekt masyvams ir dinaminiams objektams. Pabaigai pateikiame t pat pavyzd, taiau su dinaminiais objektais: // dinaminis atminties skyrimas ir polimorfizmas #include <iostream> using namespace std; class Cdaugiakampis { protected: int x, y; // x plotis, y - auktis public: void nurodyk_matavimus (int a, int b) { x=a; y=b; } virtual int plotas (void) =0; void isved (void) { cout << this->plotas() << endl; } }; class Cstaciakampis : public Cdaugiakampis { public: int plotas (void) { return (x * y); } }; 20 10

131

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

class Ctrikampis: public Cdaugiakampis { public: int plotas (void) { return (x * y / 2); } }; int main () { Cdaugiakampis * rodgk1 = new Cstaciakampis; Cdaugiakampis * rodgk2 = new Ctrikampis; rodgk1->nurodyk_matavimus (4,5); rodgk2->nurodyk_matavimus (4,5); rodgk1->isved(); rodgk2->isved(); delete rodgk1; delete rodgk2; return 0; } Pastebkime, kad rodykls rodgk1 ir rodgk2 yra Cdaugiakampis tipo, o patys objektai yra paskelbti dinamikai, nurodant tiesiog ivestini klasi tipus.

20 10

132

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

17. Dar apie duomen fail vedim/ivedim


17.1. vedimo/ivedimo funkcijos read() ir write()
C++ kalboje bibliotekiniame <fstream> faile laikomose standartinse ofstream ir ifstream klasse yra nariai-funkcijos write() ir read(), skirtos duomen mainams su failais bit lygiu (vedimo/ivedimo metu jokia duomen transformacija neatliekama). Pavyzdys. Pateikiama programa urao fail duotos struktros Studentas

duomenis, po to skaito juos i sukurto failo ir iveda ekran. Funkcijose write() ir read() uraas (char*) nurodo kompiliatoriui, kad parametro rodykls reikm, pvz., &B, gali nurodyti bet kokio tipo duomenims skirt adres. // write() ir read() funkcij naudojimo pavyzdys #include <iostream> // i ios bibliotekos imami cin, cout #include <fstream> // i ios bibliotekos imami ifstream, ofstream, write, read using namespace std; struct Studentas { char pav [20]; int metai; float ugis; }; int main() { Studentas A; Studentas B = {"Pavardenis", 21, 187.5}; cout << B.pav << " " << B.metai << " " << B.ugis << endl; ofstream R ("c:\\katalog\\duom1.d"); ifstream D ("c:\\katalog\\duom1.d"); R.write ( (char *)&B, sizeof(Studentas) ); // rao fail duom1.d R.close(); D.read ( (char*)&A, sizeof(Studentas)); // skaito i failo duom1.d cout << A.pav << " " << A.metai << " " << A.ugis << endl; D.close(); return 0;
}

write() ir read() sakiniai i atminties nurodytu adresu perduoda nurodyt bait kiek, t.y. tiek, kiek uima struktra Studentas. Faile c:\katalog\duom1.d urayt duomen vizualiai pairti negalsime, nes jie ten urayti dvejetainiu pavidalu.

133

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

17.2. vedimo/ivedimo funkcijos fscanf(), fprintf() ir kitos


Apdorojant didesnius duomen kiekius, patogu juos laikyti failuose (pvz., diskuose). Failo tipo rodykls apraomos taip: FILE *vardas; Failai paruoiami darbui funkcija (ji laikoma bibliotekoje <cstdio>), kurios prototipas yra: FILE *fopen (const char *Failo_Vardas, const char *M); Failo_Vardas nurodomas simboli eilute, vardine konstanta arba kintamuoju. Antruoju parametru M (taip pat simboli eilute, vardine konstanta arba kintamuoju) nurodomas failo stovis, t.y. leistina failo duomen perdavimo kryptis. Galimi fail stovio poymiai parodyti lentelje: Poymis r w Failo stovis Fail galima tik skaityti Failas skirtas tik raymui. Jei toks failas jau buvo, tai jis itrinamas ir kuriamas naujas. Papildyti fail duomenimis, raant juos failo gale. Jei nurodyto failo dar nebuvo, jis sukuriamas.

Stovio poym papildius raide t (raant rt, wt, at), failas bus paruotas darbui kaip tekstinis. Stovio reikm papildius raide b ( raant rb, wb, ab), failas bus paruotas darbui kaip binarinis. Jeigu nra nei t, nei b raids, failo parengimas darbui priklauso nuo globaliojo kintamojo fmode reikms (r. fail fcntl.h). Kiekviena stovio nuoroda gali bti papildyta enklu + , pvz., r+, w+, wt+. Tai reikia, kad failai gali bti atnaujinami, t.y. leidiama juos skaityti ir rayti. emiau lentelje pateikiame pagrindini buferizuot vedimo/ivedimo funkcij prototipus (antrates). Jos yra laikomos cstdio bibliotekoje. Funkcijos prototipas (antrat) int printf (const char *f [,kintamieji]); int scanf (const char *f [,kint._atminties_laukai]); int fclose (FILE *rod); int putc (int simbolis, FILE *rod); int getc (FILE *rod); Funkcijos atliekami veiksmai Iveda ekran kintamj reikmes pagal ablon f ; veda klaviatra reikmes kintamj atminties laukus pagal ablon f ; Udaro fail Iveda simbol fail rod veda simbol i failo rod

134

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int putw (int sk, FILE *rod); int getw (FILE *rod); char *fgets (char*s, int n, FILE *rod); int fputs (const char *s, FILE *rod); int fread (void *buf, int t, int n, FILE *rod);

Iveda skaii fail rod veda skaii i failo rod veda n simboli ilgio eilut s i failo rod Iveda eilut s fail rod veda n blok, turini po t bait, i failo rod bufer buf; funkcijos fread reikm vest blok skaiius Iveda n blok, turini po t bait, i buferio buf fail rod; funkcijos fwrite reikm - ivest blok skaiius Iveda fail rod ivardinto srao element reikmes pagal ablon f ; ablonas f ir kintamj sraas sudaromi taip pat, kaip ir funkcijoje printf veda srao element reikmes i failo rod pagal ablon f; ablonas f ir element sraas sudaromi taip pat, kaip ir funkcijoje scanf. Funkcijos fscanf reikm vest srao element reikms Tikrina skaitomo failo rod pabaig. Jei dar ne failo pabaiga, funkcijos reikm nelygi nuliui Tikrina darbo su failu rod klaidas. Jei klaid nebuvo, funkcijos reikm lygi nuliui alina fail vardas

int fwrite (void *buf, int t, int n, FILE *rod);

int fprintf ( FILE *rod, const char *f [,sraas] );

int fscanf (FILE *rod, const char *f [,sraas]);

int feof (FILE *rod);

int ferror (FILE *rod);

int remove (const char *vardas);

Programai apdorojam fail vardai gali bti perduodami per pagrindins funkcijos main parametrus. Tokios pagrindins funkcijos prototipas yra: int main ( int n, char *argv [] );
135

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

ia n argument skaiius, o argv argumentams skirto eilui masyvo rodykl. Argument reikms yra nurodomos programos ikvietimo komandoje ir yra atskiriamos tarpais. Nulin indekso reikm turinioje argument masyvo eilutje uraomas paios programos pavadinimas.
1 pavyzdys. Tarkime, turime skaii fail c:\ktlg\skc.txt. Reikia vesti skaiius

i io failo, urayti juos programoje paskelbt masyv ir ivesti ekran. Toliau apskaiiuoti masyvo element sum ir ivesti j ekran. Skaiiai faile yra mogui perskaitomo tekstinio (simboli) pavidalo. #include <cstdio> // i ios bibliotekos ims FILE, fscanf, fopen, foef, printf #include <cstdlib> // i ios bibliotekos ims system using namespace std; const int Kiek = 15; // ia konstanta apribojam apdorojam skaii kiek typedef int mas [Kiek]; FILE *Fskc; void Sp (mas, int); int Suma (mas, int); int main() { mas A; int n = 0; Fskc = fopen("c:\\ktlg\\skc.txt", "r"); if (Fskc == NULL) { printf("Failas neatidarytas"); exit (); } else { while ( !feof(Fskc) && ( n < Kiek) ) { fscanf ( Fskc, "%d", &A [n] ); // veda i failo Fskc if ( !feof(Fskc) ) n++; } Sp(A, n); printf ("\n \n Suma = %d \n ", Suma(A, n)); } system ("PAUSE"); // stabdo program jos rezultatams ekrane pairti return 0; } void Sp(mas X, int n) // masyvo ivedimo ekran funkcija { int i = 0; while (i<n) printf(" %d", X [i++]); } // masyvo ivedimo ekran funkcijos prototipas // masyvo element sumavimo funkcijos prototipas

136

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

int Suma(mas R, int k) { int i = 0, S = 0; while (i<k) return S; } S += R [i++];

// masyvo element sumavimo funkcija

2 pavyzdys. Faile c:\ktlg\pradf.txt yra urayti skaiiai. Reikia skaiius i io

failo vesti programoje paskelbt masyv. Po to masyvo element reikmes ivesti fail c:\ktlg\kitf.txt . #include <cstdio> #include <cstdlib> using namespace std; // i ios bibliotekos ims system

const int Kiek = 15; const char finved[] = "c:\\ktlg\\pradf.txt"; const char fisved[] = "c:\\ktlg\\kitf.txt"; typedef int mas [Kiek]; void SpF (mas, int, char); int Ivesti (mas, int *);

// failas ivedimui // failas ivedimui

// ivedimo fail funkcijos prototipas // vedimo i failo funkcijos prototipas

int main() { mas A; int n = 0; if ( Ivesti(A, &n) ) { printf ("\n** Failo neatidare arba nera duomenu\n"); system ("PAUSE"); exit(1); // exit() nutraukia program } SpF (A, n, 'A'); printf("Masyvas uzrasytas i faila %s\n", fisved); system ("PAUSE"); // stabdo program jos eigos praneimams pairti return(0); } int Ivesti (mas A, int *n) // vedimo i failo funkcija { FILE *Fin; Fin = fopen(finved, "r"); if ( Fin == NULL ) { printf ( " ** Failas neatidarytas" ); return 1; }

137

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

else while ( !feof(Fin) && (*n < Kiek) ) { fscanf(Fin, "%d", &A [*n]); if (!feof(Fin)) (*n)++; } fclose (Fin); if ( (*n) == 0 ) { printf ( " ** Faile nera duomenu" ); return 1; } return 0; } void SpF (mas X, int n, char R) // ivedimo fail funkcija { FILE *Fis; int i = 0; Fis = fopen (fisved, "w"); if (Fis == NULL) { printf ( "Failas neatidarytas isvedimui" ); exit(1); } else { while (i < n) fprintf (Fis, "%c[%2d]=%4d\n", R, i, X [i++]); fclose (Fis); } }

Tarkime, faile c:\ktlg\pradf.txt buvo urayti tokie skaiiai:

fail c:\ktlg\kitf.txt i programa ives tokius duomenis:


A[ A[ A[ A[ 1] 2] 3] 4] = = = = 5 6 98 -5

5 6 98 -5

138

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

altiniai
[Sou06] [Vid02] Juan Soulie. C++ Language Tutorial. 2006. http://www.cplusplus.com/doc/tutorial/ A. Vidinas. C++ ir C++ Builder pradmenys. Smaltijos leidykla, 2002.

C++ [BBK+01] J.Blonskis, V.Buknaitis, J.Konien, D.Rubliauskas. praktikumas. Kauno technologijos universitetas. Praktins informatikos katedra. Kaunas, 2001.

139

Vilniaus universitetas, Matematikos ir informatikos fakultetas, Program sistem katedra Valdas Undznas. INFORMATIKA. Programavimas C++ kalba. Mokymo priemon, Vilnius 2009 ________________________________________________________________________________________________________________

Priedas. C++ standartins bibliotekos.


Tarptautinis ANSI-C++ standartas nustato C++ kalbos standartini bibliotek fail (header files) vard sudarymo taisykles, kurios kakiek skiriasi nuo anksiau naudot C kalboje: - standartini bibliotek fail varduose nebenaudojamas pltinys .h, kur turjo C kalbos standartini bibliotek failai, pvz., <stdio.h>, <stdlib.h>; - i C kalbos perimt standartini bibliotek fail vard priekyje raoma raid c, kad juos galtume atskirti nuo grynai C++ kalbos standartini bibliotek fail vard. Pvz., vietoje buvusio <stdio.h> dabar raoma <cstdio>; - visi standartinse bibliotekose esani klasi ir funkcij elementai apibrti namespace std vard srityje ir todl nra globals. Tai netaikoma C kalbos makrosams. C++ kalboje yra tokie nauji standartini bibliotek failai: <algorithm>, <bitset>, <deque>, <exception>, <fstream>, <functional>, <iomanip>, <ios>, <iosfwd>, <iostream>, <istream>, <iterator>, <limits>, <list>, <locale>, <map>, <memory>, <new>, <numeric>, <ostream>, <queue>, <set>, <sstream>, <stack>, <stdexcept>, <streambuf>, <string>, <typeinfo>, <utility>, <valarray>, <vector>. Standartini bibliotek failai, perimti i C kalbos: Failo vardas. ANSI-C++ standartas <cassert> <cctype> <cerrno> <cfloat> <ciso646> <climits> <clocale> <cmath> <csetjmp> <csignal> <cstdarg> <cstddef> <cstdio> <cstdlib> <cstring> <ctime> <cwchar> <cwtype> Failo vardas. ANSI-C standartas <assert.h> <ctype.h> <errno.h> <float.h> <iso646.h> <limits.h> <locale.h> <math.h> <setjmp.h> <signal.h> <stdarg.h> <stddef.h> <stdio.h> <stdlib.h> <string.h> <time.h> <wchar.h> <wtype.h>

140

You might also like