C programavimo kalbos ypatybės

2681 0

1. I-OJI PASKAITA: Pradinės pastabos

1.1. C programavimo kalbos ypatybės

• Gerai išvystyta aukšto lygio programavimo kalba.

• Dauguma (vos ne visos) komercinės programos parašytos būtent C arba C++ kalba. De facto tai pramoninių programų rašymo standartas

• Kada atsirado C kalba? 1969 metais išleista C kalbos pirma versija. Sukurta kaip sudėtinė UNIX operacinės sistemos dalis. Vėlesnės UNIX versijos parašytos C kalba

• Kodėl pavadinta C? Buvo dvi ankstesnės versijos – A ir B, bet jos buvo nevykusios. Iš trečio karto pasisekė sukurti pasisekusią programavimo kalbą. Todėl ir pavadinimas C.

• C – tai nepriklausoma nuo maašinos tipo procedūrinė programavimo kalba

• Koks skirtumas tarp C ir C++? C++ – tai objektinis procedūrinės programavimo kalbos C poaibis

• Kokias programas galima parašyti naudojant C/C++?

1.2. Programavimo kalbų klasifikacija

• Kas yra kalba ? Ar pvz. matematika kalba ?

• Kokios kalbos yra natūralios ir kokios dirbtinės ?

• Kodėl programos nerašomos natūralia kalba ? Kas nulėmė tokią programavimo kalbų struktūrą kokia yra dabar ?

• Žemo lygio programavimo kalbos:

• – mašininiai kodai

• – asembleriai (ypatybės ?)

• Aukšto lygio programavimo kalbos:

• -procedūrinės: Fortran, Pascal, C

• -interpretatoriai: Basic

• objektinės: C++, Java, Delphi (ypatybės ?)

1.3. Programavimo priemonių rinkinys

• Ką reikia turėti norint parašyti veikiančią programą ?

Trys pagrindiniai komponentai:

 Redaktorius – tam, kad parašyti programos išeities kodą. Tinka bet koks redaktorius (pvz. Microsoft Word), bet dažniausiai naudojami specializuoti

 Kompiliatorius – tam, kad parašytą programos kodą paversti į mašininius kodus, taip vadinamą objektinį modulį

 Linkeris – kad prie objektinio modulio prijungti kitus objektinius modulius, bi

ibliotekose surinktą kodą ir gauti vykdomąją programą.

• Šiuolaikinėse sistemose dažniausiai naudojamos integruotos sistemos, apjungiančios visus tris komponentus

• Vis dažniau naudojamas vizualinis programavimas. Tačiau sunkiausią dalį programuotojas vis tiek turi padaryti pats

1.4. C kalbos programavimo priemonės

Yra sukurta daug programavimo priemonių rašyti programas C kalba:

 Nemokamos: gcc kompiliatorius, Mars C, lcc ir t.t.

 Komercinės: Microsoft C, Borland C, Symantec C ir t.t.

 Įprastinės: Turbo C, Borland C, Symantec C

 Vizualinio programavimo: Microsoft Visual C, Borland C Builder

• Kurios geriausios ? Tos, prie kurių labiausiai esi pripratęs ir gali greičiausiai pasiekti reikiamą tikslą.

1.5. Programos leksika ir sintaksė

• Programą, parašytą C kalba, sudaro vienas arba keli failai

• Kiekvieną failą sudaro funkcijų ir kintamųjų bei veiksmų su jais aprašymas

• Leksiškai programa susideda iš bazinių arba raktinių žodžių (angl. keywords) specialių ženklų, identifikatorių, konstantų ir komentarų

• C kaalboje naudojamos tiek didžiosios, tiek mažosios raidės, tačiau yra priimta eilė neoficialių susitarimų, kurių pravartu laikytis

1.6. Kintamieji ir konstantos

• Duomenys, kuriuos apdoroja kompiuteris – tai konstantos ir kintamieji

• C kalboje visi kintamieji turi būti aiškiai aprašyti

• Kintamojo aprašymas – tai jo tipo specifikavimas, kintamojo vardo uždavimas, eilė neprivalomų modifikatorių, kurie apibrėžia vidines kintamojo vaizdavimo ypatybes arba jo saugojimo klasę.

• Aprašant kintamąjį galima nurodyti jo pradinę reikšmę

• Identifikatorius – tai seka raidžių arba skaičių, kurie prasideda raide arba pabraukimo ženklu _

• Kintamojo vardas – tai identifikatorius . Vardas gali būti bet ko

okio ilgio, bet tik pirmi 32 simboliai bus reikšminiai

1.7. Kintamųjų tipai

• Tipas – bet kuriai programavimo kalbai fundamentali sąvoka

• C kalboje skiriami 4 kategorijų tipai

• Tuščias tipas (void)

• Skaliarinis tipas:

– aritmetiniai tipai

– išvardijimai (enumerations)

– rodikliai (pointers)

– nuorodos (references)

• Tipas funkcija

• Agreguotas tipas:

– masyvai (arrays)

– struktūros ir sąjungos

– klasės (tik C++ poaibyje)

• Kitaip kintamieji gali būti skirstomi į :

– pagrindinius

– išvestinius

• Pagrindiniai tipai C kalboje yra:

void char int float double

ir jų variantai su raktiniais žodžiais

short long signed unsigned

• Išvestiniai tipai:

– rodikliai ir nuorodos į kitus duomenų tipus

– funkcijos

– struktūros ir sąjungos

– klasės

1.8. Duomenų tipas int

• C kalboje duomenų tipas int (integer, integral ?) savyje apjungia duomenų tipus char, short, long

• Pats duomenų tipas int yra bazinis ir priklauso nuo operacinės sistemos skiltiškumo: jo dydis lygus operacinės sistemos adresavimo skiltiškumui (16 bitų Win16, 32 bitai Win32, ateityje 64 bitai ?)



bitai min max

char 8 -128 127

unsigned char 8 0 255

short int 16 -32768 32767

int 16 -32768 32767

unsigned int 16 0 65535

long 32 -2147413648 2147483647

unsigned long 32 0 4294967295

1.9. Sveiko tipo konstantos

• Sveiko tipo (int) konstantos gali būti užrašomos dešimtaine, aštuntaine arba šešioliktaine sistema:

• 15,5,65,156,253

• 015,05,065,0156,0253

• 0x15,0x5,0x65,0x156,0x25af

• Dešimtainės konstantos paprastoje formoje suprantamos kaip short int kintamieji.

• Jeigu reikia užrašyti didesnius kintamuosius, reikia naudoti tipo modifikatorius U(u) – unsigned arba L(l) – long

• Pvz.: negalima rašyti 40156 , 1256789, -35674 ir t.t.

• Reikia rašyti 40156u, 1256789l, -35674l ir t.t.

• Galima naudoti tiek U ir L, tiek u ir l

1.10. Slankaus kablelio konstantos

• Sveikais tipais negalima aprašyti trupmeninių skaičių: reikia naudoti slankaus kablelio tipus

• C kalboje naudojami trys slankaus kablelio duomenų tipai: float, double, long double

bitai min max tikslumas

float 32 3,4*10-38 3.4*1038 7

double 64 1.7*10-308 1.7*10308 15

long double 80 3.4*10-4932 3.4*104932 19

1.11. Kintamųjų aprašymo pavyzdžiai

Keli kintamųjų aprašymo pavyzdžiai:

• int i;

• signed short a; unsigned short k;

;

• short a, b=125, abcd=0xabcd;

• unsigned char b1=156;

• float bb, c=0.0,z=1.e-5;

• double pi=3.1415928;

• long double c1; double _z1erw=123.4561;

1.12. Priėjimo modifikatoriai const ir volatile

• Neprivalomi modifikatoriai padeda apibrėžti kintamuosius, kurie programos vykdymo metu gali arba negali pakeisti savo reikšmes

• const – negali

• volatile – gali (naudojamas pagal nutylėjimą)



• Pvz: const int max_const=32767;

• Naudojama, kuomet norima apsidrausti, kad programos vykdymo metu netyčia nebūtų pakeista reikalinga kintamojo reikšmė

1.13. Komentarai

• C/ C++ kalboje komentarus galima įterpti dviem būdais:

1) /* ... */ – komentarai rašomi tarp slešo ir žvaigždės ir žvaigždės ir slešo. Komentarų kiekis neribojamas

2) // po dviejų slešų visa eilutė iki galo traktuojama kaip komentarai

Pvz. /* aš čia dabar rašau komentarus

kiek noriu tiek rašau. ir čia komentaras int a/c;

dabar baigiu */

int a; // o dabar komentarai , int a – čia irgi komentaras

1.14. Gero stiliaus reikalavimai

Naudoti prasmingus pavadinimus globaliniams kintamiesiems ir trumpus pavadinimus – lokaliniams

Patartina globalinių kintamųjų aprašymus paydėti trumpu komentaru

• Pvz: int npending=0; // ivedimo srauto einamas ilgis

• Pvz: numberOfPoints – globalinis kintamasis

• nPoints – tiek globalinis, tiek lokalinis

• n –lokalinis kintamasis

Egzistuoja daug susitarimų ir vietinių tradicijų kaip reikėtų parinkti pavadinimus kintamiesiems įvairiose sistemose ir uždaviniuose

• Būkite nuoseklūs: panašios kilmės objektams reikėtų parinkti atitinkamus pavadinimus, parodančius jų panašumus ir skirtumus

• Būkite tikslūs: vardas reiškia ne tik objektą, bet ir jo prasmę !!!

1.15. Operacijos ir išraiškos

Išraiška – tai seka operandų, operacijų ir skiriamųjų ženklų.

Skiriamieji simboliai: [ ] { } , ; : . * = #

Išraiškas kompiliatorius interpretuoja griežtai besilaikydamas vyresniškumo taisyklių

Vyresniškumo taisyklės kaip matematikoje priimtos

1.16. Pagrindinės operacijos: aritmetinės op

peracijos

Tipinės operacijos:

• Sumavimo operacija +

• Atėmimo operacija –

• Daugybos operacija *

• Dalybos operacija /

C kalbos specifinės operacijos:

• Liekanos nustatymo operacija %

• Inkremento operacija ++

• Dekremento operacija —

1.17. Pagrindinės operacijos: poskiltinės loginės operacijos

• Vadinamos poskiltinėmis todėl, kad loginiai veiksmai atliekami su kiekviena kintamojo arba konstantos skiltimi atskirai

• Yra keturios:

• & – loginis IR (AND operacija)

• ^ – poskiltinis sumavimas moduliu 2 (XOR operacija)

• | – loginis ARBA (OR operacija)

• ~ poskiltinė inversija

1 operandas 2 operandas AND OR XOR

0 0 0 0 0

1 0 0 1 1

0 1 0 1 1

1 1 1 1 0

1.18. Pagrindinės operacijos: postūmio operacijos

• Poskiltinio postūmio operacijos:

>> – postūmis dešinėn

<< – postūmis kairėn

Pvz: half = addr>>1;

double = addr<<1;

Pvz: 5 – > 101 <<1 -> 1010 -> 10

12 -> 1100>>1 -> 110 -> 6

3 -> 11 <<3 -> 11000 -> 24

Priskyrimo operacija =. Pvz. a=b;

1.19. Pagrindinės operacijos: loginės operacijos ir santykio operacijos

Santykio operacijos:

• > – daugiau

• < – mažiau

• == – tapačiai lygu

• >= – daugiau arba lygu

• <= – mažiau arba lygu

• != – nelygu

• Teisinga, jei operandas iš kairės tenkina sąlygą

Loginės operacijos:

• && – loginis IR

• || – loginis ARBA

• ! – loginis NE

• Šios operacijos naudojamos sudarant logines išraiškas, turinčias tik dvi reikšmes: 1, jei išraiška teisinga ir 0, jei išraiška neteisinga

1.20. Sąlygos operacija ? :

• Sąlygos operacija ? : apibrėžiama kaip:

cond ? TRUE_statement : FALSE_statement

• Pvz:

int a=4, b=3;

int i;

i=a>b ? a: b;

1.21. Duomenų tipų nurodymo operacija (kastingavimas)

• C kalboje duomenų tipus (operandų tipus) galima nurodyti aiškiai

• Toje operacijoje kintamasis bus traktuojamas kaip nurodyta privedimo operacijoje

• C++ operuojant su skirtingo tipo operandais duomenų tipus būtina kastinguoti

• Kintamasis įgis nurodytą tipą tik duotoje operacijoje;

pvz.: int a=8,b=5;

float var1,var2;

var1=a/b; // var1=1.0;

var2=(float)a/b; // var2=1.6;

var2=(float)a/(float)b; // var2=1.6;

1.22. Mnimali programa C kalba

• int main() { }

• int main()

{

}

• int main(

)

{}

Pastabos: failo pavadinimas baigiasi plėtiniu .c arba .cpp

Tarpus kompiliatorius ignoruoja

Orientuotas į leksemas, o ne pozicijas faile

1.23. Pirmos programos pavyzdys

#include

int main() {

unsigned int count;

count=1;

printf(“Hello world !!! n count=%d”,count ); }

Rezultatas: Hello world !!! count=1

2. II-OJI PASKAITA

2.1. Bazinio įvedimo/ išvedimo metodai

• Skirtingi metodai naudojami konsoliniame įvedime/išvedime ir programose su langais

• Čia kalbame apie konsolinį I/O

• C++ turi savus operatorius, C specialių operatorių neturi

• Naudojamos bibliotekinės funkcijos

• Kas yra biblioteka, kas yra funkcija ?

• Standartinė įvedimo / išvedimo biblioteka:

• #include

• Konsolinio įvedimo / išvedimo biblioteka

• # include

2.2. Formatuotas išvedimas

• Pavadinimas: printf()

• Sinopsė:

• #include

• int printf(const format[,arg].)

• Aprašymas: į standartinį išvedimo įrenginį (koks įrenginys yra standartinis ?) išveda nurodytą duomenų srautą, sutinkamai su nurodytu formatu format: tai gali būti literaliniai simboliai ir transformavimo specifikatoriai:

• %d – dešimtainis sveikas skaičius

• %f – slankaus kablelio skaičius

• %o – aštuntainis skaičius be ženklo

• %x – šešioliktainis skaičius be ženklo

2.3. Formatuotas išvedimas

• Pavadinimas: printf()

• Sinopsė:

• #include

• int printf(const format[,arg].)

• Aprašymas: į standartinį išvedimo įrenginį (koks įrenginys yra standartinis ?) išveda nurodytą duomenų srautą, sutinkamai su nurodytu formatu format: tai gali būti literaliniai simboliai ir transformavimo specifikatoriai:

• %d – dešimtainis sveikas skaičius

• %f – slankaus kablelio skaičius

• %o – aštuntainis skaičius be ženklo

• %x – šešioliktainis skaičius be ženklo

Pavyzdžiai:

• printf(“iveskite varda:”);

• printf(“turimas akciju skaicius %dn”,num);

• printf(“n sio menesio %2d diena nupirkta %3d akcijun”,diena, num);

• printf(“vieneto kaina %f”, kaina);

• printf(“vieneto kaina %4.2f bendra kaina %6.2fn”,kaina, total);

• printf(“vienetu skaicius %d vieneto kaina %4.2d bendra kaina %6.2fn”,kiekis, kaina, total);

• printf(“ | vienetu skaicius %d vieneto kaina %4.2d bendra kaina %6.2f | n”,kiekis, kaina, total);

2.4. Konsolinis įvedimas

• Pavadinimas: scanf()

• Sinopsė:

• #include

• int scanf(const format[,arg].)

• Aprašymas: iš standartinio įvedimo įrenginio (koks įrenginys yra standartinis ?) nuskaito nurodytą duomenų srautą, sutinkamai su nurodytu formatu format:

• %d – dešimtainis sveikas skaičius

• %f – slankaus kablelio skaičius

• %o – aštuntainis skaičius be ženklo

• %x – šešioliktainis skaičius be ženklo

• %c – simbolis

• scanf(“%d”, &num);

• scanf(“%f”,&price);

• scanf(“%d %d”,&diena, &num);

• scanf(“%4.2f %6.2f”,&kaina, &total);

• scanf(“%d %f %f”,&kiekis, &kaina, &total);

• scanf(“%c”,&raide);

• scanf(“%d”,a[i]);

• scanf(“%s” pavadin);

2.5. Simbolinis įvedimas/ išvedimas

• Pavadinimas: getchar – įvedimo funkcija

• Sinopsė:

• #include

• int getchar(void)

Aprašymas: nuskaito ir gražina eilinį simbolį iš standartinio nuskaitymo įrenginio

Diagnostika: gražina EOF simbolį, jeigu pasiektas failo galas arba klaidos simbolį, įvykus įvedimo klaidai. Visais kitais atvejais gražina nuskaitytą simbolį

• Pavadinimas: putchar – išvedimo funkcija

• Sinopsė:

• #include

• int putchar(int c)

Aprašymas: išveda eilinį simbolį į standartinį išvedimo įrenginį

Diagnostika: gražina išvestą simbolį, jeigu išvedimas atliktas sėkmingai, priešingu atveju gražina EOF simbolį.

• Pavyzdžiai

#include

int main() {

int c;

c=getchar(); /* nuskaito simboli ir priskiria ji kintamajam c */

putchar(c);

putchar(‘m’);

putchar(‘t’);

putchar(‘07’);

}

2.6. Skaičiavimo proceso valdymo operatoriai

• Skaičiavimo procesas – tai programos operatorių vykdymo seka

• Paprastai programos operatoriai vykdomi elės tvarka: iš viršaus į apačią, iš kairės į dešinę

• Kartais normalią veiksmų vykdymo seką reikia pakeisti

• Kam reikia pakeisti valdymo seką ? Uždavinio sprendimas reikalauja

• Naudojami specialūs operatoriai – skaičiavimo proceso valdymo operatoriai

• Šakojimosi operatoriai, sąlygos operatoriai, ciklo operatoriai

• if, if-else, while, do while, switch – case – break, for, break, continue, goto, return

2.7. Operatorius if

• Šakojimosi operatoriai išrenka programoje galimą proceso tąsą iš eilės alternatyvų

• C kalboje yra du šakojimosi operatoriai – if ir switch

• if – paprasčiausias sąlygos operatorius

• if operatoriaus apibrėžimas:

if(cond_expression) TRUE_statement;

• cond_expession – sąlygos išraiška

• TRUE_statement – išraiška, kuri vykdoma jei sąlyga teisinga

• Pavyzdžiai:

• if(x>largest) largest=x;

• if( valmax) {

printf(“reiksme %d iseina uz leidziamo diapazono ribun”,val);

printf(“leidziamas diapazonas %d %dn”, min, max); }

• if(num<0) num=-num;

• c=getchar();

if(c==‘n’) lines+=1;

• ekvivalentinis if((c=getchar()) ==‘n’) lines+=1;

• neekvivaletinis if(c=getchar()==‘n’) lines+=1;

2.8. Operatorius if-else

if ir else – raktiniai žodžiai

• Jeigu išraiška teisinga – vykdoma pirmoji išraiška, jeigu išraiška neteisinga – pirmoji išraiška praleidžiama ir vykdoma antroji išraiška

• Tiek pirmoji, tiek antroji išraiškos gali būti paprastos arba blokinės

• Apibrėžimas:

• if(cond_expression) True_statement;

else False_statement;

• cond_expession – sąlygos išraiška

• TRUE_statement – išraiška, kuri vykdoma jei sąlyga teisinga

• FALSE_statement – išraiška, kuri vykdoma, jei sąlyga neteisinga

Pavyzdžiai

• if(kiekis<100) printf(“atsargu kiekis mazas”);

else printf(“atsargu kiekis pakankamas”);

• if(x!=0)

y=y/x;

else {

printf(“klaida: dalyba is nulio”);

y=0; }

• if(hour>=3 && hour<17)

rate*=1.02;

else if(hour>=17 && hour<23)

rate*=1.01;

else rate*=0.99;

Pastaba: operatoriai if-else yra inkliuzyviniai: į vieną if-else operatorių galima įstatyti kitą.

Inkliuzyvų kiekis neribojamas

2.9. Else atskyrimo problemos: klaidų šaltinis

• if(c>’ ‘)

if(c>=‘0’ && c<=‘9’)

digits+=1;

else

count+=1;

• Kuriam if priskiriamas else ?

• if(c>’ ‘)

{

if(c>=‘0’ && c<=‘9’)

digits+=1;

}

else

count+=1;

2.10. Operatoriai switch-case- break

• Dažnai pasitaikantis programavimo uždavinys: išrinkti vieną alternatyvą iš daugelio galimų variantų

• Tai patogu atlikti naudojant switch-case operatorių

• Operatoriaus sintaksė:

switch(switch_expression) {

case const1: statement1; [break;]

case const2: statement2; [break;]

..

case constn: statementn; [break;]

[default: statemnt n+1;]

}

• Iliustracija

• input=getchar();

switch(input) {

case ‘d’: z=z*5;

case ‘a’:

case ‘A’: z-=1; break;

case ‘p’:

case ‘P’: z+=1; break;

default: printf(“neteisingas pasirinkimasn”);

break;

}

2.11. Ciklo operatoriai

• Ciklas – tai tų pačių veiksmų pakartojimas nurodytą skaičių kartų

• C kalba turi tris ciklo užrašymo formas:

• while(cond_expression) operators;

• do operators while(cond_expression);

• for(init_expr; cond_expr; incr_expr) operators;

• Kuri užrašymo forma geriausia ? Priklauso nuo konkrečių sąlygų

• Visomis užrašymo formomis galima užrašyti bet kurį ciklą

2.12. Besąlyginio perėjimo operatoriai

• Yra keturi besąlyginio perėjimo operatoriai C kalboje: break, continue, goto, return

• Besąlyginio perėjimo operatoriai – sutikus tokį operatorių programos valdymas automatiškai perduodamas į apibrėžtą vietą

• break – išeina iš duoto bloko ir tęsia vykdymą iš karto nuo sekančio operatoriaus už bloko

• continue – naudojamas cikle, automatiškai pereina prie sekančios ciklo iteracijos

• return – grįžta iš funkcijos. valdymas perduodamas į funkcijos iškvietimo tašką

• goto label – valdymas automatiškai perduodamas į programos tašką, kurį žymi markeris label

2.13. Gero stiliaus reikalavimai

1) Formatuokite kodą taip, kad pabrėžti jo struktūrą

• Blogas formatavimas:

for(n++;n<100;n++) field[n++]=‘’;

*i=‘’; return(‘n’);

• Geras formatavimas:

for(n++;n<100;n++)

field[n++]=‘’;

*i=‘’;

return ‘n’;

2) rašykite išraiškas natūralia forma: rašykite taip, kaip skaitytumėte

• Blogai:

if(!(block_id=unblock))

• Gerai:

if((block_id>=actblk) || (block_id>(bitoff>>3)<<3));

• Gerai: subkey=subkey>>(bitoff&0x7));

subkey>>=bitoff&0x7;

Absoliučiai mįslinga konstrukcija:

child=(!LC&&!RC)?0:!(LC?RC:LC);

Paprastai: if(LC==0 && RC==0)

child=0;

else if(LC==0)

child=RC;

else

child=LC;

6) Būkite atsargūs u pašaliniais efektais: ++ tipo operacijos turi pašalinius efektus: jos ne tik gražina reikšmę, bet ir pakeičia operando reikšmę

• Blogai: str[i++]=str[i++]=‘A’;

(blogai, nes nėra apibrėžta ++ operacijos vykdymo tvarka)

• Gerai: str[i++]=‘A’;

• str[i++]=‘A’;

3. III-IOJI PASKAITA: Rodikliai. Nuorodos. Masyvai.

3.1. Rodiklio sąvoka

• Idėja panaudoti adresus – labai sena.

• Programose rašomose mašininiais kodais arba asembleriu dažnai sutinkamas uždavinys – perkelti duomenis iš vieno adreso į kitą

• Tokiose programose tai atliekama paprastai

• Aukšto lygio programavimo kalbose dažnai apie adresus negalvojama, o kai kuriose ir nėra jokių priemonių operuoti su adresais

• C kalboje yra abiejų būdų komponentų: tiek darbui su adresais, tiek ir ne tiesioginio adresavimo galimybių

• Kas yra rodiklis? Kintamasis, kuriame saugomas adresas

• Apibrėžimas: kntamasis-rodiklis (arba tiesiog vadinama rodikliu) – ta kintamasis, skirtas adreso saugojimui atmintyje

• Kam naudojami rodikliai?

 Kad efektyviai prieiti prie duomenų

 Lanksčios programos parašymui

 Kintamųjų, perduodamų į funkciją, reikšmių pakeitimui

 Darbui su dinamiškai paskirstoma atmintimi

 Priėjimui prie aparatinių kompiuterio resursų arba papildomų įrenginių

3.2. Rodikliai ir nuorodos C kalboje

• C kalboje apibrėžtos dvi specialios operacijos kintamųjų adresavimui per rodiklius

o operacija & – nuorodos (reference) operacija

o operacija * – rodiklio (pointer) operacija

Operacijos & rezultatas – tai objekto, kuriam taikoma i operacija, adresas

Operacija * – tai kreipinys į atminties ląstelę, kurios adresas saugomas tame objekte

3.3. Rodiklių aprašymas, inicializavimas ir naudojimas

• Kintamasis p aprašomas kaip rodiklis į sveiko tipo kintamąjį. Tai reiškia kad jame bus saugomas sveiko tipo kintamojo adresas

• int num1=3, num2=6, *p;

• Visi rodikliai turi būti inicializuoti

• p=&num1;

• Rodiklis p dabar “rodys” į kintamąjį num1

• Dabar kintamąjį num1 bus galima adresuoti tiesiogiai, naudojant priskyrimo operaciją = , arba kaip rodiklį, naudojant operatorių *

3.4. Dar apie rodiklius

• Svarbu prisiminti, kad ženklas * – tai operatorius

• Kuomet jis naudojamas su dviem operandais (binarinis operatorius) – tai daugybos operatorius

• Kuomet jis naudojamas kaip unarinis operatorius – laikoma, kad tai rodiklis, nurodantis į ženklą

• Negalima sumaišyti

• Sudėtingose išraiškose kartais gali būti painu suprasti kaip reikia perskaityti

• Pvz: p= a* *b *c **d;

3.5. Pratimai su rodikliais: operacijos & ir *

• Kas neteisinga žemiau pateiktoje programoje

#iclude

int main() }{

int num1=100, *p;

printf(“num1 is %dn”,num1);

printf(“*p is %dn”,*p);

}

Ar tokia programa bus sukompiliuota?

Ar bus įvykdyta ?

Kas bus išspausdinta ?

3.6. Rodiklių aritmetika

• Svarbu aprašant rodiklius su teisingu duomenų tipu

• Naudojama padidinant / sumažinant rodiklio reikšmę, palyginant rodiklius tarpusavyje, atimant vieną rodiklį iš kito ir pan

• char *p;

• *p – tai simbolis

• p++ ekvivalentiška p=p+1

• short *p;

• *p – tai trumpas sveikas skaičius

• p++ – ekvivalentiška p=p+2

3.7. Masyvai

• Masyvas – tai eilės tvarka, vienas paskui kitą, atmintyje išdėstyti vieno ir to paties tipo elementai.

• Kiekvienas masyvas turi nuosavą unikalų pavadinimą

• Priėjimas prie masyvo elementų atliekamas naudojant masyvo pavadinimą ir elemento eilės numerį

• Pagrindinis masyvo privalumas: leidžia saugoti aibę elementų, aiškiai nenurodant kiekvieno iš elementų pavadinimų

• Masyvai gali būti vienmačiai arba daugiamačiai (dvimačiai, trimačiai, ir t.t. Kada pabaiga ?)

• Masyvo požymis – kvadratinių skliaustelių buvimas šalia pavadinimo: char buffer[256]; int a[3]; ir t.t.

• Pagrindinės masyvų savybės C kalboje:

1) Visi masyvo elementai yra vieno ir to paties tipo

2) Aprašant masyvą nurodomas jo elementų tipas, masyvo pavadinimas ir bendras masyvo elementų skaičius

3) Pirmo masyvo elemento indeksas visada yra lygus 0, paskutinio n-1

4) Masyvo elementai į atmintį surašomi nuosekliai (pvz. 3 elementas atmintyje visada bus po 2)

5) Dvimačiai masyvai surašomi eilutėmis: pirmiausia pirmos eilutės elementai, po to antros ir t.t.

• Masyvo vardas yra rodiklis-konstantė (tiesiog rodiklis) ir visada lygus masyvo pradžios adresui

3.8. Masyvo inicializavimo būdai

• C kalboje numatyti du masyvų inicializavimo būdai:

• Inicializavimas pagal nutylėjimą: taikomas tik statiniams arba išoriniams masyvams

• Tiesioginė elementų inicializacija:

• char array[10]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’,’i’,’j’};

• char array[]={1,2,3,4,5};

• char array[5]; array[0]=1; array[1]=2; array[2]=3;

• char array[10]; int i; for(i=0;i<10;i++) array[i]=i;

3.9. Nuorodos į masyvo elementus

• Darbas su atskirais masyvo elementais arba indekso, arba operacijos * pagalba

• Abu darbo su masyvo elementais būdai yra lygiaverčiai

• Naudojant indeksus

• masyvo_vardas[sveikaskaitinė_išraiška]

• Short a[15]; a[0]=5; a[2]=7; a[5]=a[0]+a[2]; a[7]=a[5];

• Naudojant rodiklius:

• short a[15]; *a=5; *(a+2)=7; *(a+5)=*a+*(a+2); *(a+7)=*(a+5);

3.10. Daugiamačiai masyvai

• C kalba palaiko ir daugiamačius masyvus

• Masyvo matiškumas – tai indeksų, naudojamų adresuojant masyvo elementą, skaičius

• Daugiamačių masyvų elementai saugomi atmintyje dešiniausio indekso didėjimo tvarka

• Dvimačio masyvo vardas yra rodiklis į rodiklių masyvą. Masyvo elementai yra rodikliai į kiekvienos eilutės pradžios elemento adresą

• Matiškumų skaičius nėra ribojamas, praktiškai niekada nenaudojami didesni nei trimačiai masyvai

3.11. Programos su masyvais pavyzdys

#include

int main() {

const float investment=6000, interest=.085;

float rate; double value[5];

int year;

rate=1+interest; value[0]=investment; year=1;

while(year<5) {

value[year]=value[year-1]*rate;

year+=1; }

printf(“pradinis indelis %.2fn”,value[0]);

year=1;

while(year<5) {

printf(“metai %d: %.2fn”,year,value[year]);

year+=1; } }

3.12. Kelios pastabos apie masyvus

• C kalboje nėra atliekamas joks masyvų adresavimo korektiškumas

• Tai dažna klaidų priežastis: adresuoti į tuos masyvų elementus, kurių pagal pradinį masyvo aprašymą paprasčiausiai nėra

• Viena iš daugiamačių masyvų reto naudojimo priežasčių – didesnis adresavimo sudėtingumas ir didesnė klaidų tikimybė

short a[30]; for(i=0;i<30;i++) a[i]=i*i; //gerai

a[30]=a[29]; // blogai , tik 30 elementu galima

a[7*7]=a[5*5] // blogai

Visa atsakomybė už indeksų naudojimo teisingumą išimtinai priklauso programos autoriui

Jei adresuojama į masyvo elementą su didesniu indeksu, programa nulūžta

3.13. Masyvų kopijavimas

• Masyvai turi būti kopijuojami elementas po elemento

• Int prev[20],current[20];

• Neteisingai:

prev=current; // kompiliavimo klaida

• Teisingai:

i=0;

while(i<20) {

prev[i]=current[i];

i+=1; }

3.14. Inkremento ir dekremento operatoriai masyvuose

• Dėl savo patogumo ir efektyvumo inkremento/ dekremento operatoriai dažnai naudojami veiksmuose su masyvais

• Prefiksinė forma ++x, –x; postfiksinė forma x++,x—

• Prefiksinė forma – reikšmė pakeičiama nedelsiant, postfiksinė – reikšmė pakeičiama atlikus kitus veiksmus

• x=3; y=++x; // y? x?

• x=3; y=x++; // y? x?

• Pvz:

i=0; i=0;

while( while(i

• Keli pavyzdžiai:

• strcpy(src,dest) – perkopijuoti vieną eilutę į kitą

• strcmp(src,dest) – palyginti vieną eilutę su kita

• strcat(str1,str2) – prijungti vieną eilutę prie kitos

• Ir dar daug kitų funkcijų

Pavyzdys su stringais

#include

int main() {

int i;

char first[11];

printf(“prasau ivesti varda:”);

i=0;

while(i<10 && (first[i]=getchar()) !=‘n’)

i+=1;

first[i]=‘’;

printf(“ivestas vardas: %sn”,first);

}

3.18. Masyvai kaip rodikliai

• Masyvų aprašymas su kvadratiniais skliausteliais paprastas ir patogus būdas tačiau turi trūkumų:

• Negalima rezervuoti didelių masyvų (didesnių negu 32676 elementai)

• Masyvo dydį reikia nurodyti iš karto ir negalima vėliau jo keisti (dažnai nelengva iškarto nustatyti kokio dydžio masyvo mums reikės)

• Yra antras masyvų aprašymo būdas, neturintis tokių apribojimų – masyvų aprašymas per rodiklius:

• Pvz: short *a; long *b;

Tačiau kol kas neužduotas masyvo dydis. Tą būtina padaryti !!!

3.19. Masyvų dydžio nurodymas

• Naudojamos standartinės funkcijos, aprašytos header faile alloc.h:

• #include

• Atminties rezervavimui naudojamos funkcijos malloc() ir farmalloc(), atminties atlaisvinimui naudojamos funkcijos free() ir farfree().

• Atmintį atlaisvinti būtina, kai ji nėra reikalinga

• Reikalingos atminties dydis šiose funkcijose visada užduodamas baitais . Todėl reikia pačiam apskaičiuoti reikalingą baitų skaičių arba pasinaudoti komanda sizeof()

Masyvų dydžio nurodymo pavyzdys

• Reikia 100 elementų trumpų skaičių masyvo ir 300 elementų slankaus kablelio skaičių masyvo

• Pvz:

#include

int main() {

short *a;

float *b;

a=malloc(200); // nes kiekvienas short tipo elementas 2 baitai

a=malloc(100*sizeof(short)); // arba taip

b=farmalloc(1200); // nes kiekvienas float elementas 4 baitai

b=farmalloc(300*sizeof(float)) // arba taip

..

free(a); farfree(b); }

3.20. Dinaminiai masyvai

• Aprašant masyvus kaip rodiklius galima pakeisti masyvui išskirtos atminties kiekį programos vykdymo metu

• Tam dažniausiai naudojamos funkcijos realloc() arba farrealloc();

• Dydis ir vėl nurodomas baitais

• Pvz: short *a;

a=malloc(10);

a=realloc(a,20);

• Pastaba: nepriklausomai nuo masyvo aprašymo būdo, masyvo elementus galima adresuoti abiem anksčiau nurodytais būdais

4. IV-OJI PASKAITA: Funkcijos.

4.1. Bendros sąvokos apie funkcijas

• Kas yra funkcija ?

• Vieną funkcijos sąvoką žinote iš matematikos. Ką reiškia funkcija matematikoje ?

• Programavime funkcija turi panašumų, bet turi ir daug esminių skirtumų

• Sąvoka paprogramė (subroutine) naudota daugelyje ankstyvųjų programavimo kalbų (pvz. Fortran, PL/1, Cobol ir t.t.)

• Paprogramė – tai programos dalis , gebanti atlikti analogiškus veiksmus su skirtingais kintamaisiais

• Funkcija kiek platesnė sąvoka nei paprogramė

4.2. Funkcijos apibrėžimas

• Egzistuoja keletas funkcijos apibrėžimų

• Funkcija – tai operatorių grupė, atliekančių išbaigtą veiksmų seką. Į funkciją galimą kreiptis pagal pavadinimą, perduoti jai argumentus ir gauti iš jos reikšmę

• Funkcija – tai logikai savarankiška programos dalis, turinti savo pavadinimą, kuriai gali būti perduodami parametrai ir kuri gali gražinti reikšmę

• Pirmas apbrėžimas techniškesnis, antras – labiau atspindintis reikalo turinį

4.3. Funkcijos

• C kalba parašyta programa – tai iš esmės funkcijų rinkinys. Funkcijos išdėstytos bet kuria tvarka. Faktiškai funkcijos gali būti išdėstytos keliuose failuose.

• C kalbos koncepcijoje numatyti visi paprogramių tipai: funkcijos ir procedūros

• Funkcijos leidžia rašyti programą moduliniu būdu: kiekviena funkcija atlieką tam tikrą uždavinį. Tokias programas žymiai lengviau skaityti

• Funkcijos leidžia išvengti analogiškų veiksmų dubliavimo

• Daugelis programų gali naudoti tas pačias funkcijas, todėl nereikia perrašinėti kiekvieną kartą.

4.4. Funkcijos aprašymas

Funkcijos aprašymo standartas atrodo taip:

• [duomenu_tipas] funkcijos_vardas(argumentu_sarasas) {

kintamuju aprasymai;

... // funkcijos_kunas

operatoriai;

[return (israiska)];

}

[] – skliausteliuose pateikti neprivalomi funkcijos elementai

4.5. Funkcijos aprašymo paaiškinimas

• Laukas “duomenų tipas” nurodo funkcijos gražinamos reikšmės tipą jeigu jis nėra nurodytas, pagal nutylėjimą laikoma, kad funkcija gražina int tipo reikšmę. Jeigu lauke “duomenų tipas” nurodytas raktinis žodis void, tuomet funkcija negražina jokios reikšmės.

• Laukas “funkcijos pavadinimas” – tai ypatingas rodiklio tipas, vadinamas rodikliu į funkciją. Jo reikšmė yra lygi įėjimo į funkciją pradžios adresui. Funkcijos pavadinimas be to yra identifikatorius ir sudaromas pagal identifikatoriams C kalboje keliamus reikalavimus.

• Laukas “argumentų sąrašas” apibrėžia argumentus (kartais vadinami parametrais), perduodamus į funkciją. Argumentų sąrašas gali būti sudarytas iš bet kokios duomenų tipų jų vardų kombinacijos. Argumentų skaičius neribojamas. Argumentai tarpusavyje skiriami kableliais. Jeigu argumentai nenaudojami, sąraše rašomas žodis void

4.6. Funkcijos prototipas

• C kalbos standartas reikalauja, kad dar iki pirmo funkcijos iškvietimo programoje būtų pateiktas funkcijos apibrėžimas

• Toks pirminis funkcijos apibrėžimas vadinamas funkcijos prototipu.

• Prototipas praneša kompiliatoriui apie gražinamos reikšmės tipą, argumentų kiekį ir tipus.

• Po prototipo dedamas kabliataškis;

• Dažnai prototipai talpinami į atskirus failus, turinčius plėtinį .h ir vadinamus header-failais

• Standartinių funkcijų prototipai pateikti header failuose, kurie įtraukiami su direktyva include

4.7. Pirmas funkcijos pavyzdys

• Užduotis: apskaičiuoti skritulio plotą, kai spindulys r=5,10,27

• Galima taip:

void main() {

int r1=5,r2=10,r3=27;

float s1,s2,s3;

s1=3.14159*r1*r1;

s2=3.14159*r2*r2;

s3=3.14159*r3*r3;

}

Funkcijos nenaudojamos

4.8. Formalūs ir aktualūs argumentai

• Kuomet aprašome funkcijos kūną, nurodome argumentų, kurie turėtų būti perduoti į funkciją, sąrašą.

• Šie argumentai vadinami formaliais, su jais veiksmai programos vykdymo metu nebus atliekami

• Kuomet iškviečiame funkciją, nurodome į funkciją perduodamų argumentų sąrašą.

• Šie argumentai (tiksliau – jų kopijos) programos vykdymo metu bus perduoti į funkciją ir su jais atliekami veiksmai. Jie vadinami aktualiais argumentais.

• Privalo sutapti formalių ir aktualių argumentų tipai.

• Kompiliatorius pasirūpins, kad atitinkamas aktualus argumentas atsidurtų atitinkamo formalaus argumento vietoje.

4.9. Funkcijos iškvietimas

• funkcijos_vardas(argumentų sąrašas)

• Vykdymas perduodamas į funkciją

• Atliekami eilės tvarka funkcijos kūne aprašyti veiksmai

• Įvykdžius sugrįžtama į sekančią po funkcijos iškvietimo einančią operaciją

void intro(void);

int main() {

..

intro();

...

}

void intro(void) {

printf(“pradedamas programos vykdymasn”);

printf(“programos autorius jonukasn”” }

4.10. Funkcijos argumentai

• Naudojami informacijos perdavimui į funkciją

• Į funkciją perduodamos reikšmės, o ne patys kintamieji

• Yra lokaliniai funkcijos kintamieji

• Iškviečiant funkciją reikia nurodyti tikslų jų skaičių, tipus, ir eilės tvarką

int main() {

float amount=250, interest=0.075;

print_growth(amount,interest);

printf(main: amount= %.2fn”,amount);

}

void print_growth(float val,float rate) {

val=1+rate)*val;

}

4.11. Tipų kastingavimas funkcijose

• Tipų kastingavimas naudojamas laikinam duomenų tipo pakeitimui

• Naudojamas aiškiam teisingo funkcijos tipo nurodymui

float func(float x);

void func1(int x);

int man() {

int x;

func((float)x);

funcą(x);

}

4.12. Duomenų perdavimas į funkciją

• Parametrų perdavimui į funkciją egzistuoja du stiliai:

1) funkcijų iškvietimas su reikšmių perdavimu (call-by-value);

2) funkcijų iškvietimas su kintamųjų adresų perdavimu (call-by-reference);

• Iškvietimas su reikšmių perdavimu – tai kintamųjų reikšmių kopijų perdavimas į funkcijos kūną. Tai niekaip neleidžia pakeisti kintamųjų reikšmes iškvietimo taške

• Iškvietimas su adresų perdavimu – tai kintamųjų adresų kopijų perdavimas į funkcijos kūną. Tokiu būdu mes galime keisti reikšmes saugomas nurodytais adresais

4.13. Kintamųjų reikšmių perdavimo pavyzdys

void suma(int a,int b,int suma);

void main() {

int a=5,b=7,sum=5;

printf(“sum=%dn”,sum);

suma(a,b,sum);

printf(“sum=%dn”,sum);

}

void suma(int a,int b,int suma) {

suma=a+b;

}

void suma(int a,int b,int suma);

void main() {

int a=5,b=7,sum=5;

printf(“sum=%dn”,sum);

suma(&a,&b,∑);

printf(“sum=%dn”,sum);

}

void suma(int *a,int *b,int *suma) {

*suma=*a+*b;

}

4.14. Keli pavyzdžiai

• Kas neteisinga šiame funkcijos aprašyme ?

int compute(int , int ){

int x;

double y;

... }

Kas bus išspausdinta įvykdžius sekančią programą ?

void square(int val);

int main() {

int x=5;

square(x);

printf(“x lygu %dn”,x);

}

void square(int val) {

val=val*val:

printf(“%dn”,val); }

4.15. Steko reikšmė

• Stekas – ta atminties sritis, kurią vykdanti programa naudojama laikinam saugojimui;

• Kuomet iškviečiama funkcija, visi šios funkcijos argumentai patalpinami į steką, po to patalpinamos esamų registrų reikšmės ir kiti parametrai

• Toks argumentų, registrų ir automatinių kintamųjų rinkinys, skirtas vienai funkcijai, vadinamas freimu.

• Jei iškviesta funkcija viduje iškviečią dar vieną funkciją, tai jai sukuriamas dar vienas freimas ir anksčiau steke buvę parametrai perstumiami tolyn

• C kalba parašytoms programoms reikia daug steko, neretai stekas persipildo ir dėl to gali “nulūžti” programa

4.16. Operatorius return

• Gražina reikšmę į iškviečiančią funkciją return išraiška;

• Nėra privalomas operatorius

• Negražina jokios reikšmės jeigu naudojama išraiška

return;

int main(){

int len=50, width=4, area;

area=area_rect(len,width);

printf(“plotas lygus %dn”,area);

return 0; }

int area_rect(int l, in w) {

return l*w; }

4.17. Masyvai kaip funkcijos argumentai

• Į funkcija neperduodama viso masyvo kopija

• Perduodamas tik pirmo elemento adresas

• Per šį adresą funkcija gali prieiti prie masyvo elementų, juos modifikuoti.

void main() {

char current[30], target[0];

.

stringcopy(target,current);

. }

void stringcopy(char str1[], char str2[]) {

int i;

for(i=0; str2[i]!=‘’;i++) str1[i]=str2[i];

str1[i]=‘’;

}

4.18. Vienmačių masyvų perdavimas į funkciją

• Duoti du sveikų skaičių masyvai. Rasti kuriame iš jų yra daugiau teigiamų skaičių

• int n_posit(const int *a, const int n) {

int main() {

int i,n;

int a[50], b[50];

printf(“iveskite elementu skaiciu:”);

scanf(“%d”,&n);

printf(“iveskite elementus:”);

for(i=0;in_posit(b,n)

printf(“pirame daugiau teigiamu elementu);

else if ..

}

int n_posit(const int *a, const int n) {

int i, count=0;

for(i=0;i0) count++;

return count; }

4.19. Stringų perdavimas į funkcijas

• Parašyti programą, kuri nustatytų kiek simbolių yra eilutėje

int string_elem(char *str);

void main() { char strp[256];

int elem;

printf(“iveskite simboliu eilute”);

gets(strp);

elem=string(elem);

printf(“stringe yra %d eleementun”,elem);

}

int string_elem(char *str) {

int elem;

for(i=0;str[i]!=‘’;i++)

elem++;

return(elem);

}

4.20. Parametrų perdavimas į funkciją main

• Kai kada reikia perduoti parametrus į pagrindinę funkciją main

• tai naudoja pvz. archyvavimo programos, dirbančios iš komandinės eilutės

• [tipas] main(int argc, char **argv) {

funkcijos kunas

}

arba

• [tipas] main(int argc, char **argv, char **env) {

funkcijos kunas

}

4.21. Standartinės funkcijos

• Kiekvienoje C programų kūrimo sistemoje yra daug standartinių funkcijų

• Su visa eile standartinių funkcijų jau teko susitikti: printf, scanf

• Šios funkcijos yra sudėtos į bibliotekas, jų prototipai – į header-failus, kuriuos reikia įtraukti naudojant direktyvą include

• Standartinės funkcijos sugrupuotos pagal tematiką į grupes, programuotojui reikėtų pasirūpinti reikalingų funkcijų paieška

• Pats programuotojas taip pat gali kurti nuosavas funkcijų bibliotekas

4.22. Parametrų perdavimas į funkciją main

• Komandinės eilutės žodžiai tai transformuotos į ASCII formatą simbolių sekos, atskirtos tarpais, užduodamos programos paleidimo metu

• Programos aplinka – tai seka ASCII simboliais išreikštų sekų, kuri tam prieinama programai, jos paleidimo metu

• Į funkciją perduodamų parametrų prasmė:

int argc – žodžių skaičius komandinėje eilutėje

char **argv – rodiklis į rodiklių masyvą iš argc elementų. nulinis elementas – visada programos pavadinimas

char **env – rodiklis į kintamo dydžio masyvų rodiklį

Pavyzdys programos su argumentų perdavimu į funkciją main:

#include

void main(int argc, char **argv) {

printf(“i programa perduota %d argumentun”,argc);

printf(“ perduoti duomenys irasyti faile %sn”, argv[1]);

printf(“paleista programa vadinasi %sn”, argv[0]);

}

4.23. Rekursinės funkcijos

• C kalba leidžia funkcijai iškviesti pačiai save.

• Funkcija, besikreipianti pati į save vadinama rekursija

• Kiekvienu atveju steke išskiriama atminties sritis saugoti kintmųjų kopijas ir kitus parametrus

• Klasika tapusi faktorialo skaičiavimo funkcija:

f(n) {

if(n) return n*f(n-1);

else return 1;

}

5. V-OJI PASKAITA. Priešprocesorius. Grafika.

5.1. Kompiliacijos etapai

• Priešprocesorius (include failai)

• Išplėstinis Pradinis programos kodas

• programos kodas C kalba

• C kompiliatorius

• Kodas asemblerio kalba

• Asemblerio kompiliatorius

• Objektinis kodas

• Linkeris, objektų biblioteka

• Vykdomas kodas

5.2. Priešprocesorius

Praktiškai kartu su kiekvienu C kalbos kompiliatoriumi pateikiamas taip vadinama priešprocesorius (angl. preprocessor)

Priešprocesorius ieško jam skirtų direktyvų dar iki programos kompiliavimo pradžios ir atlieka veiksmus, kurių reikalauja panaudotos direktyvos.

Priešprocesoriaus direktyvų vykdymas – tai atitinkamas programos išeities kodo sutvarkymas bet jokiu būdu ne kompiliavimas, t.y. Programos kodo vertimas į mašinines komandas

Preišprocesorius – tai galinga priemonė, leidžianti pagerinti programos skaitymą

Visos priešprocesoriaus direktyvos pradedamos komanda #

5.3. Priešprocesoriaus apibendrinimas

• Tai pirmas kompiliavimo etapas

• Pranašumai:

 Skaitymo patogumas

 Programos palaikymo palengvinimas

 Lankstumas

 Mobilumas

• Direktyvos:

 Pradedamos simboliu #

 Gali būti bet kurioje programos vietoje, nors dažniausiai naudojamos pradžioje

5.4. Prešprocesoriaus priemonės

Priemonės:

• Komentarų pašalinimas

• Konstantų ir makrosų (arba makrokomandų) apibrėžimas

• Failų įtraukimas (file inclusion)

• Sąlyginė kompiliacija (conditional compilation)

5.5. Simbolinės konstantos

• Apibrėžus simbolinę konstantą, priešprocesorius pakeičia visas faile aptiktas nuorodas į šią konstantą jos faktine reikšme

• Negalima pakeisti komentarų arba dvigubų kabučių

• Pvz. , jeigu programoje buvo apibrėžta simbolinė konstanta vardu MAXITEMS , visur, kur programoje priešprocesorius aptiks tokiu vardu esančią konstantą, jis pakeis ją priskirta reikšme

• Reikšmė turi būti nurodyta aprašant simbolinę konstantą

5.6. Makrosai

• Makrosai (taip pat dažnai vadinami makrokomandomis) – tai trumpa programa, kuriai gali būti perduoti argumentai

• Sintaksė panaši kaip ir simbolinių konstantų, tačiau makrosuose egzistuoja eilė parametrų, einančių iš karto po identifikatoriaus

• Tie parametrai gali būti argumentų pavadinimai

• Tarp identifikatoriaus ir atidarančio skliaustelio ( jokiu būdu negali būti tarpo

• Kuomet priešprocesorius išskleidžia makrosą, jis atitinkamoje vietoje įstato kodą su atitinkamais parametrais

5.7. Makrosų tęsinys

• Jeigu makrokomandos užima daugiau negu vieną eilutę, reikia naudoti simbolį jų apjungimui

• Keliems sakiniams naudokite bloką

#define SWAP(A,B) { int temp;

temp=A;

A=B;

B=temp; }

int main() {

int num1=30, num2=50;

if(num2>num1) SWAP(num1,num2);

}

• Leksemos makrokomandose gali būti apjungtos naudojant operatorių ##

• Makrososuose naudojami trigrafai – trijų simbolių sekos, kurios reiškia vieną simbolį

• Trigrafai naudojami norint surinkti simboliu, kurių nėra kai kuriose klaviatūrose:

• ??= # ??> } ??- ~

?? ( [ ??/

?? ) ] ??’ ^

?? < { ??! |

#define WheatBread 0

#define RyeBread 1

#define WhiteBread 2

#define PumopernickeBread 3

#define Bread(x) x## Bread

int main() {

printf(“Value of WheatBread is %dn”, Bread(Wheat));

printf(“Value of RyeBread is %dn”, Bread(Rye));

printf(“Value of WhiteBread is %dn”, Bread(White));

printf(“%cn”, ‘??-’);

}

5.8. Funkcijų ir makrokomandų palyginimas

• Greitaeigiškumas:

1) Makrosai greitesni, įterpiami atitinkamose vietose

2) Funkcijos lėtesnės, naudoja steką

• Vykdomos programos dydis:

1) Mažesnis, jei naudojamos funkcijos, kodas pasikartoja tik vieną kartą

• Kiti faktoriai:

1) Funkcijos gali sugražinti reikšmę operatoriuje return, makrosai negali

2) Makrosai neleidžia rekursijos

3) Makrosai dažnai sudėtingesni programos derinimo metu

5.9. Failų įtraukimas

#include

#include “filename.xxx”

Į programą įtraukiama nurodyto failo kopija: aptikęs šią direktyvą priešprocesorius toje vietoje įdės nurodyto C kalba parašyto failo kopiją

Dažnai naudojama header failų įtraukimui.

Header failai turi funkcijų prototipus

Gali būti naudojama ir bet kokių kitų programų failų įtraukimui į kompiliuojamą išeities programą

5.10. Naujo duomenų tipo pavadinimo apibrėžimas

• Komanda typedef – tai naujo, sinoniminio, pavadinimo suteikimas egzistuojančiam duomenų tipui

• typedef egzistuojantis_tipas naujas_tipas

• Naudojama skaitomumui ir mobilumui pagerinti

• Sintaksė analogiška kintamųjų aprašymui

• Rekomenduojama naudoti didžiąsias raides

typedef char BYTE;

typedef unsigned short USHORT;

typedef int WORD;

int main() {

BYTE input;

WORD buf[512];

USHORT a;

}

5.11. Sąlyginė kompiliacija

• #if, #else, #elseif, #endif, #ifdef, #ifndef -tai sąlyginės kompiliacijos direktyvos

• Leidžia sukurti keletą tos pačios programos versijų

• Kompiliuojama ta versija, kuriai patenkinamos užduotos sąlygos

• Sąlygos paprastai užduodamos naudojant direktyvą define

• Kai kuriais atvejais gali būti naudojamos kitos direktyvos

#define WINDOWS32

int main() {

#ifdef WINDOWS32

printf(“ Programa skirta Win32 operacinei aplinkain”);

#endif

#ifdef UNIX

printf(“programa skirta Unix operacinei aplinkain”);

#endif

... }

5.12. Kontroliniai pratimai

5.13. Darbas su grafika

• Informacija į standartinį išvedimo įrenginį (dažniausiai monitoriaus ekraną) gali būti išvedama dviem skirtingais režimais: tekstiniu ir grafiniu.

• Grafiniame režime informacija išvedama taškais, tekstiniame – simboliais

• Bet kuriuo atveju išvedimas, ypač grafiniame režime, labai priklauso nuo techninės įrangos

• Negalima padaryti universalių, nepriklausančių nuo aparatinės įrangos, išvedimo modulių.

• Todėl C kalboje nėra specialių grafikos apdorojimo metodų, o grafiniam išvedimui naudojamos standartinių bibliotekų funkcijos

• Esminis elementas grafikos apdorojime – draiverio sąvoka

• Draiveris – tai speciali programa, atliekanti tarpininko vaidmenį, t.y. Perimanti programos pateikiamus duomenis, atitinkamu būdu transformuojanti juos, ir perduodanti techniniams įrenginiams, kurie išveda atitinkantį grafinį vaizdą į ekraną.

• Kaip taisyklė, savo programoje autorius turi nurodyti kokį grafinį draiverį reikia naudoti !!!

• Programiniu požiūriu, bazinis grafikos elementas vadinamas pikseliu (sutrumpinimas nuo picture element).

• Pikselių kiekis užduoda naudojamą grafinę rezoliuciją.

• Kokius grafinius režimus (rezoliucijas) žinote ?

5.14. Darbas su grafinėmis funkcijomis

• Labai priklauso nuo konkrečios programavimo aplinkos

• Mūsų funkcijos aprašytos faile graphics.h , todėl reikia naudoti direktyvą:

#include

• Programiniu požiūriu grafiko programavimas: nurodyti ką su kiekvienu ekrano pikseliu reikia daryti

• Programavimą visada sudaro trys pagrindiniai etapai:

1. Grafinio įrenginio atidarymas

2. Grafikos apdorojimo veiksmų programavimas

3. Grafinio įrenginio uždarymas

5.15. Grafinio įrenginio atidarymas

• Grafinio įrenginio inicializavimo funkcija:

• void initgraph(int *graphdriver, int *graphmode chat *pathtodriver);

graphdriver – skaičius, žymintis grafinio draiverio pavadinimą. Galima naudoti simbolinius pavadinimus DETECT, CGA, VGA, MCGA ir t.t.

gmode – kintamasis, reiškiantis pradinį grafinį režimą

pathtodriver – kelias iki direktorijos, kur įrašyti grafiniai draiveriai. Pas mus c:bcbgi

Pvz: int gdriver=DETECT, gmode;

initgraph(&gdriver, &gmode, ”c:\bc\bgi”);

5.16. Grafinio įrenginio uždarymas

• Pabaigus darbą su grafiniu režimu, reikia uždaryti grafinį įrenginį

• Uždarymui naudojama funkcija closegraph:

• void closegraph(void);

• Pvz:

#include

void main() {

int gdriver=detect, gmode;

initgraph(&gdriver, &gmode, ”c:\bc\bgi”);

.. // cia rasomi garfikos apdorojimo veiksmai

closegraph();

}

5.17. Kai kurios grafinės funkcijos

Ekrano išvalymo funkcija:

• void cleardevice(void);

Kursoriaus pozicijos valdymo funkcijos:

• void moveto(int x, int y);

• void moverel(int dx, int dy);

Tiesių braižymo funkcijos:

• void line(int x1, int y1, int x2, int y2);

• void linerel(int dx, int dy);

• void linerel(int x, int y);

• Vieno pikselio išvedimo funkcija:

• void putpixel(int x, int y, int color);

Grafinių figūrų paišymo funkcijos:

• void rectangle(int left, int top, int right, int bottom);

• void circle(int x, int y, int radius);

• void arc(int x, int y, int stangle, int endangle, int radius);

• void drawpoly(int numpoints, int *polypoints);

• void bar(int left, int top, int right, int bottom);

• void fillpoly(int numpoints, int *polypoints);

5.18. Spalvų valdymo funkcijos

• Fono spalvos nustatymas: void setbkcolor(int color);

• Objekto spalvos nustatymas: void setcolor(int color);

• Spalva – tai sveikas skaičius iš intervalo 0 – 15 (kur 0 – juoda spalva, 15 – balta spalva).

• Be to galima naudoti šiuos simbolinius spalvų pavadinimus:

• BLACK , BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE.

• Atskiras spalvos modifikatorius: BLINK

5.19. Teksto valdymas grafiniame režime

Teksto išvedimo funkcijos:

• outtext(char *textstring);

• outtextxy(int x, int y, char *textstring);

Teksto dydžio, stiliaus valdymo funkcijos:

• void setextstyle(int font, int direction, int charsize);

• Font: TRIPLEX_FONT, SMALL_FONT, SANS_SERIF_FONT, GOTHIC_FONT

• Direction: HORIZ_DIR, VERT_DIR

• Charsize: 0,1 (8×8), 2 (16×16), 3 (32×32) ir t.t.

5.20. Paprastos programos su grafika pavyzdys

6. VI-OJI PASKAITA. Matomumo sritis. Kintamųjų klasės.

6.1. Matomumo sritis

• Aprašėme programoje kintamąjį, tegul int a. Kurioje programos dalyje šis kintamasis yra matomas, tai yra juo galima naudotis (priskirti reikšmes, naudoti operanduose ir pan.) ?

• C kalboje egzistuoja pagrindinė taisyklė: visi kintamieji yra matomi blokuose.

• Blokas – tai programos dalis, apimta riestiniais skliausteliais { }

• Kiek blokų gali būti vienoje programoje ?

• Kokio tipo blokai dažniausiai sutinkami programoje ?

• Dažniausiai pasitaikantis blokas programose yra funkcija, tokiu atveju ir kintamasis yra matomas funkcijos ribose

• Tačiau tai nėra privaloma

• Funkcijos viduje galima padaryti atskirus blokus: t.y. kintamasis bus matomas tik dalyje funkcijos

• Tačiau toks skaidymas naudojamas retai.

• Žymiai dažniau naudojami globaliniai kintamieji – kintamieji , kurie yra matomi ne tik vieno bloko viduje, bet platesnėje programos dalyje

6.2. Lokaliniai ir globaliniai kintamieji

• Pasikartosime: kintamieji apibrėžti bloke yra matomi tik to bloko ribose

• Tokie kintamieji vadinami lokaliniais

• Jų priešingybė – globaliniai kintamieji

• Globaliniai kintamieji yra apibrėžiami už bloko ribų (todėl nepriklauso jokiam blokui) ir yra matomi .

• Kur yra matomi globaliniai kintamieji

• Priklauso nuo apibrėžimo: paprastai už bloko ribų aprašyti kintamieji yra matomi duoto failo ribose.

• Matomi visuose blokuose, t.y. visose tame faile aprašytose funkcijose

6.3. Globaliniai kintamieji

• Globaliniai kintamieji – vienas iš būdų perduoti į funkciją kintamuosius ir gauti iš funkcijos reikšmes.

int a;

void main() {

int c,b; a=7; b=5;

c=a+b;

func(c); printf(“%dn”,a); }

void func(int c) {

int b;

b=a+c; a=b; }

6.4. Lokalinių ir globalinių kintamųjų vardų sutapimas

• Neretai pasitaiko situacijo, kuomet programoje yra lokalinių ir globalinių pavadinimų tais pačiais vardais:

int a,b;

void main() {

int c; a=7; b=5;

c=a+b;

func(c); printf(“%dn”,a); }

void func(int c) {

int b;

b=a+c; a=b; }

Jeigu yra lokalinis ir globalinis kintamasis tuo pačiu vardu, pagal nutylėjimą naudojamas lokalinis kintamasis.

• Jeigu norime panaudoti globalinį kintamąjį, prieš jo pavadinimą reikia parašyti modifikatorių :: (du dvitaškiai):

int a,b;

void main() {

int c; a=7; b=5;

c=a+b;

func(c); printf(“%dn”,a); }

void func(int c) {

int b;

b=a+c; ::b=b; }

6.5. Atminties klasių apžvalga

• Atminties klasės – tai alternatyvūs duomenų saugojimo variantai

• Atminties klasės:

o automatiniai

o registriniai

o išoriniai

o statiniai

• Veikimo sritis: sakiniai, kuriuose galima naudoti nurodytą kintamąjį

• Gyvavimo laikas: laiko tarpas, kurio metu išsaugoma kintamojo reikšmė

6.6. Automatiniai kintamieji

• Veikimo sritis: lokaliniai, blokas, aprašomi naudojant raktinį žodį auto

• Gyvavimo laikas: sukuriami įeinant į bloką. Nustoja gyvuot (sunaikinami) išeinant iš bloko

• Vidiniai aprašymai išstumia išorinius

void print_cube(int);

int main(){

int x;

x=getchar():

if(x==‘c’) { ..

}

print_cube(100); }

void print_cube(int x) { // x zinoma tiktai funkcijoje print_cube

printf(“%dn”,x*x*x); }

6.7. Registriniai kintamieji

• Registriniai kintamieji naudojami siekiant pasiekti aukštesnį programos veikimo našumą

• Aprašomi naudojant raktinį žodį register

• Kompiliatoriui generuojama užklausa, kad šis kintamasis būtų saugomas ne steke, o registre (kitaip sakant procesoriuje)

• Ta automatinių kintamųjų poaibis, todėl gali būti aprašyti tik lokaliniai kintamieji

• Registrų nedaug, galima priskirti tik tuos kintamuosius, kurie tikrai naudojami programoje labai dažnai

• Patartina tokia galimybe naudotis tik labai patyrusiems programuotojams, nes naujokams tai kaip taisyklė neduos jokios naudos.

• Šiuolaikiniai kompiliatoriai labai efektyviai optimizuoja registrinių kintamųjų priskyrimo procesą

• Greitis ir efektyvumas

• Naudojami procesoriaus registrai vietoj steko kintamųjų saugojimui

• Naudotini funkcijų parametrams ir automatiniams kintamiesiems

• Matomumo sritis ir gyvavimo laikas: kaip automatiniams kintamiesiems

• Leidžiamų registrų skaičius priklauso nuo procesoriaus tipo

f(register int count, register int num) {

register int i;

for(i=0;i

• Šis operatorius nenaudojamas niekam kitam, nes rodikliai į struktūras naudojami labai dažnai

• sp->salary=2750.50;

7.7. Alternatyvūs struktūrų aprašymo būdai

• Tego uždavimas ir kintamųjų aprašymas toje pačioje vietoje

struct emp { char name[12];

char id[8];

double salary;

} prgmr employe[100], *p;

• Aprašymas be tego

struct { char name[12];

char id[8];

double salary;

} prgmr, employe[100], *p;

• Tipo modifikatoriaus panaudojimas

typedef struct { char name[12];

char id[8];

double salary;

} EMPLOYEE;

EMPLOYEE prgmr,employe[100], *p;

7.8. Struktūros ir funkcijos

7.9. Pratimas – rodikliai į struktūras

• Prieš tai pateikta programa būtų žymiai efektyvesnė, jeigu į funkciją raise() būtų perduotas rodiklis į struktūrą, o ne pati struktūra Pakeiskite brūkšnelius, kad į funkciją būtų perduodamas rodiklis į struktūrą

#include

#include “emp.h”

void main() {

struct emp progmr;

—– raise(struct emp —, double);

...

printf(“senas atlyginimas: %.2fn”, prgmr.salary);

prgmr=raise(—- prgmr, 0.12);

printf(“naujas atlyginimas: %.2fn”, prgmr.salary);

}

—— raise(struct emp —person, double increase) {

person—salary*=(1+increase);

return person;

}

7.10. Struktūrų inicializavimas

• Struktūros gali būti inicializuojamos aprašymo metu

• Struktūros laukams priskiriamos reikšmės pateikiamos kaip sąrašas, atskiriamos kableliais ir apskliaudžiamos riestiniais skliausteliais

• Neinicializuoti struktūrų elementai pagal nutylėjimą lygūs 0

• Neinicializuoti automatinių struktūrų elementai pagal nutylėjimą nėra apibrėžti

struct course {

char name[30];

int number;

char nickname[30]; } title = { “c for programmers”, 1001, “my guide” };

struct mailinfo {

char name[25];

char mail_addr[30]; } proj_member[]= {

{“jean griffin”, “ first 25” }

{“sue armani”, “second 13” }

{ “frank kruk”, “boulevard 6” }

};

int f(void) {

static struct mailinfo admin=

{“administartor”, “computer 7” };

}

7.11. Struktūros su struktūromis

• Struktūros lauku gali būti struktūra

• Struktūros elementu gali būti rodiklis į jos pačios tipą

• Naudojama susietiems sąrašams ir medžiams

• Susietas sąrašas:

struct info { int num;

float sum;

struct info *next; };

• Medis:

struct node { int key;

char description[50];

struct node *left, *right; };

7.12. Apjungimai

• Visi struktūrų aprašymo ir panaudojimo aspektai (tegai, šablonai, priėjimas), kurie buvo aprašyti kalbant apie struktūras, tinka ir apjungimams.

• Vienintelis skirtumas – naudojamas ne raktinis žodis struct, bet raktinis žodis union.

• Lietuviškai kartais vadinama apjungimais, kartais vadinama sąjungomis

• Skirtingai negu struktūrose, apjungimas turi tik vieną iš savo elementų kiekvienu laiko momentu.

• Apjungimas panaudoja vieną atminties sritį skirtingų kintamųjų saugojimui skirtingais laiko momentais

• Faktiškai apjungimas – tai struktūra, kurios visi elementai pradedami su postūmiu lygiu 0 ir skirtingais momentais konceptualiai persidengia.

7.13. Apjungimų palyginimas su struktūromis

• Aprašymas, tegas, šablonai – viskas taip, kaip ir su struktūromis.

• Aprašymui naudojamas raktinis žodis union

• Duotu laiko momentu saugo tik vieną elementą

• Pakankamai didelis, kad saugotų didžiausią galimą elementą

struct s_tag { union u_tag {

char c; char c;

int i; int i;

double d; double d;

} s_item; } u_item;

printf(“s_tem dydis %dn”,sizeof(s_item));

printf(“u_tem dydis %dn”,sizeof(u_item));

7.14. Apjungimų pranašumai

• Apjungimai neretai įtraukiami į struktūras, o vienas iš struktūros elementų naudojamas kaip raktas, kad parodyti kuris iš apjungimo elementų bus naudojamas

• Lankstumas – gali saugoti skirtingo tipo objektus atmintyje

• Dažnai naudojama, kad taupyti atmintį

struct mail {

char id; // a- active, r – retired

union { struct { char name[30];

char dept[10];

char location[3]; } active;

struct { char name[30];

char street[20];

char city_code[5]; } retired; } info; } person;

7.15. Išvardijimai

• Naudojami tuomet, kada reikia konstantų sekos ir nenorime sukurti naujo duomenų tipo.

• Įvedami išvardinti tipai (enumerated types)

• Aprašomi naudojant raktinį žodį enum.

• Tarkime mums reikia mėnesių sekos metuose “masyvo”:

enum e_months {JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

typedef enum e_months month;

month currentmonth;

currentmonth = JUN; /* same as currentmonth = 6; */ printf(“%dn”, currentmonth);

• Mes išvardijame mėnesius metuose naujame tipe vadinamame month.

• Mes nesukuriame naujo tipo, nes išvardijimai yra paprasti int tipo skaičiai. Todėl printf funkcija naudoja %d, o ne %s.

• Dėmesio, jeigu JAN=1 pasako C kompiliatoriui išvardijimą pradėti nuo 1 vietoj 0.

• Pastaba: Tai bus beveik tas pats , kas:

#define JAN 1

#define FEB 2

#define MAR 3 /* . etc . */

7.16. Struktūrų masyvo surūšiavimas

7.16. Kai kurie praktiniai patarimai: komentarai

1) Nerašykite akivaizdžių dalykų:

pvz: /* gražinam SUCCESS reikšmę */

return SUCCESS;

zerocount+; // padidinam zerocount reikšmę vienetu

Tokie komentarai ne padeda, o tik trukdo.

2) Komentuokite funkcijas ir globalinius kintamuosius. Kadangi globaliniai kintamieji pasirodo įvairiose programos vietose, patartina kartais priminti jų reikšmę ir paskirtį. Prie funkcijos kūno visada patartina pateikti jos trumpą charakteristiką. Jei funkcija sudėtinga, patartina nurodyti šaltinį, kuriame aprašytas algoritmas.

3) Nekomentuokite blogo kodo, o perrašykite tą kodą kartais nepavykus parašyti kodo fragmento sėkmingai, jis paliekamas, tik užkomentuojamas. Tuo tarpu komentarai paliekami, ir dažnai nebeaišku kam tie komentarai priklauso.

4) Neprieštaraukite kodui: paprastai parašius programą, komentarai atitinką kodo prasmę, tačiau vėliau padarius kokias nors modifikacijas, kodas pataisomas, o komentarai paliekami.

5) Komentarai turi įvesti aiškumą ne sumaištį.

7.16. Kai kurie patarimai: vieningas stilius ir idiomos

• Būkite nuoseklūs naudodami atitraukimus ir figūrinius (riestinius) skliaustelius

• Naudokite idiomas vieningam stiliui palaikyti: yra tam tikri stiliai – idiomos, kurie yra priimtini ir naudojami, nors yra teisingi ir kiti

Galima:

a) i=0;

while(i<=n-1) array[i]=1.0;

b) for(i=0;i=65 && c<=90)

Geriau naudoti: if(c>=‘A’ && c<=‘Z’)

Dar geriau: if(isupper(c))

Objekto dydžio nurodymui naudokite programavimo kalbos priemones:

#define NELEMS(array) (sizeof(array)/sizeof(array[0]))

8. VIII-OJI PASKAITA

Objektinio programavimo principai

8.1. Objektinis programavimas

• Objektiškai orientuoto (objektinio) projektavimo principai

• Sąvokų įsisavinimas: klasė, objektas, sąryšis

• Objektinio programavimo instrumentų panaudojimas

• Projekto, sukurto naudojant objektinius principus, kokybės įvertinimas

• Tinkamo modelio objektiniam projektui parinkimas

• Objektinio projekto dokumentavimas (aprašymas)

• Objektinio projekto gyvavimo ciklas

8.2. C ir C++ kalbos

• Sutinkami dažnai terminai – C ir C++. Tai ta pati kalba, ar dvi skirtingos kalbos ?

• C – tai įprastinė procedūrinė (kartais vadinam struktūrinė) aukšto lygio programavimo kalba. Giminiškos kalbos Pascal, Fortran, PL/1 ir t.t.

• C++ – tai objektiškai orientuota programavimo kalba. Giminiškos kalbos – Delphi, Smalltalk, šiek tiek Java ir t.t.

• C++ sukurta panaudojant C kalbos sintaksė, leksemas ir visa iki tol sukaupta tos kalbos patirtį.

• Prie klasikinių C kalbos savybių C++ buvo prijungtos objektinio programavimo galimybės

• Teisinga teigti, kad C – tai C++ poaibis, realizuojantis procedūrinio programavimo principus

8.3. Kam reikalingas objektinis programavimas ?

• Visų pirma naudojamas dideliuose projektuose

• Labiausiai nauda juntama, kai programinį produktą kuria dideli žmonių kolektyvai

• Daugumą šiuolaikinių programų kuria būtent dideli programuotojų kolektyvai

• Tačiau pakanka ir dviejų programuotojų kad nauda būtų akivaizdžiai juntama

• Kolektyvinio programavimo principas – skirtingi asmenys būna atsakingi už skirtingas projekto dalis ir reikia, kad jų dalys būtų tarpusavyje suderintos

• Objektinis programavimas leidžia programą rašyti objektais (realizuoti atskirais objektais), kurie su kitais objektais bendrauja per tam tikrus interfeisus

8.4. Objektinio programavimo principai

• Kuriant objektinio programavimo principus, stengtasi įvertinti žmogiško mąstymo principus

• Žmonės dažnai skirsto stebimus objektus į klases, tos pačios klasės objektai turi bendrų savybių; bendresnės klasės objektus galima skirstyti į smulkesnių klasių objektus; smulkesnių klasių objektai paprastai paveldi stambesnių klasių objektų savybes ir įgyja naujų savybių

• Skirtingų klasių objektai turi bendras savybes, bet jos būna išreikštos per skirtingo tipo parametrus.

• Panašūs principai buvo realizuoti, kuriant objektinio programavimo principus.

8.5. Objektinio programavimo procesas

• Objektinio programavimo stilius projektuojant – tai iteracinis aplikacijos vystymas

• Faktiškai tai priešingybė “kulinarinių receptų” stiliui

• Projektuojant objektiniu principu reikia atlikti sekančius veiksmus:

 Išorinių reikalavimų nustatymas

 Esybių identifikavimas

 Jų savybių ir elgesio identifikavimas

 Esminių ryšių ir savybių identifikavimas

Iteracijos baigiamos, kai visas projektas tampa pinu ir korektišku

8.6. Išorinis aprašymas

• Sudaromas aukšto lygio koncepcinis projektuojamo objekto modelis

• Išorinis aprašymas:

 Sąskaitų tipai, kuriuos padoroja bankas

1. Komercinės sąskaitos (max 7 procentai palūkanų priklausomai nuo kitų sąlygų)

2. Nekomercinės sąskaitos (palūkanos nemokamos, min indėlio dydis 200)

 Finansinių operacijų tipai:

1. Indėlio atidarymas, uždarymas, pakeitimas

2. Finansinės ataskaitos sudarymas

 Bankomato funkcijos:

1. Kortelės tikrumo patikrinimas

2. Sąskaitos būklės patikrinimas

3. Finansinių operacijų vykdymas

8.7. Esybių identifikavimas

• Žodyno sudarymas:

 Reikalavimų analizė

 Bendravimas su ekspertais

• Esminių abstrakcijų nustatymas, kurios gali būti potencialių pakitimų šaltiniais

 Procedūrų abstrakcijos

 Duomenų abstrakcijos

• Esybės, kurios žymimos daiktavardžiais:

 gali būti realios arba irrealios

 Gali būti specialiai išrastos

 Ne visos priskiriamos konkrečioms klasėms

 Bendru atveju yra kandidatais konkrečiai klasei

Esybių identifikavimo pavyzdys

• Procedūros:

• Visų finansinių deklaracijų spausdinimas

• Objektai:

• Komercinės sąskaitos

• Nekomercinės sąskaitos

8.8. Esybių elgesio identifikavimas

• Išnagrinėti kiekvieną esybę atskirai nuo kitų

• Identifikuoti duotos esybės elgesį

• Esybės ribos gali būti pakeistos dėl:

 Kai kurių esybių didelio sudėtingumo

 Esybių apjungimo

 Kitų esybių reikšmių pasikeitimo

• Esybių elgesio identifikavimas – tai visada iteracinis procesas

• Esybių identifikavimo stadija kaip taisyklė sudėtingesnė, negu esybių aibės nustatymo stadija

8.9. Esybių požymių nustatymas

• Sumažinti abstrahavimo lygį

• Išnagrinėti kiekvieną esybę iš išorės

• Nustatyti požymius

• Nustatyti naujas esybes

• Objektiškai orientuoto projektavimo principas nepalaiko grynųjų “iš viršaus – į apačią” arba “iš apačios – į viršų” projektavimo strategijų

• Nustatant požymius dažnai tena grįžti į ankstesnes stadijas

• Nustatant požymius galimos projektavimo proceso iteracijos

8.10. Ryšių identifikavimas

• Objektų integravimo į sistemą būdų nustatymas:

– bendrumų, panašumų nustatymas

– statinės ir dinaminės semantikos nustatymas

– matomumo nustatymas

Ryšių identifikavimo metodai:

Iš apačios į viršų

Iš viršaus į apačią

Kombinuotas

8.11. Objektinio projektavimo būdo apibendrinimas

• OOP procesas yra iteracinis, jame realizuota mišri projektavimo strategija

• OOP palaiko projektuotojo darbą keliuose projekto abstrahavimo lygiuose

• Objektinis projektavimas – tai “kulinarinių receptų knygos antitezė

• Pagrindiniai OOP etapai:

o išorinis projektavimas ir reikalavimų sistemai nustatymas

o Esybių identifikavimas

o Esybių elgesio nustatymas, jų požymių ir charakteristikų aptikimas

o Ryšių ir struktūrų identifikavimas

• OOP procesas sustabdomas po užbaigto ir korektiško projekto sugeneravimo

8.12. Objekto sąvokos įsisavinimas

• Objektas yra tam tikros objektų klasės realizacija

• Objektas gali turėti būseną

• Objektas gali turėti elgseną

• Objektas gali turėti pavadinimą arba likti bevardis

• Objektas – tai tam tikros klasės egzempliorius

• Objekto matomumas yra apibotas kitų objektų atžvilgiu

• Objektas gali būti nagrinėjamas specifikavimo ir realizavimo požiūriu

8.13. Objekto būsena

8.14. Objektų rolės

• Objektai gali funkcionuoti keliuose režimuose:

• Operatoriaus režimas: Operatorius veikia į kitus objektus ir nepatiria poveikio iš jų pusės. Bankinis automatas gali būti vertinamas kaip kortelių apdorojimo interfeisas

• Serverio režimas. Serveris – tai toks objektas, kuris patiria išorinius poveikius ir nedaro poveikio kitiems objektams.

• Tarpininko režimas. Tarpininkas – ta objektas, kuris priima kitų objektų poveikius ir pats daro poveikius kitiems objektams.

• Didelę įtaką turi poveikių seka

8.15. Objektų elgesys

• Visiškai izoliuotų objektų neegzistuoja. Objektai priima poveikius ir perduoda poveikius kitiems objektams

• Vartotojo požiūriu galima išskirti penkias poveikių klases:

• Modifikatoriai – operaotoriai, kurie pakeičia objekto būseną

• Selektoriai – operatoriai, kurie įgalina prieiti prie objekto būsenos

• Iteratoriai – leidžia prieiti prie visų objekto dalių griežtai apibrėžta tvarka

• Konstruktoriai – operatoriai, kurie inicializuoja objektą

• Destruktoriai – operatoriai, kurie sunaikina objektą.

• Konstruktoriai ir destruktoriai C++ kalboje sukuriami automatiškai

8.16. Klasės

• Klasė:

• Tai abstrakti sąvoka (duomenų tipas)

• Apibrėžiama objektų, kurie turi panašią elgseną ir panašią struktūrą, aibei

• Interfeisas aprašo išorines klasės savybes. Interfeiso elementai visada turi modifikatorių public. Interfeiso elementais gali būti:

• – operatoriai

• – klasių aprašymai

• – konstantės

• -kintamieji

• Realizacija parašo klasės sandarą. Realizacijos elementai turi modifikatorių private. Realizacijos elementai – tai:

• – operatoriai

• – klasių aprašymai

• – konstantės

• – kintamieji

• Klasė aprašoma naudojant raktinį žodį class

• Konkreti klasės realizacija vadinama objektu

8.17. Klasių i

. . .

• Yra bendri duomenys visiems tam tikros klasės-šablono egzemplioriaus klasės objektams.

• Apibrėžiami failo matomumo srityje, kuomet prieš apibrėžimą naudojamas template

template class C {

static int i;

static T t; };

template int C ::i; // apibrėžiame matomumo srityje

template int C ::t;

C c;

C f;

10.16. Funkcijų-narių šablonai

• Apibrėžiami už klasių, kurioms priklauso, apibrėžimų ribų naudojant specifikatorių template

• Apibrėžtiems tipams gali būti perdengti, kad atlikti tam tikrus veiksmus, kuriuos metodų šablonai neatlieka

template void

Stack ::Push(const T& element)

{

if(top==size-1)

error(“stack oveflow”);

else v[++top]=element;

}

10.17. Draugiškos funkcijos

• Kiekvienam T tipui gali būt visų T tipo klasių draugais. Tai įprastos draugiškos klasės

• T tipui gali būt T tipo klasės draugais

• Prieš juos gali eiti specifikatorius template

• Gali būti kitos klasės funkcijomis- nariais

• Gali būti apibrėžti visai klasei

• Gali būti ne šabloninių klasių draugais

10.18. Operacijų perkrovimas

• Gali išplėsti iki klasės tipo bet kurių operacijų reikšmes, įskaitant :: , sizeof, ? :, ., *

• Atliekama deklaruojant funkciją, susidedančią iš raktinio žodžio operator, po kurios seka viena iš vidinių operacijų

• Nedaro jokių prielaidų apie tokias operacijas. Pvz: jeigu i yra int tipo, tai ++i yra tas pats, kas i=+1 ir i=i+1. Perkrautiems operatoriams tokios prielaidos nebegalioja tol, kol pats programuotojas jų atitinkamai neapibrėžia

• Negali naudoti argumentų pagal nutylėjimą

10.19. Unariniai operatoriai

• Gali būti apibrėžti kaip nestatinės funkcijos-nariai, neturintys argumentų. Tai yra @ x interpretuojama kaip x.operator@() bet kuriam operatoriui @

• Gali būti apibrėžti kaip funkcijos, nesančios kokios nors klasės nariais, ir turinčios vieną argumentą

• Šis argumentas yra tos klasės kintamasis arba nuoroda į tokį kintamąjį

• Šiuo atveju @x interpretuojama kaip operator@(x) bet kuriam operatoriui @

11. XI-OJI PASKAITA

Operatorių perkrovimas. Polimorfizmas.

11.1. Unariniai operatoriai

Class X {

X operator-() const; // unarinis minusas

X operator &() const; // adreso gavimas

X operator ^() const; // klaida: ^ binarine operacija

};

class Y {

friend Y operator –(const Y&); // unarinis minusas

friend Y operator &(const Y&); // adreso skaiciavimas

friend Y operator^(const Y&); // klaida

};

11.2. Binarinės operacijos

• Gali būti deklaruotos kaip nestatinės funkcijos, kurios turi vieną argumentą. Tai yra užrašas x@y interpretuojamas kaip x.operator@(y) bet kuriam operatoriui @.

• Gali būti deklaruotos kaip funkcijos, nepriklausančios konkrečiai klasei ir turinčios vieną argumentą.

• Šis argumentas turi būti arba duotos klasės kintamuoju, arba nuoroda į tokį kintamąjį. Ta yra bet kuriai operacijai @, Įskaitant ir operaciją =, x@y interpretuojama kaip operator@(x,y)

• Pvz:

class X {

X operator –(const X&) const; // binarinis minusas

X operator &(const X&) const; // poskiltinis IR

X operator! (const X&) const; // klaida: ! Unarine operacija

};

class Y {

friend Y operator –(const Y&, const Y&);

friend Y operator &(const Y&, const Y&);

friend Y operator! (const Y&, const Y&); // klaida

};

11.3. Operatorių perkrovimas

11.4. Funkcijos iškvietimo operacija

• Turi būt paskelbta, kaip nestatinė klasės funkcija narys

• Leidžia vartotojui nustatyti operandų kiekį

Class X {

// ..

public:

X(int a, int b, int c);

// ..

void operator() (int i, int j, in k);

};

X Xample(1,2,3); // iškviečiamas konstruktorius

Xamople(4,5,6); // iškviečiama operacija ()

11.5. Priskyrimo operacija

• Naudojama vieno duotos klasės objekto reikšmės priskyrimui kitam objektui

• Jeigu vartotojas jos neapibrėžė, tai atlieka vieno klasės objekto laukų priskyrimą kitam objektui

• Turi būti apibrėžta, jeigu klasėje yra laukai, kurie yra rodikliai į dinamiškai išskirtas atminties sritis

• Tai tik operacijos funkcija, kuri nėra paveldima

• Turi būti apibrėžta, kaip nestatinė klasės funkcija – narys

11.6. Indeksavimo operacija

• Turi būti apibrėžta kaip nestatinė klasės funkcija- narys

• Dažniausiai gražina nuorodą, todėl ją galima naudoti priskyrimo operacijoje iš abiejų operando pusių

class String* {

char *s;

//.

public:

String(char);

String(const char *);

char &operator[](int pos) { return s[pos]; }

// .

};

String ball=mitten”;

ball[0]=‘k’;

11.7. Priėjimo prie nario operacija

• X->m interpretuojama kaip (x.operator->())->m.

• Pastebima, kad tai unarinė operacija ir kad x – tai klasės objektas, o ne rodiklis į jį.

• Turi gražinti rodiklį į klasės objektą, arba patį klasės objektą, arba nuorodą į klasės objektą, kuriam ši operacija yra priskirta, kadangi originali operacijos -> prasmė nėra prarandama, o tik užlaikoma

• Turi būti apibrėžta, kaip nestatinė klasės funkcija – narys

11.8. Polimorfizmas

• Polimorfizmas išvertus iš graikų kalbos reiškia daugiaformiškumas

• Tai paskutinė bazinė objektinio programavimo koncepcija

• Polimorfizmas objektiniame programavime suprantamas kaip objekto sugebėjimas sureaguoti į tam tikrą užklausą priklausomai nuo savo tipo, netgi ir tuo atveju, kuomet kompiliacijos metu objekto, kuriam nukreipta užklausa, tipas dar nėra žinomas.

• C++ kalboje polimorfizmo koncepcija realizuota naudojant virtualių funkcijų-narių mechanzmą

11.9. Virtualios funkcijos-nariai

• Jeigu kurioje nors klasėje yra funkcija, aprašyta kaip virtual, tai į tokią klasę kompiliatorius patalpina paslėptą narį – rodiklį į virtualių funkcijų lentelę.

• Taip pat sugeneruojamas specialus kodas, leidžiantis parinkti virtualią funkciją, tinkančią duoto tipo objektui, programos vykdymo metu.

• Šis procesas įgijo vėlyvo surišimo pavadinimą (angl. late binding).

• Kita vertus virtualių funkcijų naudojimas lėtina programos veikimą ir didina klasės objektų dydį

• Jeigu kokia nors funkcija bazinėje klasėje apibrėžta kaip virtuali, tai funkcija tokiu pačiu pavadinimu, su tuo pačiu argumentų sąrašu ir tokio paties tipo gražinama reikšme, apibrėžta bazinėje klasėje, automatiškai tampa virtualia

• Negalima apibrėžti išvestinėje klasėje funkcijos, besiskiriančios tiktai gražinamos reikšmės tipu

• Virtuali funkcija savaime suprantama turi būti kokios nors klasės metodu, tačiau ji negali būti statiniu kokios nors klasės metodu.

• Išvestinėje klasėje galima apibrėžti funkciją su kitu besiskiriančiu argumentų sąrašu ir ji bus paprasta (nevirtuali) funkcija

class Base {

int dummy;

public:

void f() { cout<

//lango klases pavadinimas

char const szClassName[]=“MyWindowsAppClass”;

//lango pavadinimas

char const szWindowsTitle[]=“MyWindowApplication”;

Int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow) {

HWND hwnd; // lango identifikatorius

MSG msg;

ATOM aWndClass; // grizimo kodo atomas

WNDCLASS wc; // lango klases registravimo struktura

// uzpildome lango klases registravimo strukturos laukus

//lango stilius

wc.style=0;

// rodikis i lango funkcija, apdorojancia visus sios klases langu pranesimus

wc.lpfnWndPoc=(WNDPROC)WndProc;

wc.cbClsExtra=0;

wc.cbWndExtra=0; // papildomos atminties dydis

wc.hInstance=hInstance;

wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); //ikoneles identifikatorius

wc.hCursor=LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground=(HBRUSH)(COLOR_WINDOW=1);

wc.lpszMenuName=(LPSTR)NULL;

wc.lpszClassName=(LPSTR) szClassName;

// uzregistruojame lango klase

aWndClass=RegisterClass(&wc);

// sukuriam langa

hwnd=CreateWindow(szClassName, szWindowTitle, WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT,

// lango dydis ir vieta

0, // motininio lango identifikatorius

0, // meniu identifikatorius

hInstance, NULL);

if(!hwnd) return FALSE;

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

// paleidziam pranesimu apdorojimo cikla

while(GetMessage(&msg,0,0,0)) {

DispatchMessage(&msg); }

return msg.wParam; }

LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

switch(msg) {

case WM_LBUTTONDOWN: {

MessageBox(NULL, “paspaustas kairysis peles klavisas”, “pranesimas”, MB_OK);

return 0; }

case W_RBUTTONDOWN: {

MessageBox(NULL, “paspaustas desinysis peles klavisas”, “pranesimas”, MB_OK);

return 0; }

case WM_DESTROY: {

PostQuitMessage(0);

return(0);

}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

11.11. Darbas su Windows sistemos meniu

• Beveik kiekviena Windows aplinkai parašyta programa turi meniu.

• Dažniausiai meniu kuriamas naudojant programos resursų failą ir resursų kompiliatorių

• Resursų failas turi plėtinį .rc

• Resursu faile gali buti ir kai kurie kiti programai reikalingi duomenys (pavyzdžiui akseleratoriai, ikonėlės ir t.t.)

MY_MENU

nameID MENU

BEGIN

POPUP “&File”

BEGIN

MENUITEM “&New”, CM_NEW

MENUITEM “&Open”, CM_OPEN

MENUITEM “&Save”, CM_SAVE

END

POPUP “&Edit”

BEGIN

MENUITEM “&Undo”, CM_UNDO

MENUITEM “&Cut”, CM_CUT

MENUITEM “&Paste”, CM_PASTE

MENUITEM “&Copy”, CM_COPY

END

END

MENUITEM SEPARATOR

Join the Conversation

×
×