C# õppematerjal
2006
Sisukord
Sisukord 2
Sissejuhatus 5
Põhivõimalused 6
Käivitamine 8
Ülesandeid 9
Suhtlus arvutiga 9
Arvutamine 10
Ülesandeid 11
Valikud 11
Kommentaarid 12
Ülesandeid 13
Kordused 13
Järelkontroll 15
Ülesandeid 15
Korrutustabel 15
Alamprogramm 17
Ülesandeid 17
Massiivid 17
Tsükkel andmete kasutamiseks 18
Massiiv ja alamaprogramm 19
Algväärtustamine, järjestamine 19
Osutid ja
koopiad 20
Massiiv alamprogrammi parameetrina 21
foreach - tsükkel 22
Mitmemõõtmeline massiiv 22
Ülesandeid 23
Käsud mitmes
failis 23
Ülesandeid 24
Tekst 24
Muutmine 25
Tükeldamine 26
Ülesandeid 26
Tekstifailid 27
Kirjutamine 27
Lisamine 27
Lugemine 28
Ülesandeid 28
Juhuarv 28
Ülesandeid 29
Omaloodud andmestruktuur 29
Punktimassiiv 31
Ülesandeid 32
Objektorienteeritud programmeerimine 33
Tutvustus 33
Klassimuutuja 34
Osuti,
omistamine . 34
Punktimassiiv 36
Ülesandeid 37
Dokumenteerivad kommentaarid 38
Readonly 38
Näide 38
Kompileerimine 39
Kommentaarifail 39
Ülesandeid 40
Pärilus 40
Päriluseta näide 41
Alamklass 41
Ülesandeid 43
Ülekate 43
Ülesandeid 44
Liidesed 44
Ülesandeid 46
Abstraktne klass 46
Ülesandeid 47
Meetodite asendus 47
Ülesandeid 49
Omadused 49
Pöördumisstatistika 51
Ülesandeid 52
Indekseering 52
Vahendus 53
Ülesandeid 54
Operaatorite üledefineerimine 54
Tüübimuundusoperaatorid 56
Võrdlusoperaatorid 58
Ülesandeid 61
Abivahendid 62
Erindid 62
Püüdmine 62
Reageering tüübi põhjal 63
Püüdmine alamprogrammist 65
Erindi
heitmine 65
Ülesandeid 66
Andmekollektsioonid 67
ArrayList 67
Sortimine 68
Tüübimäärang 68
Järjekord 69
Paisktabel 70
Ülesandeid 71
Andmebaasiliides 71
Ühenduse loomine, päring 71
Andmete lisamine 75
SQL-
parameeter 75
Salvestatud
protseduur 76
Ülesandeid 77
Funktsiooni delegaadid 77
Funktsioonide komplekt 79
Sündmused 79
Ilmajaamad 80
Graafiline liides 83
Ülesandeid 84
Kokkuvõte 85
Sissejuhatus
Mõnigi võib ohata, et jälle üks uus programmeerimiskeel siia ilma
välja mõeldud. Teine jälle rõõmustab, et midagi uut ja huvitavat
sünnib. Kolmas aga hakkas äsja veebilahendusi kirjutama ja sai
mõnegi ilusa näite
lihtsasti kokku. Oma soovide
arvutile selgemaks
tegemise juures läheb varsti vaja teada, "mis
karul kõhus on",
et oleks võimalik täpsemalt öelda, mida ja kuidas masin tegema
peaks. Loodetavasti on järgnevatel lehekülgedel kõigile siia
sattunute jaoks midagi
sobivat . Mis liialt lihtne ja igav tundub,
sellest saab kiiresti üle lapata. Mis esimesel pilgul paistab
arusaamatu, kuid siiski vajalik, seda tasub teist korda lugeda. Ning
polegi
loota , et kõik kohe lennult külge jääks.
Selle jaoks on teksti sees koodinäited, mida saab kopeerida ja
arvutis tööle panna. Ning mõningase muutmise ja katsetamise peale
avastada , mis mille jaoks on ning kuidas seda oma kasuks rakendada
saab. Töötav näide on üks hea kindel tugipunkt nagu üks suur puu
lagendikul, kuhu oskab alati tagasi minna. Juhul, kui muutmistega on
õnnestunud oma koodilõik nii sõlme keerata, et see
sugugi enam
töötada ei taha, saab alati võtta materjalist taas algse töötava
näite ning sealt juurest katsetama hakata.
Kes
pikemalt mitmesuguseid rakendusi kirjutab, avastab mõne aja
pärast, et samas keeles kirjutatud programm võib vähemalt
esmapilgul mõnevõrra erinev välja näha sõltuvalt sellest, kas
programm käivitatakse veebist, tegutsetakse nuppudega ja
tekstiväljadega aknas, väljundiks on mobiiltelefon või
piirdub kogu tegevus tekstiaknaga. Esimesel korral võib tunduda, et oleks
nagu täiesti eri keeltes ja eri moodi kirjutamine. Ühes kohas on
alati koodi juures salapärane button1_click, teises public static
void Main ning kolmandas veel midagi muud. Aga sellest ei tasu ennast
väga häirida lasta.
Ehkki .
NETi ja C# juures on püütud eri
kohtades käivituvate rakenduste loomist sarnasemaks muuta, tuleb
siiski
kirjutamisel arvestada käivitumiskoha võimalustega. Siin
materjalis keskendume C# keele ülesehitusega seotud teemadele, mis
on ühised kõigi käivitumiskohtade puhul. Ning kasutajaliidesena
pruugime programmeerimisõpikute traditsioonilist lihtsat ning
väheste (eksimis)võimalustega tekstiakent - nii jääb rohkem aega
tähelepanu pühendada keele enese konstruktsioonidele, mida siis
edaspidi julgesti veebirakenduste juures ja soovi korral mujalgi
pruukida.
Põhivõimalused
Kui
rakendus juba mingitki elumärki annab, on see tunduvalt rohkem,
kui lihtsalt hulk koodi, mis peaks "midagi arukat" tegema.
Tunne, et suutsin programmi ise, omade roosade kätega käima panna,
on hea. Ja annab kindlustunde, et järgmisel korral saab asi ainult
paremaks minna. Kui käima on lükatud, siis edasi võib mõtelda
juba juurde panemise peale. Nii nagu talumees, kes omale krati oli
ehitanud, sai hakata talle ülesandeid andma alles siis, kui
kratt hinge sisse võttis. Muul juhul on tegemist palja põhuhunnikuga,
millele
teivas sisse löödud ja vanad kartulikorvid külge riputatud
- olgu need nii suured ja vägevad tahes. Tööle hakkamiseks on
hinge vaja. Aga hinge ei saa enne sisse puhuda, kui väikegi tervik
olemas. Ning C# puhul näeb lühim tervikprogramm välja ligikaudu
järgmine:
using
System;
class Tervitus",
arv1,
arv2, arv1*arv2);
C:\Projects\oma\naited>Arvutus
Esimene
arv:
3
Teine
arv:
5
Arvude
3 ja 5 korrutis on 15
Ülesandeid
* Küsi kahe inimese nimed ning teata, et nad on täna pinginaabrid * Küsi ristkülikukujulise toa seinte pikkused ning arvuta põranda
pindala
* Leia 30% hinnasoodustusega hinna põhjal alghind
Valikud
Ehk võimalus otsustamiseks, kui on vaja, et programm käituks kord
üht-, kord teistmoodi. Allpoololev näide koos väljundiga võiks
näidata, kuidas
tingimuslause abil tehtud valik toimib.
using
System;<
else
while(tund23);
Console.WriteLine(" TubliD:\kodu\0606\opikc#>Kordus3
Sisesta
tund vahemikus 0-23
32
Sisesta
tund vahemikus 0-23
11
Tubli,
sisestasid 11.
Ülesandeid
* Trüki arvude ruudud ühest kahekümneni
* Küsi kasutajalt viis arvu ning väljasta nende summa
* Ütle kasutajale "Osta elevant ära!". Senikaua korda
küsimust, kuni kasutaja lõpuks ise kirjutab "elevant".
Korrutustabel
... ehk näide, kuidas eelnevalt vaadatud tarkused ühe programmi
sisse kokku panna ning mis selle peale ka midagi tarvilikku teeb.
Algul on näha, kuidas otse programmi käivitamise juures ka mõned
andmed sinna kätte anda. Et kui
kirjutan Korrutustabel
4 5
siis saadakse sellest aru, et soovin korrutustabelit nelja rea ja
viie veeruga. Nende käsurea parameetrite püüdmiseks on
alamprogramm Main-il ümarsulgudes koht string[] argumendid. Kõik
käsureale kirjutatud sõnad (ka üksik number on arvuti jaoks sõna)
pannakse sinna argumentide massiivi ehk jadasse, kust neid
järjekorranumbri järgi kätte saab. Andmetüüp string[]
tähendabki, et tegemist on stringide ehk sõnede ehk tekstide
massiiviga. Kirjutades massiivi järgi .
Length , saab teada, mitu
elementi selles massiivis on - mis praegusel juhul on võrdne lisatud
sõnade arvuga käsureal. Kõik sõnad saab ka ükshaaval
järjekorranumbri järgi kätte. Arvestama peab ainult, et sõnu
hakatakse lugema numbrist 0. Nii et kui eeldatakse, et tegemist on
kahe parameetriga, siis nende kättesaamiseks peame ette andma
numbrid null ja üks.
Nagu tingimusest on näha: juhul kui argumente pole täpselt kaks,
siis kasutatakse vaikimisi ridade- ja veergude arvu ning
joonistatakse korrutustabel suurusega 10 korda 10.
Tabeli trükkimiseks on kaks for-tsüklit paigutatud üksteise sisse.
Milles pole ka midagi imelikku - iga rea juures trükitakse kõik
veerud esimesest kuni viimaseni. Ning selleks, et erinevate numbrite
arvuga arvud meie tabelit sassi ei lööks, on väljatrü. Ainsat Console.Write
argumenti (järjekorranumbriga 0) trükitakse nõnda, et ta võtaks
alati viis kohta.
using
System;<", a, b, Korruta(a, b));
Console.WriteLine(Korruta(3,
5));
C:\Projects\oma\naited>Alamprogramm
4
korda 6 on 24
15
Ülesandeid
*
Koosta alamprogramm kahe arvu keskmise leidmiseks
* Koosta alamprogramm etteantud arvu tärnide väljatrükiks.
Katseta .
* Küsi inimeselt kolm arvu. Iga arvu puhul joonista vastav kogus
tärne ekraanile
Massiivid
Kuna arvuti on mõeldud suure hulga andmetega ümber käimiseks, siis
on programmeerimiskeelte juurde mõeldud ka vahendid nende
andmehulkadega läbi käimiseks. Kõige lihtsam ja levinum neist on
massiiv. Iga elemendi poole saab tema järjekorranumbri abil
pöörduda. Algul tuleb määrata,
millisest tüübist andmeid
massiivi pannakse ning mitu kohta elementide jaoks massiivis on.
Järgnevas näites tehakse massiiv kolme täisarvu hoidmiseks.
Kusjuures nagu C-programmeerimiskeele sugulastele kombeks on,
hakatakse elemente lugema nullist. Nii et kolme massiivielemendi
puhul on nende järjekorranumbrid 0, 1 ja 2. Tahtes väärtusi sisse
kirjutada või massiivist lugeda, tuleb selleks kirja panna massiiv
nimi (praeguse juhul m) ning selle taha kandiliste sulgude sisse
järjekorranumber, millise elemendiga suhelda tahetakse.
using
System;<;
Array.Sort(m);
for(int
i=0; iMassiiv4
33
40
48
Osutid ja koopiad
Kui ühe
hariliku täisarvulise muutuja väärtus omistada teisele,
siis mõlemas muutujas on koopia
samast väärtusest ning toimingud
ühe muutujaga teise väärtust ei mõjuta. Massiividega ning
tulevikus ka muude objektidega tuleb tähelepanelikum olla. Kui üks
massiiv omistada teisele, siis tegelikult kopeeritakse vaid massiivi
osuti, mõlemale muutuja kaudu pääsetakse ligi tegelikult samadele
andmetele. Nagu järgnevas näites: massiivid m2
ja m
näitavad samadele andmetele. Kui ühe muutuja kaudu andmeid muuta,
siis muutuvad ka teise muutuja kaudu nähtavad andmed nagu väljatrüki
juures paistab. Algselt on massiivi m
ja m2
elemendid 40, 48, 33. Pärast massiivi m elemendi number 1
muutmist 32ks, on ka massiivi m2
elemendid muutunud - väärtusteks 40, 32, 33. Nõnda on suurte
andmemassiivide juures teise muutuja tegemine andmete juurde
pääsemiseks arvuti jaoks kerge ülesanne. Samas aga peab vaatama,
et vajalikke andmeid kogemata ettevaatamatult ei muudaks. <;
int[]
m2=m; //
Viide samale massiivile
Tryki(m2);
m[1]=32;
Tryki(m2);
Kui soovida, et kaks algsetest andmetest pärit massiivi on
üksteisest sõltumatud, siis tuleb teha algsest massiivist koopia
(kloon).
int[]
m3=(int[])m.Clone(); //Andmete koopia
m[1]=20;
Tryki(m3);
Pärast kloonimist muutused massiiviga m enam massiivi m3 väärtusi
ei mõjuta.
Soovides massiivi tühjendada, aitab klassi Array käsklus
Clear , mis
täisarvude puhul kirjutab etteantud vahemikus (ehk praegusel juhul
kogupikkuses, 0 ja Length-i vahel) täisarvude puhul väärtusteks
nullid .
Array.Clear(m3,
0, m3.Length); //Tühjendus
Massiivist andmete otsimiseks sobib käsklus IndexOf. Soovitud
elemendi leidumise korral väljastatakse selle elemendi
järjekorranumber. Otsitava puudumisel aga -1.
Console.WriteLine(Array.IndexOf(m,33));
Console.WriteLine(Array.IndexOf(m,17));
//
puuduv element
using
System;<,<
Console.WriteLine(m[0,
1]); //48
Console.WriteLine("M66dete
arv: "+m.
Rank );
Console.WriteLine("Ridade
arv: "+m.GetLength(0));
Console.WriteLine("Veergude
arv: "+m.GetLength(1));
//elemente
mõõtmes nr. 1
int
summa=0;
foreach(int
arv in m){
summa+=arv;
Console.WriteLine("Summa:
"+summa);
C:\Projects\oma\naited>Massiiv8
48
M66dete
arv: 2
Ridade
arv: 2
Veergude
arv: 3
Summa:
197
Ülesandeid
* Küsi kasutaja käest viis arvu ning väljasta need tagurpidises
järjekorras.
* Loo alamprogramm massiivi väärtuste aritmeetilise keskmise
leidmiseks. Katseta.
* Loo alamprogramm, mis suurendab kõiki massiivi elemente ühe
võrra. Katseta.
* Sorteeri massiiv ning väljasta selle keskmine element.
* Koosta kahemõõtmeline massiiv ning täida korrutustabeli
väärtustega. Küsi massiivist kontrollimiseks väärtusi.
Käsud mitmes failis
Suuremate programmide puhul on täiesti loomulik, et kood jagatakse
mitme faili vahel. Nii on hea jaotuse puhul kergem orienteeruda. Samuti on mugav terviklike tegevuste plokke muudesse programmidesse
ümber tõsta, kui see peaks vajalikuks osutuma. Siin näites on kaks
lihtsat arvutustehet omaette abivahendite klassi välja toodud.<);
foreach(string
linn in linnad){
Console.WriteLine(linn);
Console.WriteLine(String.Join(";
", linnad));
D:\kodu\0606\opikc#>Tekst3
Tallinn
Tartu
Narva
Tallinn;
Tartu; Narva
Ülesandeid
* Trüki inimese nime eelviimane täht
* Teata, kas
sisestatud nimi algab A-ga
* Trüki sisestatud nimi välja suurtähtedega
* Teata, kas lauses leidub sõna "ja"
* Asenda olemasolu korral "ja" sõnaga "ning" ja
teata asendusest
* Trüki välja lause kõige pikem sõna
Tekstifailid
Kui samu lähteandmeid on vaja korduvalt, siis on nad igakordse
sissetoksimise asemel mugavam sisse lugeda
failist . Samuti on
suuremate andmemahtude korral hea, kui sisendi ja väljundi andmed
jäävad alles ka masina väljalülitamise järel. Keerukama
struktuuriga andmete ning mitme üheaegse kasutaja korral (näiteks
veebirakendustes) kasutatakse enamasti andmebaasi. Käsurea- või
iseseisva graafilise rakenduse puhul on tekstifail aga lihtne ja
mugav moodus andmete hoidmiseks. Samuti on ta tarvilik juhul, kui
juba pruugitakse eelnevalt tekstifailikujul olevaid andmeid.
Kirjutamine
Andmete faili saatmiseks tuleb kõigepealt moodustada voog etteantud
nimega faili kirjutamiseks. Edasine trükk toimub juba sarnaselt
ekraaniväljundiga Write ning WriteLine käskude abil. Lõppu
kindlasti käsklus
Close , et teataks hoolitseda andmete füüsilise
kettale jõudmise eest ning antakse fail vabalt kasutatavaks ka
ülejäänud programmide jaoks. Siinse näite tulemusena tekib
käivituskataloogi lihtne fail nimega "inimesed.txt", kuhu
kirjutatakse kaks nime. Tekstiekraanil enesel pole käivitamise järel
midagi näha - aga see veel ei tähenda, nagu programm midagi ei
teeks. Lihtsalt tema töö tulemus jõuab loodavasse faili.
using
System;
using
System.IO;<;
Console.WriteLine(nimed[r.Next(nimed.Length)]);
//Juhuslik nimi
D:\kodu\0606\opikc#>Juhuarv1
0,74339002358885
11
95
Kati
Ülesandeid
* Trüki juhuslike teguritega korrutamisülesanne
* Kontrolli, kas kasutaja pakutud vastus oli õige
* Sõltuvalt vastuse õigsusest lase
arvutil pakkuda olemasolevate
hulgast valitud kiitev või julgustav kommentaar.
Omaloodud andmestruktuur
Standardandmetüüpe on .NET raamistikus kätte saada palju. Klasside
arvu loetakse tuhandetes. Sellegipoolest juhtub oma rakenduste puhul
olukordi , kus tuleb toimetada andmetega, mille hoidmiseks mugavat
moodust pole olemas. Või siis on keegi kusagil selle küll loonud,
aga lihtsalt ei leia üles.
Harilike muutujate ja massiivide abil
saab küll kõike arvutis ettekujutatavat hoida. Vahel aga on
mugavam, kui pidevalt korduvate sarnaste andmete hoidmiseks luuakse
eraldi andmetüüp. Siis on teada, et kokku kuuluvad andmed püsivad
kindlalt ühes kohas koos ning pole nii suurt muret, et näiteks kahe
firma andmed omavahel segamini võiksid minna.
Järgnevas näites kirjeldatakse selliseks omaette andmestruktuuriks
punkt tasandil, kaks täisarvulist muutujat asukohti määramas.
struct
Kui aga vähemalt üks programmeerija loodud konstruktor olemas, siis
seda nähtamatut konstruktorit ei tehta. Päriluse puhul kutsutakse
alamklassi eksemplari loomisel alati välja ülemklassi konstruktor.
Vaikimisi võtab kompilaator selleks ülemklassi parameetritega
konstruktori. Kui see aga puudub või soovitakse käivitada mõnda
muud, siis tuleb sobiva konstruktori väljakutse alamklassi juures
ära märkida. Siin märgitakse näiteks Modelli
loomise juures, et Modelli
isendi loomise juures tehakse kõigepealt valmis baasklassi (inimese) isend , kellele siis siis Modelli
enese konstruktoris vajalikud lisandused juurde pannakse. Ülemklassi
konstruktori määramine on kohe Modelli
konstruktori juures. Pärast koolonit olev base(vanus) ütleb, et
kasutatagu inimese puhul seda konstruktorit, kus tuleb täisarvuline
vanus kohe ette öelda.
public
Modell(int vanus, int uymberm66t):base(vanus){
ymberm66t=uymberm66t;
Ehkki praegu tegelikult muud võimalust
polnudki , tuleb see ikkagi
arvutile ette öelda.
using
System;<
public
override void YtleVanus(){
Console.WriteLine("Minu
vanus on "+(vanus-5)+" aastat"); <
public
void Tervita(String tuttav){
Console.WriteLine("Tere,
"+tuttav);<
public
override double KysiKorgus(){return 1.5;}<",
t.KysiRuumala(),
v.KysiRuumala());
/*
D:\kodu\0606\opikc#>AbstraktseKlassiUuring
Ruumalad
12 ja 282,743338823081
Ülesandeid
* Lisa klassile Kujund meetod KyljePindala ning abstraktne meetod
PohjaYmbermoot. Katseta - lisades vajalikud meetodid ka
alamklassidesse.
* Loo Kujundi alamklass
Risttahukas lisades talle vajalikud väljad
ja meetodid. Katseta mitmesuguste
Risttahuka eksemplaridega.
Meetodite asendus
Harilikult kirjutatakse meetodite üle katmise juures ülemklassi
meetodi ette virtual ning alamklassi juurde override. Sellisel juhul
alamklassi (siinses näites Daami)
objekti puhul kasutatakse alati seda meetodit, mis tema juurde käib
- sõltumata, millisest tüübist on muutuja, mille kaudu eksemplari
poole pöördutakse. C++ võimalusi säilitades aga on jäetud ka
teine võimalus. Meetodi võib asendada nõnda, et tema kirjeldamise
ette kirjutatakse sõna new. Sel juhul peidetakse vana meetod samuti
ära. Küll aga saab vana meetodi kätte juhul, kui objekti poole
pöörduda ülemklassi muutujast, kus vastav meetod vanal kujul
kasutusel oli. Ka annab new
meetodi ees
vabamad käed uue meetodi kirjeldamise. Kui
virtual/override
puhul pidid
parameetrid ja väljastustüüp samaks jääma, siis new
loob täiesti uue ja eelmisest sõltumatu meetodi.
Järgnevas näites on ehitatud kunstlik pärilusahel. Ülemklassiks
Inimene,
kes ütleb oma vanuse nõnda nagu see on. Inimesest
pärinenud Daam
võtab ilma pikemalt mõtlemata 5 aastat maha. Daami
alamklassiks olev
Beib keeldub üldse vanuse teatamisest ning eriti kaugele arenenud
KavalBeib
palub kasutajal ise tema vanust pakkuda. Sõna sealed
klassi juures näitab, et sellest klassist ei lubata enam edasi
pärida. Selline määrang aitab kompilaatoril koodi optimeerida.
Alljärgnevalt katsetatakse, millist tüüpi muutuja kaudu millise
tegeliku objekti poole pöördumisel milline tulemus saadakse. Et
omistamine on võimalik ainult ülemklassi suunas, siis igaühe neist
saab omistada Inimese
tüüpi muutujale. Mida tase edasi, seda vähem on omistusvõimalusi.
Katsetamise käigus antakse Beiblastele
vanuseks 17 aastat, teistele 40. Ning jälgitakse, milline meetod
millise muutuja kaudu väljakutsel käima läheb. Kõige pikem ja
keerukam lugu on Kavala Beibega. Et ta on pärimispuus kõige
kaugemal, siis teda on võimalik omistada kõikide selles puus
olevate tüüpidega muutujatele. Enese tüübi puhul küsib ta
vanuseks 19, nagu käsklusele kohale. Ka lihtsalt Beib-tüüpi
muutuja kaudu küsib ta enesele 19, sest klassi Beib
meetod YtleVanus
on virtual ning tegelikult käima läheb objekti enese ehk klassis
KavalBeib
loodud meetod.
Edasi muutub lugu keerulisemaks. Daami-muutujast
välja kutsutav Kavala
Beibe vanus tuleb 12, sest ta lahutab aastad
maha nagu
Daamile kohane. Ning ka hariliku inimese kaudu tuleb 12,
sest virtual-piiritleja
kaudu võetakse käsklus võimalikult objekti enese lähedalt.
using
System;<
public
override void YtleVanus(){
Console.WriteLine("Minu
vanus on "+(vanus-5)+" aastat"); <
new
public virtual void YtleVanus(){
Console.WriteLine("Minu
vanus pole sinu asi, vot!");<
public
override void YtleVanus(){
Console.WriteLine("
Arva?", vanus+2);<<
//value on sisendväärtuse nimi<<
return
(string)esinemised[kuupaev];<
public
int Minut(){return minut;}
public
void tryki(){
Console.WriteLine(",
tund, minut);
public
static Kellaaeg operator+(Kellaaeg k1, Kellaaeg k2){
return
new Kellaaeg(k1.tund+k2.Tund(), k1.minut+k2.Minut());<
public
int Minut(){return minut;}
public
void tryki(){
Console.WriteLine(",
tund, minut);
public
static Kellaaeg operator+(Kellaaeg k1, Kellaaeg k2){
return
new Kellaaeg(k1.Tund()+k2.Tund(), k2.Minut()+k2.Minut());
public
static implicit operator int(Kellaaeg k){
return
k.Tund()*60+k.Minut();
public
static explicit operator double(Kellaaeg k){
//kohustuslik
muunduse näitamine
return
k.Tund()+k.Minut()/60.0;
public
static explicit operator Kellaaeg(int minutid){
return
new Kellaaeg(minutid/60, minutid%60);<
catch(FormatException probleem){
Console.WriteLine("Viga
sisendandmetega: "+probleem.Message);
}
catch(OverflowException){
Console.WriteLine("Liiga
suur arv.");
}
catch(Exception){
Console.WriteLine("Tundmatu
probleem");
}catch(FormatException
probleem){
Console.WriteLine("Viga
teisendusel: "+probleem.Message);
D:\kodu\0606\opikc#>Erind4
Palun
arv:
5
Kirjutati:
5
Erindi heitmine
Sugugi ei pea leppima vaid arvuti enese antud veateadetega. Kui ikka
oma programmis paistab, et midagi läheb väga käest ära, siis on
vahel kasulik ise märku anda, et sarnaselt edasi toimida pole enam
mõtet. Näiteks, kui arvutuse algandmed on ilmselgelt valed
(kolmnurga üks külg pikem kui teised kaks kokku), siis võib
julgesti enne arvutamist teada anda milles asi ning heita
selleteemalise erindi. Edasi on juba vastavat koodilõiku
väljakutsuva programmeerija ülesandeks silumise käigus kindlaks
teha, millest probleem tekkis ning vastavalt edasi toimida.
Siin näites lihtsalt keelati sajast suuremate arvude sisestus. Kui
arv juhtub liiga suur olema, heidetakse erind. Lihtsuse mõttes pole
oma tüüpi loodud, kasutatakse SystemExceptionit.
Kuigi - vähegi pikema programmi selguse huvides oleks oma tüübi
loomine kasulik. Et peaprogrammis pole SystemExceptioni
jaoks veapüünist, siis tuleb ette süsteemne veateade, mille järele
programmeerija peab juba ise edasi mõtlema, mida edasi teha.
using
System;
Console.WriteLine("Viga
teisendusel: "+probleem.Message);
D:\kodu\0606\opikc#>Erind5
Palun
arv:
789
Unhandled
Exception: System.SystemException: Liiga suur arv
at
Erind5.LoeArv()
at
Erind5.Main(String[] arg)
Ülesandeid
* Katseta näite "Erind2" juures. Vaata, kuidas käitub
programm juhul, kui ette anda veatu arv.
* Muuda täisarvu käsklused reaalarvu omadeks ja leia, mis kasutamisel muutus.
* Loo tsükkel, mille abil küsitakse arvu senikaua, kuni saadakse
sobiv sisend.
* Muuda näidet "Erind5" nõnda, et see annaks
peaprogrammis viisaka seletuse ka omaheidetud erindi korral.
* Loo erindeid kasutades programm, mis suurendaks faili arv.txt sisu
ühe võrra. Kui fail puudub, või failis pole arv, siis antakse
selgitusega veateade.
* Kui failis olev arv ületab 365, siis anna välja omapoolne erind
ning püüa sellele reageerida.
Andmekollektsioonid
Andmetega ümber käimisele kulub märgatav osa arvutite ja
programmeerija ajast. 2000 aasta paiku arvati selleks osaks olema
ligikaudu kolmandik. Nüüd ehk veidi vähem, kuid tähtsus on ikka
alles jäänud. Et põhioperatsioonidele ei kuluks liialt palju
tähelepanu, selleks on programmeerimiskeeltes välja mõeldud valmis
vahendid andmeoperatsioonideks. Nii ka C# puhul.
ArrayList
Hea lihtne koht andmete hoidmiseks ja kätte saamiseks. Võrreldes
tavalise massiiviga pole vaja elementide arvu kohe ette määrata.
ArrayListi
objekt hoolitseb ise selle eest, et oleks parajalt ruumi sissepandud
andmete hoidmiseks. Iga Add-käsklusega
lisatakse sissepandud väärtus olemasolevate lõppu. Käsuga
Contains
võib kontrollida otsitava elemendi olemasolu. Count näitab elementide arvu. Insert-käsklus
lisab uue elemendi soovitud järjekorranumbriga kohale, lükates
ülejäänud ühe koha võrra edasi. IndexOf
aitab soovitud väärtust otsida. Viimase puudumisel tagastatakse
järjekorranumbrina -1. Ning foreach-tsükkel
sobib kõigi elementide läbi käimiseks.
using
System;
using
System.Collections;<",
ht["Kati"]);
Kontrollitakse, kas Kati on nimede hulgas olemas. Kui jah, siis
trükitakse ta hinne.
ht["Sass"]=((int)ht["Sass"])-1;
Sassi hinnet alandatakse ühe võrra.
ht.Remove("Mati");
Mati eemaldatakse nimekirjast.
Tahtes kõik andmed kätte saada, aitab jälle enumeraator. Ainult et
igal enumeraatori elemnendil on võti ja väärtus. Siin trükitakse
nad lihtsalt välja, aga eks igaüks tea ise paremini, mida tal oma
programmis nendega kõige mõistlikum teha on.
IDictionaryEnumerator
enumr=ht.GetEnumerator();
while(enumr.MoveNext()){
string
eesnimi=enumr.Key as string;
int
hinne=(int)enumr.Value;
Console.WriteLine(", eesnimi, hinne);
Ning kogu näide tervikuna.
using
System;
using
System.Collections;<",
ht["Kati"]);
ht["Sass"]=((int)ht["Sass"])-1;
ht.Remove("Mati");
IDictionaryEnumerator
enumr=ht.GetEnumerator();
while(enumr.MoveNext()){
string
eesnimi=enumr.Key as string;
int
hinne=(int)enumr.Value;
Console.WriteLine(", eesnimi, hinne);
D:\kodu\0606\dotnet>Kollektsioon4
5
Kati:
5
Juku:
3
Sass:
3
Ülesandeid
* Küsi kasutajalt arve, kuni ta sisestab nulli. Salvesta ArrayListi.
Väljasta need arvud tagurpidises järjekorras.
* Proovi eelmine ülesanne lahendada LinkedListi abil. Omadus Last
annab loetelu viimase elemendi, RemoveLast() kustutab viimase.
* Loe tekstifailist arvud, väljasta nad sorteerituna teise
tekstifaili.
* Loe tekstifailist arvud. Teise tekstifaili väljasta, mitu korda
iga arv esines.
Andmebaasiliides
Ühenduse loomine, päring
Kui juhtub, et arvutis või kättesaadavas võrgus on kasutada mõni andmebaas , siis suure tõenäosusega saab sealsete andmete poole
pöörduda ja omakoostatud C#-programmi kaudu. Ühe-kaks väärtust
võib olla lihtsam baasi enese juurde käiva halduskeskkonna abil
paika sättida. Kui aga andmeid on pidevalt ja kümneid. Või siis
pole andmetega tegelejaks mitte teie ise, vaid keegi muu. Või soovite , et teated toimingutest jõuaksid automaatselt andmebaasi –
sellisel juhul on kasulik koostatud programmilõigu peale mõelda.
Esimene näide eeldab, et masinas nimega RINDE on üles seatud
SQL-serveri eksemplar nimega SQLEXPRESS. Ning sinna sisse on loodud
andmebaas nimega proovibaas. Ja selles baasis on tabel nimega
"inimesed". Ning kõige esimeseks tulbaks inimeste tabelis
on eesnimi. Sellisel juhul, kui kõik etapid õnnestuvad, võib
loeteluna näha tabelis olevate inimeste eesnimesid. Eks igaüks saab
masina, tabeli ja muud andmed enese omade vastu vahetada, ning ongi
lihtne üldkasutatav näide, kuidas vajalikke andmeid baasist oma
programmi sisse välja meelitada. Mõningad lähemad seletused toimuva kohta.
Muutujasse constr
( connection string) salvestatakse kõigepealt seletus programmi
jaoks, kust andmebaas üles leida.
string
constr="Data Source=RINDE\\SQLEXPRESS;"+
"Initial
Catalog=proovibaas; "+
"Integrated Security =SSPI; Persist Security Info= False ";
Eraldi muutujasse pannakse kirja SQL-lause, mille abil loodame
andmeid küsida.
string
lause=" SELECT eesnimi FROM inimesed";
Järgnevalt luuakse ja avatakse ühendus andmebaasiga. See toiming
võib mõnikord märgatava hulga sekundeid aega võtta.
SqlConnection
cn=new SqlConnection(constr);
cn.Open();
Et arvuti oskaks andmeid küsida, selleks luuakse SQL-käsklus, kus
baasiühendusega seotakse SQL-lause. Siinse vaheetapi juures on
keerulisematel juhtudel näiteks võimalus käsklusele parameetreid
lisada. Siin aga piirduma lihtsama variandiga .
SqlCommand
cm = new SqlCommand(lause, cn);
Saabuvate andmete püüdmiseks on SQL-serveri puhu SqlDataReader.
SqlCommandi
käsklus ExecuteReader
väljastab vastavat tüüpi objekti, mille kaudu programm omakorda
saab andmeid küsima hakata. Selline vaheetapp on vajalik, et
programm saaks vajadusel hakkama ka väga suure andmehulgaga. Kui
andmete vahendamise jaoks on omaette objekt, kelle kaudu vaikselt
andmeid küsima hakatakse, siis ei pea programm saabuvaid andmeid
kõiki korraga enesele mällu laadima , vaid jätab selle töö
SqlDataReaderi
hooleks.
SqlDataReader
reader=cm.ExecuteReader();
Alles edaspidises tsüklis võetakse inimeste andmed ükshaaval ja
toimetatakse nendega. Käsklus Read
viib lugemiskursori ühe rea võrra edasi – esimesel korral siis
esimese inimese juurde. Ning käsklus GetString
annab etteantud järjekorranumbriga veerust andmed kätte. Nagu näha,
hakkavad veerud lugema nullist.
while(reader.Read()){
Console.WriteLine(reader.GetString(0));
Iga ühenduse kasutamise järel on viisakas see kinni panna. Mis
juhtub, kui ühendus lahti jäetakse sõltub juba otsestest oludest .
Aga kinni pandult on ressursside raiskamise mure programmeerija käest
ära.
cn.Close();
Ning
kood tervikuna.
using
System;
using
System.Data.SqlClient;<; "+
"DBQ=d:\\kodu\\0606\\dotnet\\proovibaas2.mdb;
"+
"Trusted_Connection=yes";
string
lause="SELECT mark FROM autod";
OdbcConnection
cn=new OdbcConnection(constr);
cn.Open();
OdbcCommand
cm = new OdbcCommand(lause, cn);
OdbcDataReader
reader=cm.ExecuteReader();
while(reader.Read()){
Console.WriteLine(reader.GetString(0));
cn.Close();
Kui aga tegemist pole Accessiga, vaid mõne muu
andmebaasikeskkonnaga, mis aga sellegipoolest on Control Paneli kaudu
ODBC alt kättesaadav, siis ka sealtkaudu saab oma andmetele ligi.
Olgu näiteks olemas juba toimiv veebibaas PHP ja MySQLi abil –
kuhu aga tahetakse ka kohalikus arvutis toimiva programmi kaudu pilku
peale visata . Tehes see algne baas ODBC kaudu nähtavaks nime all
näiteks proovibaas2, näeks sidepidamisprogramm välja nagu
järgnevalt. Tasub tähele panna, et võrreldes SQL-serveriga on
kasutatavateks objektiklassideks OdbcConnection
ja OdbcCommand.
Aga andmetega ümber käiakse ikka samamoodi.
using
System;
using
System.Data.Odbc;<
Ja ongi kogu näide, mida võib edaspidi sarnaste rakenduste loomisel
aluseks võtta.
using
System;
public
delegate void Sisenemine();
namespace
Ilmaandmed{
public
delegate void IlmajaamaTeade(IlmajaamaParameetrid p);
class
Syndmused2{
static
void HarilikTeave(IlmajaamaParameetrid p){
Console.WriteLine(p);
static
void HoiatusTeave(IlmajaamaParameetrid p){
Console.WriteLine(" Hoiatus : "+p);
public
static void Main(string[] arg){
Ilmajaam [] jaamad =new Ilmajaam[10];
for(int
i=0; i
Kõik kommentaarid