Browse Source

Add content

master
Pekka Helenius 4 years ago
parent
commit
ab0ac27483
24 changed files with 2736 additions and 2 deletions
  1. +44
    -0
      1_fundamentals/1_for-loop.md
  2. +126
    -0
      1_fundamentals/2_multiple-functions.md
  3. +56
    -0
      1_fundamentals/3_hypothenuse.md
  4. +88
    -0
      2_classes-and-methods/1_point-class.md
  5. +88
    -0
      2_classes-and-methods/2_point-class-service.md
  6. +89
    -0
      2_classes-and-methods/3-point-class-usage.md
  7. +153
    -0
      3_creating-class/1_customer-account.md
  8. +159
    -0
      3_creating-class/2_object-array.md
  9. +70
    -0
      4_pointers-vars-and-memory-handling/1_pointer-as-param.md
  10. +64
    -0
      4_pointers-vars-and-memory-handling/2_refvar-as-param.md
  11. +108
    -0
      4_pointers-vars-and-memory-handling/3_dynamic-memory.md
  12. +71
    -0
      5_object-lifetime/1_default-constructor.md
  13. +86
    -0
      5_object-lifetime/2_parameter-constructor.md
  14. +76
    -0
      5_object-lifetime/3_destructor.md
  15. +160
    -0
      6_uml-principles/1_team-players.md
  16. +143
    -0
      7_class-relations/1_card-deck.md
  17. +118
    -0
      7_class-relations/2_car-human-association.md
  18. +181
    -0
      8_inheritance/1_class-inheritance.md
  19. +134
    -0
      8_inheritance/2_abstract-class.md
  20. +190
    -0
      8_inheritance/3_inherited-shape.md
  21. +182
    -0
      8_inheritance/4_different-shapes.md
  22. +110
    -0
      9_shallow-and-deep-copy/1_copy-operations.md
  23. +194
    -0
      9_shallow-and-deep-copy/2_dogs-and-humans.md
  24. +46
    -2
      README.md

+ 44
- 0
1_fundamentals/1_for-loop.md View File

@ -0,0 +1,44 @@
## 1 for-lause
**Tehtävä:**
Tee ohjelma, joka kysyy käyttäjältä kokonaisluvun n (n>0) ja tulostaa monitorille luvut 1,2,3..n allekkain. Tee ohjelma käyttäen for-lausetta.
Example output:
```
Anna kokonaisluku:2
1
2
```
**Vastaus:**
```
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Anna kokonaisluku:";
cin >> n;
if (cin.fail()) {
cerr << "Syötä luku" << endl;
exit(1);
}
if (n<=0) {
cerr << "Luku ei voi olla 0 tai pienempi" << endl;
exit(1);
} else {
for (int i=1; i<n+1; i++) {
cout << i << endl;
}
}
return 0;
}
```

+ 126
- 0
1_fundamentals/2_multiple-functions.md View File

@ -0,0 +1,126 @@
## 2 Funktiot suurin ja pienin
**Tehtävä:**
Alla oleva ohjelma kysyy käyttäjältä kolme kokonaislukua ja tulostaa syötetyistä luvuista suurimman ja pienimmän näytölle. Tehtävänäsi on kirjoittaa ohjelmasta puuttuvat funktiot (suurin() ja pienin()), jotka saavat parametreina käyttäjän syöttämät kokonaisluvut ja palauttavat nimensä mukaiset kokonaisluvut.
Täydennettävä ohjelma:
```
#include <iostream>
using namespace std;
int suurin(int eka, int toka, int kolmas);
int pienin(int eka, int toka, int kolmas);
int main()
{
int luku1, luku2, luku3, suurinLuku, pieninLuku;
cout << "Syötä ensimmäinen kokonaisluku:";
cin >> luku1;
cout << "Syötä toinen kokonaisluku:";
cin >> luku2;
cout << "Syötä kolmas kokonaisluku:";
cin >> luku3;
suurinLuku = suurin(luku1, luku2, luku3);
pieninLuku = pienin(luku1, luku2, luku3);
cout << "Syöttämistäsi luvuista suurin oli " << suurinLuku;
cout << " ja pienin " << pieninLuku << "." << endl;
}
```
Huom! Sinun tulee siis kirjoittaa ainoastaan koodista puuttuvat funktiot.
Example output:
```
Syötä ensimmäinen kokonaisluku:99
Syötä toinen kokonaisluku:88
Syötä kolmas kokonaisluku:66
Syöttämistäsi luvuista suurin oli 99 ja pienin 66.
```
**Vastaus:**
```
/*
Alla oleva ohjelma kysyy käyttäjältä kolme kokonaislukua ja tulostaa syötetyistä luvuista
suurimman ja pienimmän näytölle. Tehtävänäsi on kirjoittaa ohjelmasta puuttuvat funktiot
(suurin() ja pienin()), jotka saavat parametreina käyttäjän syöttämät kokonaisluvut
ja palauttavat nimensä mukaiset kokonaisluvut.
Huom! Sinun tulee siis kirjoittaa ainoastaan koodista puuttuvat funktiot. Älä kopioi alla olevaa koodia palautuskenttään.
Example output:
Syötä ensimmäinen kokonaisluku:99
Syötä toinen kokonaisluku:88
Syötä kolmas kokonaisluku:66
Syöttämistäsi luvuista suurin oli 99 ja pienin 66.
*/
#include <iostream>
//** Pre-defined code in the assignment **//
using namespace std;
int suurin(int eka, int toka, int kolmas);
int pienin(int eka, int toka, int kolmas);
int main()
{
int luku1, luku2, luku3, suurinLuku, pieninLuku;
cout << "Syötä ensimmäinen kokonaisluku:";
cin >> luku1;
cout << "Syötä toinen kokonaisluku:";
cin >> luku2;
cout << "Syötä kolmas kokonaisluku:";
cin >> luku3;
suurinLuku = suurin(luku1, luku2, luku3);
pieninLuku = pienin(luku1, luku2, luku3);
cout << "Syöttämistäsi luvuista suurin oli " << suurinLuku;
cout << " ja pienin " << pieninLuku << "." << endl;
}
//** ---------- ---------- ---------- **//
/*
These functions contain almost duplicate code
Should be get rid of the duplication
*/
int suurin(int luku1, int luku2, int luku3) {
int i, luvut[3] = {luku1, luku2, luku3};
int sluku = luvut[0];
for (i=0; i<3; i++)
{
if(luvut[i] > sluku)
{
sluku = luvut[i];
}
}
return sluku;
}
int pienin(int luku1, int luku2, int luku3) {
int i, luvut[3] = {luku1, luku2, luku3};
int pluku = luvut[0];
for (i=0; i<3; i++)
{
if (luvut[i] < pluku)
{
pluku = luvut[i];
}
}
return pluku;
}
```

+ 56
- 0
1_fundamentals/3_hypothenuse.md View File

@ -0,0 +1,56 @@
## 3 Hypotenuusan laskeminen
**Tehtävä:**
Tee ohjelma, joka laskee suorakulmaisen kolmion hypotenuusan pituuden ohjelmaan syötettyjen kateettien pituuksien perusteella. Kateettien pituuksien odotetaan olevan kokonaislukuja, kun taas hypotenuusan pituus sijoitetaan double-muuttujaan.
**Vihje:**
Neliöjuuren voi laskea seuraavasti (palauttaa double-tyypin arvon):
```
double juuri = sqrt(double_luku);
```
Tarvitset cmath-kirjastoa.
Example output:
```
Anna ensimmäinen kateetti:34
Anna toinen kateetti:11
Hypotenuusan pituus: 35.7351
```
**Vastaus:**
```
#include <cmath>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
int katYksi, katKaksi;
double double_luku, juuri;
cout << "Anna ensimmäinen kateetti:";
cin >> katYksi;
if (cin.fail()) exit(1);
cout << "Anna toinen kateetti:";
cin >> katKaksi;
if (cin.fail()) exit(1);
// The assignment expects strictly formatted output
double_luku = (double)( pow(katYksi, 2) + pow(katKaksi, 2) );
juuri = sqrt(double_luku);
cout << "Hypotenuusan pituus:" << " " << setprecision(4) << fixed << juuri << endl;
return 0;
}
```

+ 88
- 0
2_classes-and-methods/1_point-class.md View File

@ -0,0 +1,88 @@
## 1 Piste-luokan määritteleminen
**Tehtävä:**
Olet luvun teoriasivuja lukiessa oppinut, kuinka luokkia yksinkertaisimmillaan määritellään. Nyt tehtävänäsi on laatia määrittely luokalle "Piste", joka sisältää kaksi jäsenmuuttujaa: x- ja y-koordinaatit.
Kyseiset tietojäsenet määritellään kokonaisluvuiksi ja ne nimetään seuraavasti: "x_" ja "y_". Koska pelkin tietojäsenin varustettu luokka on käytännössä käyttökelvoton, esitellään luokan määrittelyssä lisäksi äsenfunktiot "AsetaX", "AsetaY", "Siirra" ja "KerroPaikka".
Koordinaattien arvojen asettamiseen käytettävään funktioita "AsetaX" ja "AsetaY". Funktiot ottavat vastaan niitä kutsuttaessa yhden kokonaislukuarvon sijoittaen tämän arvon funktiosta riippuen, joko jäsenmuuttujaan "x_", tai "y_". Asetusfunktiot eivät palauta arvoja.
Jäsenfunktio "Siirra" ottaa vastaan kaksi kokonaislukuarvoa: x:n ja y:n siirtymät edellisessä järjestyksessä. "Siirra" liikuttaa pisteen koordinaatteja sille välitettyjen parametrien mukaisen määrän. "Siirra" ei palauta arvoa.
Pisteen paikan kertomisesta vastaava funktio tulostaa pisteen koordinaatit allekkain esimerkkitulosteen mukaisesti. Funktiolle "KerroPaikka" ei välitetä parametreja, eikä se palauta arvoa.
Muista, että tässä tehtävässä sinun tulee laatia vain luokan määrittely, joka tarkistetaan liittämällä se valmiisiin jäsenfunktioihin ja pääohjelmaan, joka käyttää luokan palveluita. Muista myös, että luokan määrittelyssä jäsenfunktiot on määriteltävä julkisiksi, kun taas jäsenmuuttujien tulee olla ns. sisäisiä.
Example output:
```
Pisteolio muodostettu ja koordinaatit asetettu.
Pisteen x-koordinaatti: 34
Pisteen y-koordinaatti: 100
Pistettä siirretty.
Pisteen x-koordinaatti: 54
Pisteen y-koordinaatti: 67
```
**Vastaus:**
```
#include<iostream>
using namespace std;
class Piste
{
public:
void AsetaX(int x);
void AsetaY(int y);
void Siirra(int x, int y);
void KerroPaikka();
private:
int x_;
int y_;
};
//** Pre-defined code in the assignment **//
void Piste::AsetaX(int x)
{
x_ = x;
}
void Piste::AsetaY(int y)
{
y_ = y;
}
void Piste::Siirra(int x, int y)
{
x_ = x_ + x;
y_ = y_ + y;
}
void Piste::KerroPaikka()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
int main()
{
Piste pikseli;
pikseli.AsetaX(34);
pikseli.AsetaY(100);
cout << "Pisteolio muodostettu ja koordinaatit asetettu.\n"
pikseli.KerroPaikka();
pikseli.Siirra(20, -33);
cout << "Pistettä siirretty.\n"
pikseli.KerroPaikka();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 88
- 0
2_classes-and-methods/2_point-class-service.md View File

@ -0,0 +1,88 @@
## 2 Piste-luokalle palvelut
**Tehtävä:**
Edellisessä tehtävässä sinun piti toteuttaa luokan "Piste" määrittely. Nyt tehtävänäsi on toteuttaa luokan määritellyssä esitellyt jäsenfunktiot: AsetaX, AsetaY, KerroPaikka ja Siirra.
Luokassa määriteltyjen koordinaattien asettamisesta vastaavat jäsenfunktiot ottavat vastaan kokonaisluvun, jonka funktio sijoittaa sen vastulla olevaan jäsenmuuttujaan. Nämä funktiot eivät palauta arvoa.
Pisteen paikan kertomisesta vastaava jäsenfunktio ei ota vastaan parametreja, eikä palauta arvoa. Jäsenfunktion tehtävänä on tulostaa piste-olion koordinaatit esimerkkitulosteen mukaisesti. Funktio tulostaa ensin x-koordinaatin ja tämän alle y-koordinaatin.
Jäsenfunktio "Siirra" ottaa vastaan x:n ja y:n siirtymän kokonaislukuarvoina annetussa järjestyksessä. Siirtäminen muuttaa jäsenmuuttujien arvoa annettujen siirtymien mukaisesti. "Siirra" ei palauta arvoa sitä kutsuvalle ohjelman osalle.
Huomaa, että esimerkkitulosteessa rivit "Pisteolio muodostettu ja koordinaatit asetettu.", sekä "Pistettä siirretty." ovat vastaustasi testaavan ohjelman aikaan saamia.
Example output:
```
Pisteolio muodostettu ja koordinaatit asetettu.
Pisteen x-koordinaatti: 34
Pisteen y-koordinaatti: 100
Pistettä siirretty.
Pisteen x-koordinaatti: 54
Pisteen y-koordinaatti: 67
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Piste
{
public:
void KerroPaikka();
void AsetaX(int x);
void AsetaY(int y);
void Siirra(int x, int y);
private:
int x_;
int y_;
};
//** ---------- ---------- ---------- **//
void Piste::AsetaX(int x)
{
x_ = x;
}
void Piste::AsetaY(int y)
{
y_ = y;
}
void Piste::KerroPaikka()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
void Piste::Siirra(int x, int y)
{
x_ = x_ + x;
y_ = y_ + y;
}
//** Pre-defined code in the assignment **//
int main()
{
Piste pikseli;
pikseli.AsetaX(34);
pikseli.AsetaY(100);
cout << "Pisteolio muodostettu ja koordinaatit asetettu.\n"
pikseli.KerroPaikka();
pikseli.Siirra(20, -33);
cout << "Pistettä siirretty.\n"
pikseli.KerroPaikka();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 89
- 0
2_classes-and-methods/3-point-class-usage.md View File

@ -0,0 +1,89 @@
## 3 Piste-luokan käyttäminen
**Tehtävä:**
Luvun viimeisessä ohjelmointitehtävässä tehtävänäsi on laatia pääohjelma, joka käyttää Piste-luokan palveluita. Laatimasi pääohjelman tulee kysyä kaksi kokonaislukua (x- ja y-koordinaatit), muodostaa olio luokasta "Piste", asettaa saadut koordinaatit olioon ja lopulta tulostaa koordinaatit hyödyntäen luokan palvelua "KerroPaikka".
Pääohjelman käyttäjä syöttää koordinaatit näppäimistöltä ja ne voidaan ottaa vastaan cin-oliolla. Tarkastelemalla tehtävän esimerkkitulostusta näet, millaisia tulosteita pääohjelman on muodostettava.
Huomaa, että sinun tulee kirjoittaa vain pääohjelma, joka alkaa merkinnällä "int main()" ja päättyy sulkevaan aaltosulkeeseen.
Omasta nurkasta voit tarkastella edellisiä tehtäviä palauttaaksesi mieleen, kuinka Piste-luokka on toteutettu.
Example output:
```
Syötä x-koordinaatti:39
Syötä y-koordinaatti:23
Pisteolio muodostettu ja koordinaatit asetettu.
Pisteen x-koordinaatti: 39
Pisteen y-koordinaatti: 23
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Piste
{
public:
void KerroPaikka();
void AsetaX(int x);
void AsetaY(int y);
void Siirra(int x, int y);
private:
int x_;
int y_;
};
void Piste::AsetaX(int x)
{
x_ = x;
}
void Piste::AsetaY(int y)
{
y_ = y;
}
void Piste::Siirra(int x, int y)
{
x_ = x_ + x;
y_ = y_ + y;
}
void Piste::KerroPaikka()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
//** ---------- ---------- ---------- **//
int main()
{
Piste taso;
int xk, yk;
cout << "Syötä x-koordinaatti:";
cin >> xk;
if (cin.fail()) exit(1);
cout << "Syötä y-koordinaatti:";
cin >> yk;
if (cin.fail()) exit(1);
taso.AsetaX(xk);
taso.AsetaY(yk);
cout << "Pisteolio muodostettu ja koordinaatit asetettu." << endl;
taso.KerroPaikka();
return 0;
}
```

+ 153
- 0
3_creating-class/1_customer-account.md View File

@ -0,0 +1,153 @@
## 1 Luokan toteuttaminen: Asiakastili
**Tehtävä:**
Tämän luvun ensimmäisessä ohjelmointitehtävässä tehtävänäsi on laatia luokka "Asiakastili". Luokan palveluita käytetään hyväksi alkeellisessa pankkiohjelmassa, jolla ohjelman käyttäjä voi selata asiakastietoja ja muuttaa asiakkaiden saldoja annetun tilinumeron perusteella. Pankkiohjelma on toteutettu pääohjelmassa, jonka toiminnasta sinun ei tarvitse välittää vaan riittää, että ohjelma saa tarvitsemansa palvelut alla esitettyjen määritelmien mukaan. Tehtävästä suoriutuminen vaatii huolellisuutta, kuten aina ohjelmoitaessa luokkia annetun toimeksiannon / määrittelyn mukaan.
Luokka "Asiakastili" sisältää kolme jäsenmuuttujaa: kokonaislukutyypin muuttujat asiakkaan tilinumerolle ja saldolle, sekä string-tyypin muuttujan asiakkaan nimelle. Jäsenmuuttujat ovat luokan sisäisiä, joten voit nimetä ne haluamallasi tavalla.
Luokan kaikki jäsenfunktiot ovat julkisia ja niistä ensimmäinen, "LisaaAsiakas" saa parametrinä asiakkaan tilinumeron, saldon ja nimen sijoittaen nämä olion jäsenmuuttujiin. Parametrit välitetään jäsenfunktiolle esitetyssä järjestyksessä. "LisaaAsiakas" ei palauta arvoa sitä kutsuvalle ohjelman osalle.
Toinen jäsenfunktio, "NaytaTiedot" ei ota vastaan parametrejä, eikä palauta mitään arvoa. Funktion tehtävävänä on tulostaa näytölle kolme riviä, jotka sisältävät olion jäsenmuuttujien arvot esimerkkitulosteen mukaisella tavalla.
Kolmas jäsenfunktio, "MuutaSaldoa" ottaa vastaan kokonaislukuparametrin, jonka se sijoittaa olion saldoa kuvaavaan jäsenmuuttujaan. Funktio ei palauta arvoa.
Luokan viimeinen jäsenfunktio, "VertaaTiliNro" saa parametrinä kokonaislukuarvon, jota verrataan olion tilinumeroon. Mikäli parametrinä välitetty tilinumero on sama kuin olion tiedoissa sijaitseva, palauttaa jäsenfunktio kokonaislukuarvon 1. Jos taas annettu ja olion tilinumero eivät täsmää, palauttaa jäsenfunktio kokonaislukuarvon 0.
Luokan palveluita hyödyntävän pankkiohjelman toiminta perustuu luokasta muodostettavaan automaattiseen oliotaulukkoon, jonka avulla eri asiakkaiden tietoja käsitellään. Ohjelmisto toimii kokonaisuutena, kun sinun vastuulla oleva luokka tarjoaa siltä pyydetyt palvelut.
Example output:
```
1: Näytä asiakkaan tiedot.
2: Muuta asiakkaan saldoa.
Lopetus negatiivisella luvulla.
Valitse toiminto: 1
Anna tilinumero:
45678
Tilinumero: 45678
Asiakkaan nimi: Riku Rikas
Tilin saldo: 99834
1: Näytä asiakkaan tiedot.
2: Muuta asiakkaan saldoa.
Lopetus negatiivisella luvulla.
Valitse toiminto: 2
Anna tilinumero: 89892
Anna uusi saldo: 234
Antamaasi tilinumeroa ei löytynyt.
1: Näytä asiakkaan tiedot.
2: Muuta asiakkaan saldoa.
Lopetus negatiivisella luvulla.
Valitse toiminto: 0
Ohjelma lopetetaan.
```
**Vastaus:**
```
#include<iostream>
using namespace std;
class Asiakastili
{
public:
void LisaaAsiakas(int tilinumero, int saldo, string nimi);
void NaytaTiedot();
int MuutaSaldoa(int saldo);
int VertaaTiliNro(int vertaatilinumero);
private:
int tilinumero_, saldo_;
string nimi_;
};
void Asiakastili::LisaaAsiakas(int tilinumero, int saldo, string nimi)
{
tilinumero_ = tilinumero;
saldo_ = saldo;
nimi_ = nimi;
}
void Asiakastili::NaytaTiedot()
{
cout << "Tilinumero: " << tilinumero_ << endl << "Asiakkaan nimi: " << nimi_ << endl << "Tilin saldo: " << saldo_ << endl;
}
int Asiakastili::MuutaSaldoa(int saldo)
{
saldo_ = saldo;
return saldo_;
}
int Asiakastili::VertaaTiliNro(int tilinumero)
{
if (tilinumero_ == tilinumero)
{
return 1;
}
else
{
return 0;
}
}
//** Pre-defined code in the assignment **//
int main() {
int valinta, tilin_nro, uusi_saldo, i, loytyi = 0;
Asiakastili asiakasrekisteri[5];
asiakasrekisteri[0].LisaaAsiakas(12345, 312, "Mikko Möttönen");
asiakasrekisteri[1].LisaaAsiakas(23456, 23, "Anni Manninen");
asiakasrekisteri[2].LisaaAsiakas(34567, 112, "Simo Siili");
asiakasrekisteri[3].LisaaAsiakas(45678, 99834, "Riku Rikas");
asiakasrekisteri[4].LisaaAsiakas(56789, 7500, "Marja Mallikas");
do {
cout << endl << "1: Näytä asiakkaan tiedot." << endl;
cout << "2: Muuta asiakkaan saldoa." << endl;
cout << "Lopetus negatiivisella luvulla." << endl;
cout << "Valitse toiminto: ";
cin >> valinta;
if(valinta == 1) {
cout << "Anna tilinumero: " << endl;
cin >> tilin_nro;
for(i=0; i<5; i++) {
if(asiakasrekisteri[i].VertaaTiliNro(tilin_nro)==1) {
loytyi = 1;
asiakasrekisteri[i].NaytaTiedot();
}
}
if(loytyi == 0) {
cout << "Antamaasi tilinumeroa ei löytynyt." << endl;
}
loytyi = 0;
} else if(valinta == 2) {
cout << "Anna tilinumero: ";
cin >> tilin_nro;
cout << "Anna uusi saldo: ";
cin >> uusi_saldo;
for(i=0; i<5; i++) {
if(asiakasrekisteri[i].VertaaTiliNro(tilin_nro) == 1) {
loytyi = 1;
asiakasrekisteri[i].MuutaSaldoa(uusi_saldo);
cout << endl << "Saldo muutettu." << endl;
}
}
if(loytyi == 0) {
cout << endl << "Antamaasi tilinumeroa ei löytynyt." << endl;
}
loytyi = 0;
} else {
cout << endl << "Ohjelma lopetetaan.";
}
}
while(valinta>0);
}
//** ---------- ---------- ---------- **//
```

+ 159
- 0
3_creating-class/2_object-array.md View File

@ -0,0 +1,159 @@
## 2 Oliotaulukon käsittely
**Tehtävä:**
Edellisessä tehtävässä sinun vastuulla oli toteuttaa luokka, jonka
palveluiden avulla alkeellinen pankkiohjelma toimi. Nyt tehtävänäsi on
toteuttaa pieni osa "Asiakastili" luokkaa hyödyntävästä pääohjelmasta,
joka kokonaisuudessaan muodostaa pankkiohjelman logiikan ja toiminnan.
Tehtävänäsi on kirjoittaa ohjelmanpätkä, joka liitetään osaksi koko pankkiohjelmaa. Sinun ohjelman osan tulee selvittää, löytyykö köytössäsi olevasta oliotaulukosta oliota eli asiakasta, jolla on sama tilinumero kuin ohjelmalle juuri syötetty tilinumero. Jos oliotaulukko (asiakasrekisteri[5]) sisältää asiakkaan, jolla on sama numero, tulee ohjelman osasi asettaa bool-muuttujalle "loytyi" arvo "true", sekä kutsua täsmäävän olion jäsenfunktiota "NaytaTiedot()".
Seuraavassa huomioita tehtävän ratkaisemiseksi:
- Tilinumero, jota haetaan oliotaulukon olioista sijaitsee muuttujassa "tilin_nro".
- Oliot, joiden seasta etsitään täsmäävää tilinumeroa on nimeltään "asiakasrekisteri" ja se sisältää viisi oliota (asiakasrekisteri[0]-->asiakasrekisteri[4]).
- Tehokkaimmin täsmäävän tilinumeron etsiminen onnistuu silmukassa. Silmukan ehto-osassa on mahdollista määritellä erityinen indeksimuuttuja, esim: for(int indeksi; ....
- Olioiden funktioihin viitataan pistenotaatiolla.
- Ohjelman tulee vain ja ainoastaan verrata olemassa olevaa tilinumeroa olioiden tilinumeroihin ja jos saman tilinumeron omaava olio löytyy, asettaa "loytyi", sekä kutsua "NaytaTiedot" funktiota. Muut toiminnallisuudet ovat turhia ja estävät mahdollisesti tehtävän hyväksytyn suorittamisen.
Example output:
```
1: Näytä asiakkaan tiedot.
2: Muuta asiakkaan saldoa.
Lopetus negatiivisella luvulla.
Valitse toiminto: 1
Anna tilinumero:
32442
Antamaasi tilinumeroa ei löytynyt.
1: Näytä asiakkaan tiedot.
2: Muuta asiakkaan saldoa.
Lopetus negatiivisella luvulla.
Valitse toiminto: -1
Ohjelma lopetetaan.
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include <iostream>
using namespace std;
class Asiakastili
{
public:
void LisaaAsiakas(int tilinumero, int saldo, string nimi);
void NaytaTiedot();
int MuutaSaldoa(int saldo);
int VertaaTiliNro(int vertaatilinumero);
private:
int tilinumero_, saldo_;
string nimi_;
};
void Asiakastili::LisaaAsiakas(int tilinumero, int saldo, string nimi)
{
tilinumero_ = tilinumero;
saldo_ = saldo;
nimi_ = nimi;
}
void Asiakastili::NaytaTiedot()
{
cout << endl << "Tilinumero: " << tilinumero_ << endl << "Asiakkaan nimi: " << nimi_ << endl << "Tilin saldo: " << saldo_ << endl;
}
int Asiakastili::MuutaSaldoa(int saldo)
{
saldo_ = saldo;
return saldo_;
}
int Asiakastili::VertaaTiliNro(int tilinumero)
{
if (tilinumero_ == tilinumero)
{
return 1;
}
else
{
return 0;
}
}
int main() {
int valinta, tilin_nro, uusi_saldo, i;
bool loytyi;
Asiakastili asiakasrekisteri[5];
asiakasrekisteri[0].LisaaAsiakas(12345, 312, "Mikko Möttönen");
asiakasrekisteri[1].LisaaAsiakas(23456, 23, "Anni Manninen");
asiakasrekisteri[2].LisaaAsiakas(34567, 112, "Simo Siili");
asiakasrekisteri[3].LisaaAsiakas(45678, 99834, "Riku Rikas");
asiakasrekisteri[4].LisaaAsiakas(56789, 7500, "Marja Mallikas");
do {
cout << endl << "1: Näytä asiakkaan tiedot." << endl;
cout << "2: Muuta asiakkaan saldoa." << endl;
cout << "Lopetus negatiivisella luvulla." << endl;
cout << "Valitse toiminto: ";
cin >> valinta;
if(valinta == 1) {
cout << "Anna tilinumero: " << endl;
cin >> tilin_nro;
//** ---------- ---------- ---------- **//
loytyi = false;
for(int a=0; a<5; a++)
{
if(asiakasrekisteri[a].VertaaTiliNro(tilin_nro))
{
loytyi = true;
asiakasrekisteri[a].NaytaTiedot();
break;
}
}
//** Pre-defined code in the assignment **//
if(loytyi == false) {
cout << endl << "Antamaasi tilinumeroa ei löytynyt." << endl;
}
loytyi = 0;
} else if(valinta == 2){
cout << "Anna tilinumero: ";
cin >> tilin_nro;
cout << "Anna uusi saldo:";
cin >> uusi_saldo;
for(int i=0; i<5; i++) {
if(asiakasrekisteri[i].VertaaTiliNro(tilin_nro) == 1) {
loytyi = true;
asiakasrekisteri[i].MuutaSaldoa(uusi_saldo);
cout << endl << "Saldo muutettu." << endl;
}
}
if(loytyi == false) {
cout << endl << "Antamaasi tilinumeroa ei löytynyt." << endl;
}
loytyi = false;
} else {
cout << endl << "Ohjelma lopetetaan.";
}
}
while(valinta>0);
}
//** ---------- ---------- ---------- **//
```

+ 70
- 0
4_pointers-vars-and-memory-handling/1_pointer-as-param.md View File

@ -0,0 +1,70 @@
## 1 Osoittimen käyttö aliohjelmaparametrina
**Tehtävä:**
Tehtävänäsi on laatia funktion "muuta_lukua" prototyyppi ja funktion toteutus. Seuraavassa näet pääohjelman, joka käyttää funktiota hyväkseen:
```
#include<iostream>
using namespace std;
// tähän funktion "muuta_lukua" prototyyppi
// ja prototyypin perään funktion toteutus
int main()
{
int luku = 2;
cout << "Luku ohjelman alussa: " << luku << endl;
muuta_lukua(&luku);
cout << "Luku ohjelman lopussa: " << luku << endl;
return 0;
}
```
Pääohjelmassa alustetaan kokonaislukumuuttuja "luku", jonka osoite välitetään funktiolle "muuta_lukua". Funktion tehtävänä on kysyä esimerkkitulosteen mukaisesti korvaavaa lukua, joka sijoitetaan parametrina saadun osoitteen epäsuorasti viittamaan muuttujaan.
Tarkastelemalla edellistä pääohjelmaa, sekä esimerkkitulostetta näet, kuinka tarvittava funktio on laadittava. Huomaa, että tehtävänäsi on kirjoittaa VAIN funktion prototyyppi ja tämän perään funktion toteutus. Älä siis kopioi esitettyä pääohjelmaa vastaukseesi.
Example output:
```
Luku ohjelman alussa: 2
Anna korvaava luku: 4
Luku ohjelman lopussa: 4
```
**Vastaus:**
```
#include<iostream>
using namespace std;
// Prototype
int muuta_lukua(int* luku);
// Function definition
int muuta_lukua(int* luku)
{
// int *p_luku = luku;
cout << "Anna korvaava luku: ";
// cin >> *p_luku;
cin >> *luku;
if (cin.fail()) exit(1);
return *luku;
}
//** Pre-defined code in the assignment **//
int main()
{
int luku = 2;
cout << "Luku ohjelman alussa: " << luku << endl;
muuta_lukua(&luku);
cout << "Luku ohjelman lopussa: " << luku << endl;
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 64
- 0
4_pointers-vars-and-memory-handling/2_refvar-as-param.md View File

@ -0,0 +1,64 @@
## 2 Viittauksen käyttö aliohjelmaparametrissa
**Tehtävä:**
Nyt tehtävänäsi on laatia samanlainen funktio ja sen prototyyppi, kuten edellisessä tehtävässä.
Ainoana erona edelliseen tehtävään on, että tällä kertaa laatimasi funktion on käytettävä parametrina saatua viittausmuuttujaa muuttujan "luku" sisältämän arvon muuttamiseksi.
Tällä kertaa aliohjelmaa hyödyntävä runko näyttää seuraavalta:
```
#include<iostream>
using namespace std;
// tähän funktion "muuta_lukua" prototyyppi
// tähän itse funktio, joka saa viittauksen parametrina
// välitettävään muuttujaan
int main()
{
int luku = 2;
cout << "Luku ohjelman alussa: " << luku << endl;
muuta_lukua(luku);
cout << "Luku ohjelman lopussa: " << luku << endl;
return 0;
}
```
Example output:
```
Luku ohjelman alussa: 2
Anna korvaava luku: 23
Luku ohjelman lopussa: 23
```
**Vastaus:**
```
#include<iostream>
using namespace std;
// Prototype
void muuta_lukua(int &luku);
// Function definition
void muuta_lukua(int &luku)
{
qint* const p_luku = &luku;
cout << "Anna korvaava luku: ";
cin >> *p_luku;
if (cin.fail()) exit(1);
}
//** Pre-defined code in the assignment **//
int main()
{
int luku = 2;
cout << "Luku ohjelman alussa: " << luku << endl;
muuta_lukua(luku);
cout << "Luku ohjelman lopussa: " << luku << endl;
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 108
- 0
4_pointers-vars-and-memory-handling/3_dynamic-memory.md View File

@ -0,0 +1,108 @@
## 3 Dynaamista muistinhallintaa
**Tehtävä:**
Luvun viimeisenä ohjelmointitehtävänä sinun tulee laatia aliohjelma "uusi_piste", jota käytetään seuraavassa esitetyn pääohjelman osana:
int main()
{
Piste* pisteolio;
pisteolio = uusi_piste();
pisteolio->TulostaPiste();
delete pisteolio;
return 0;
}
Luokka "Piste", jota pääohjelmassa ja aliohjelmassa "uusi_piste" käytetään, sisältää kaksi jäsenmuuttujaa: koordinaatit x ja y, sekä jäsenfunktiot "TulostaPiste" ja "AsetaPiste". Funktion TulostaPiste tehtävänä on tulostaa piste-olion koordinaatit näytölle ja AsetaPiste puolestaan asettaa sille parametrina välitetyt koordinaatit olion jäsenmuuttujiin.
Sinun vastuulla olevan funktion "uusi_piste" tehtävänä on:
- Luoda uusi (dynaaminen) olio luokasta "Piste"
- Luominen tapahtuu seuraavan syntaksin mukaisesti: osoitin_olioon = new Piste;
- Kysyä käyttäjältä esimerkkitulosteen esittämällä tavalla pisteoliolle asetettavat koordinaatit
- Asettaa saadut koordinaatit funktiossa luodulle oliolle
- Koordinaattien asetus tapahtuu seuraavan syntaksin mukaisesti: osoitin_olioon->AsetaPiste(x, y);
- Palauttaa olion osoite sitä kutsuvalle pääohjelmalle
- Olion osoite palautetaan seuraavan syntaksin mukaisesti: return osoitin_olioon;
Funktio "uusi_piste" palauttaa osoitteen funktion sisällä muodostettuun dynaamiseen olioon, jonka vuoksi sen prototyyppi on seuraava: Piste* uusi_piste();. Sinun tulee kirjoittaa vain funktion otsikko ja toteutus prototyyppi on valmiiksi kirjoitettu.
Example output:
```
Anna uuden pisteen x: 45
Anna uuden pisteen y: 3
Pisteen x-koordinaatti: 45
Pisteen y-koordinaatti: 3
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include <iostream>
using namespace std;
class Piste
{
public:
void TulostaPiste();
void AsetaPiste(int x, int y);
private:
int x_;
int y_;
};
void Piste::TulostaPiste()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
void Piste::AsetaPiste(int x, int y)
{
x_ = x;
y_ = y;
}
// Funktio "uusi_piste" palauttaa osoitteen funktion sisällä
// muodostettuun dynaamiseen olioon, minkä vuoksi sen prototyyppi on seuraava:
Piste* uusi_piste();
int main()
{
Piste* pisteolio;
pisteolio = uusi_piste();
pisteolio->TulostaPiste();
delete pisteolio;
return 0;
}
//** ---------- ---------- ---------- **//
Piste* uusi_piste() {
short int x, y;
Piste* piste = new Piste;
cout << "Anna uuden pisteen x: ";
cin >> x;
if (cin.fail()) exit(1);
cout << "Anna uuden pisteen y: ";
cin >> y;
if (cin.fail()) exit(1);
piste->AsetaPiste(x, y);
return piste;
}
```

+ 71
- 0
5_object-lifetime/1_default-constructor.md View File

@ -0,0 +1,71 @@
## 1 Oletusmuodostimen rakentaminen
**Tehtävä:**
Tässä tehtävässä sinun tulee kirjoittaa oletusmuodostimen toteutus luokalle "Piste", joka sisältää kokonaislukutyypin jäsenmuuttujat "x_" ja "y_".
Luokan "Piste" toteutus on olemassa - sinun tarvitsee siis kirjoittaa vain ja ainoastaan siihen liitettävä oletusmuodostin,
joka alustaa jäsenmuuttujan "x_" arvolla 1 ja jäsenmuuttujan "y_" arvolla 1. Oletusmuodostin on esitelty valmiiksi luokan määrittelyssä.
Luokkaa ja sen oletusmuodostinta testataan seuraavassa esitetyllä pääohjelmalla (älä kopioi pääohjelmaa vastaukseesi):
```
int main()
{
Piste pisteolio;
pisteolio.TulostaPiste();
return 0;
}
```
Example output:
```
Pisteen x-koordinaatti: 1
Pisteen y-koordinaatti: 1
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Piste
{
public:
Piste();
void TulostaPiste();
void AsetaPiste(int x, int y);
private:
int x_;
int y_;
};
void Piste::TulostaPiste()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
void Piste::AsetaPiste(int x, int y)
{
x_ = x;
y_ = y;
}
//** ---------- ---------- ---------- **//
Piste::Piste() : x_(1), y_(1)
{
}
//** Pre-defined code in the assignment **//
int main()
{
Piste pisteolio;
pisteolio.TulostaPiste();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 86
- 0
5_object-lifetime/2_parameter-constructor.md View File

@ -0,0 +1,86 @@
## 2 Parametrillisen muodostimen rakentaminen
**Tehtävä:**
Luvun toisessa tehtävässä sinun tulee kirjoittaa jo aiemmin tutuksi tulleeseen luokkaan "Piste" parametrillisen muodostimen toteutus.
Tämä muodostin on esitelty luokan määrittelyssä seuraavasti:
Piste:Piste(int x, int y);
Muodostin sijoittaa parametrina saadut arvot jäsenmuuttujiin "x_" ja "y_". Kirjoittamaasi muodostinta testataan seuraavalla pääohjelmalla:
```
int main()
{
int x, y;
cout << "Anna muodostettavan olion x-koordinaatti: ";
cin >> x;
cout << "Anna muodostettavan olio y-koordinaatti: ";
cin >> y;
Piste pisteolio(x, y);
pisteolio.TulostaPiste();
return 0;
}
```
Pääohjelma kysyy käyttäjältä muodostettavan olion koordinaatit ja muodostaa automaattisen olion kutsuen sen parametrillista muodostinta.
Example output:
```
Anna muodostettavan olion x-koordinaatti: 2
Anna muodostettavan olio y-koordinaatti: 1
Pisteen x-koordinaatti: 2
Pisteen y-koordinaatti: 1
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include <iostream>
using namespace std;
class Piste
{
public:
Piste(int x, int y);
void TulostaPiste();
void AsetaPiste(int x, int y);
private:
int x_;
int y_;
};
void Piste::TulostaPiste()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
void Piste::AsetaPiste(int x, int y)
{
x_ = x;
y_ = y;
}
//** ---------- ---------- ---------- **//
Piste::Piste(int x, int y) : x_(x), y_(y)
{
}
//** Pre-defined code in the assignment **//
int main()
{
int x, y;
cout << "Anna muodostettavan olion x-koordinaatti: ";
cin >> x;
cout << "Anna muodostettavan olio y-koordinaatti: ";
cin >> y;
Piste pisteolio(x, y);
pisteolio.TulostaPiste();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 76
- 0
5_object-lifetime/3_destructor.md View File

@ -0,0 +1,76 @@
## 3 Tuhoajan rakentaminen
**Tehtävä:**
Tuhoajan tehtävänä oliota tuhottaessa on huolehtia siihen kuuluvien dynaamisten tietojäsenten tuhoamisesta. Olio voi esimerkiksi sisältää toisen olion, jonka tuhoaminen on emo-olion vastuulla. Koska emme ole toistaiseksi käsitelleet dynaamisia tietojäseniä, emme voi tässä vaiheessa harjoitella myöskään niiden tuhoamista.
Tässä tehtävässä sinun tulee laatia luokalle Piste tuhoajan toteutus, joka suoritetaan, kun luokasta muodostettu olio tuhotaan. Purkajaan ei toteuta muistinhallintaan tai esimerkiksi tietojen tallentamiseen liittyviä toimintoja, vaan sen ainoana tehtävänä on tulostaa näytölle teksti: "Tuhoaja suoritettu ja olio tuhottu.". Tuhoaja on esitelty valmiiksi luokan "Piste" määrittelyssä.
Example output:
```
Anna muodostettavan olion x-koordinaatti: 34
Anna muodostettavan olio y-koordinaatti: 22
Pisteen x-koordinaatti: 34 Pisteen y-koordinaatti: 22
Tuhoaja suoritettu ja olio tuhottu.
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include <iostream>
using namespace std;
class Piste
{
public:
Piste(int x, int y);
~Piste();
void TulostaPiste();
void AsetaPiste(int x, int y);
private:
int x_;
int y_;
};
Piste::Piste(int x, int y): x_(x), y_(y)
{
}
//** ---------- ---------- ---------- **//
Piste::~Piste()
{
cout << "Tuhoaja suoritettu ja olio tuhottu.";
}
//** Pre-defined code in the assignment **//
void Piste::TulostaPiste()
{
cout << "Pisteen x-koordinaatti: " << x_ << endl;
cout << "Pisteen y-koordinaatti: " << y_ << endl;
}
void Piste::AsetaPiste(int x, int y)
{
x_ = x;
y_ = y;
}
int main()
{
int x, y;
cout << "Anna muodostettavan olion x-koordinaatti: ";
cin >> x;
cout << "Anna muodostettavan olion y-koordinaatti: ";
cin >> y;
Piste* pisteolio = new Piste(x, y);
pisteolio->TulostaPiste();
delete pisteolio;
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 160
- 0
6_uml-principles/1_team-players.md View File

@ -0,0 +1,160 @@
## 1 Joukkue koostuu pelaajista
**Tehtävä:**
Alla näet UML-kaavion, joka on osa suurempaa oliosuunnitelmaa. Sinun
tehtävänäsi on toteuttaa kaavion mukainen luokka "Pelaaja". Kuten kuvasta
voidaan nähdä, Joukkue-luokka koostuu pelaajista. Tämä ei kuitenkaan vaikuta
sinun osuuteesi ohjelmiston toteutuksessa - riittää, kun osaat kirjoittaa
luokan UML-kaavion osoittamalla tavalla.
Ohessa joitakin huomioita, joita tarvitset kaavion tulkinnassa:
- Merkit "-" ja "+" jäsenten edessä määrittelevät jäsenen näkyvyyden. (+ = public, - = private)
- Notaatiossa esitetään ensin jäsenmuuttujan tai parametrin nimi ja tämän jälkeen tietotyyppi.
- Jäsenfunktioiden paluuarvot näkyvät notaatiossa funktioiden otsikoiden perässä kaksoispisteellä eroteltuna.
```
+---------------------------------+
| Pelaaja |
+---------------------------------+
+--------+ |- rooli_: string |
|Joukkue +-------------------------+- nimi_ : string |
|--------| 1 40 |- pelinro_: int |
+--------+ +---------------------------------+
|+ AsetaNimi(nimi:string):void* |
|+ KerroNimi():string |
|+ AsetaRooli(rooli:string):void* |
|+ KerroRooli():string |
|+ AsetaNro(nro:int):void* |
|+ KerroNro():int |
+---------------------------------+
```
Example output:
```
Nimi: Matti Meikäläinen
Rooli: Maalivahti
Pelinumero: 1
Nimi: Kale Kokkola
Rooli: Vaihtopenkin lämmittäjä
Pelinumero: 82
Nimi: Simo Supermies
Rooli: Hyökkääjä
Pelinumero: 99
```
**Vastaus:**
```
#include<iostream>
using namespace std;
class Pelaaja
{
public:
void AsetaNimi(string nimi)
{
nimi_ = nimi;
}
string KerroNimi()
{
return nimi_;
}
void AsetaRooli(string rooli)
{
rooli_ = rooli;
}
string KerroRooli()
{
return rooli_;
}
void AsetaNro(int nro)
{
pelinro_ = nro;
}
int KerroNro()
{
return pelinro_;
}
private:
string rooli_;
string nimi_;
int pelinro_;
};
//** Pre-defined code in the assignment **//
class Joukkue
{
public:
void LisaaPelaaja(string nimi, string rooli, int nro);
void TulostaJoukkue();
Joukkue();
~Joukkue();
private:
Pelaaja* pelaajat[30];
int pelaajia_;
};
Joukkue::Joukkue() : pelaajia_(0)
{
int i;
for (i=0; i<30; i++) {
pelaajat[i] = NULL;
}
}
Joukkue::~Joukkue()
{
int i;
for (i=0; i<30; i++) {
delete pelaajat[i];
}
}
void Joukkue::LisaaPelaaja(string nimi, string rooli, int nro)
{
pelaajat[pelaajia_] = new Pelaaja();
pelaajat[pelaajia_]->AsetaNimi(nimi);
pelaajat[pelaajia_]->AsetaRooli(rooli);
pelaajat[pelaajia_]->AsetaNro(nro);
pelaajia_++;
}
void Joukkue::TulostaJoukkue()
{
int i;
for(i=0; i<30; i++) {
if(pelaajat[i] != NULL)
{
cout << "Nimi: " << pelaajat[i]->KerroNimi() << endl;
cout << "Rooli: " << pelaajat[i]->KerroRooli() << endl;
cout << "Pelinumero: " << pelaajat[i]->KerroNro() << endl << endl;
}
}
}
int main()
{
Joukkue VioPa;
VioPa.LisaaPelaaja("Matti Meikäläinen", "Maalivahti", 1);
VioPa.LisaaPelaaja("Kale Kokkola", "Vaihtopenkin lämmittäjä", 82);
VioPa.LisaaPelaaja("Simo Supermies", "Hyökkääjä", 99);
VioPa.TulostaJoukkue();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 143
- 0
7_class-relations/1_card-deck.md View File

@ -0,0 +1,143 @@
## 1 Korttipakka koostuu korteista
**Tehtävä:**
Luvun ensimmäisessä tehtävässä on laadittu ennalta luokka Kortti, joka sisältää kaksi kokonaislukutyypin jäsenmuuttujaa: maa_ ja arvo_. Luokan logiikka perustuu oletukseen, jonka mukaan muuttujan maa_ arvot merkitsevät seuraavia maita: 1-> hertta, 2->ruutu, 3->pata ja 4->risti. Muuttuja arvo_ saa korteista tuttuja arvoja väliltä 1-13.
Kortti-luokassa on oletusmuodostin, joka alustaa luokasta muodostettavan luokassa olevien korttiolioiden jäsenet arvolla 0. Lisäksi luokka sisältää jäsenfunktiot KerroMaa() ja KerroArvo(), jotka palauttavat nimensä mukaiset kortti-olioon kuuluvat arvot. Neljäs Kortti-luokkaan kuuluva funktio on AlustaKortti(maa, arvo), joka alustaa kortin annetuilla arvoilla.
Sinun tehtävänäsi on luokka KorttiPakka, johon on liitetty kokoonpanollisella koostumissuhteella (automaattisella oliotaulukolla) 52 korttioliota, sekä seuraavassa esitetyt funktiot.
KorttiPakkaan on kirjoitettava oletusmuodostin, joka antaa korttipakkaan kuuluville korttiolioille todelliset kortteja ilmentävät arvot. Korttien alustamiseen käytetään Kortti-luokkaan kuuluvaa AlustaKortti jäsenfunktiota, joka saa parametrina kortin maan ja arvon. Alustaminen on tehtävä siten, että pakan kortit alustuvat seuraavaan järjestykseen (oliotaulukon ensimmäinen alkio = pakan ensimmäinen kortti): hertta 1 - 13, ruutu 1-13, pata 1-13 ja risti 1-13.
KorttiPakka-luokan ainoa varsinainen jäsenfunktio on TulostaKortti(jnro), joka saa parametrina kortin järjestysnumeron alustetussa pakassa ja tulostaa järjestysnumeron mukaisen kortin esimerkkitulosteen mukaisesti. Laatimaasi luokkaa testaava pääohjelma muodostaa korttipakka-olion ja tulostaa pakasta joitakin kortteja.
Example output:
```
Hertta 1
Ruutu 8
Pata 2
Risti 2
Risti 13
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Kortti
{
public:
int KerroMaa();
int KerroArvo();
void AlustaKortti(int maa, int arvo);
Kortti();
private:
int maa_; // 1=hertta, 2=ruutu, 3=pata, 4=risti
int arvo_;
};
Kortti::Kortti() : maa_(0), arvo_(0)
{
}
int Kortti::KerroMaa()
{
return maa_;
}
int Kortti::KerroArvo()
{
return arvo_;
}
void Kortti::AlustaKortti(int maa, int arvo)
{
maa_ = maa;
arvo_ = arvo;
}
//** ---------- ---------- ---------- **//
class KorttiPakka
{
public:
KorttiPakka();
~KorttiPakka();
void TulostaKortti(int jnro)
{
int arvo = jnro+1;
if (jnro >= 0 && jnro <= 13) {
cout << "Hertta " << arvo << endl;
} else if (jnro > 13 && jnro <= 26) {
cout << "Ruutu " << arvo-13 << endl;
} else if (jnro > 26 && jnro <= 39) {
cout << "Pata " << arvo-26 << endl;
} else if (jnro > 39 && jnro <= 51) {
cout << "Risti " << arvo-39 << endl;
} else {
cerr << "Kortin on oltava väliltä 0-51" << endl;
}
}
private:
Kortti* kortti_[51];
int jnro_;
};
KorttiPakka::KorttiPakka() : jnro_(0)
{
int a;
for (int i=0; i<=51; i++) {
if (jnro_ > 12) {
jnro_ = 1;
}
if(i >= 0 && i <= 13) {
a = 1;
} else if (i > 13 && i <= 26) {
a = 2;
} else if (i > 26 && i <= 39) {
a = 3;
} else if (i > 39 && i <= 51) {
a = 4;
} else {
cerr << "Kortin on oltava väliltä 0-51" << endl;
}
kortti_[i] = new Kortti();
kortti_[i]->AlustaKortti(a,jnro_);
jnro_++;
}
}
KorttiPakka::~KorttiPakka()
{
for (int i=0; i<51; i++) {
delete kortti_[i];
}
}
//** Pre-defined code in the assignment **//
int main()
{
int jnro;
KorttiPakka pakka;
pakka.TulostaKortti(0); // Hertta 1
pakka.TulostaKortti(20); // Ruutu 8
pakka.TulostaKortti(27); // Pata 2
pakka.TulostaKortti(40); // Risti 2
pakka.TulostaKortti(51); // Risti 13
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 118
- 0
7_class-relations/2_car-human-association.md View File

@ -0,0 +1,118 @@
## 2 Auto-Henkilo -assosiaatio
**Tehtävä:**
Tässä tehtävässä on valmiiksi kirjoitettu luokka Auto, joka sisältää kaksi jäsenmuuttujaa. Ensimmäinen on string-tyypin muuttuja merkki_, joka kuvaa auton merkkiä. Toinen muuttujista on ajetut_km_, joka kuvaa autolla ajettujen kilometrien määrää.
Edellisten lisäksi Auto-luokassa on:
- Parametrillinen muodostin, joka välittää muodostettavalle auto-oliolle merkin ja ajettujen kilometrien määrän annetussa järjestyksessä.
- Funktio Liiku, joka ottaa vastaa kokonaislukutyypin arvon, jolla imaistaan liikuttavien kilometrien määrää. Funktio lisää vastaanotetun arvon muuttujaan ajetut_km_ ja tulostaa esimerkkitulosteen mukaisen tekstin näytölle.
- Funktio KerroAjetutKm, joka sitä kutsuttaessa tulostaa autolla ajettujen kilometrien määrän.
Sinun tehtävänäsi on muodostaa Henkilo-luokka, jolla on osoittimen avulla toteutettu assosiaatiosuhde Auto-luokkaan. Henkilo-luokka tarvitsee kaksi jäsenmuuttujaa: henkilön nimen (string) ja osoittimen Auto-luokan olioihin. Edellisten jäsenmuuttujien lisäksi Henkilo-luokkaan pitää määritellä ja toteuttaa seuraavat palvelut:
- Parametrillinen muodostin, joka muodostaa uuden henkilön ja sijoittaa olion jäsenmuuttujiin parametrina saadut nimen ja osoittimen tiettyyn auto-olioon.
- Funktio AjaAutoa, joka saa kokonaislukutyypin parametrin, jolla ilmaistaan ajettavien kilometrien määrän. AjaAutoa-funktion tehtävänä on kutsua Auto-luokan Liiku funktiota, jolle ajettavien kilometrien lukumäärä välitetään.
- Funktio VaihdaAutoa, joka saa parametrina osoittimen uuteen auto-olioon ja jonka funktio vaihtaa entisen auton tilalle. Huomaa, että vanhaa auto ei tarvitse, eikä pidä tuhota.
Pääohjelma, jossa vastaustasi testataan, muodostaa kaksi autoa ja yhden henkilön. Henkilö ajaa ensin toista autoa, vaihtaa autoa ja ajaa uudella autolla. Lisäksi auto-oliota pyydetään tulostamaan ajettuja kilometrejä luokkien välisen assosiaation toimimisen toteamiseksi.
Example output:
```
Toyota Corolla DX merkkisellä autolla on ajettu 25000 km
Wrooom...1000 kilometriä ajettu.
Toyota Corolla DX merkkisellä autolla on ajettu 26000 km
Ferrari F50 merkkisellä autolla on ajettu 1500 km
Wrooom...20000 kilometriä ajettu.
Ferrari F50 merkkisellä autolla on ajettu 21500 km
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Auto
{
public:
void Liiku(int km);
void KerroAjetutKm();
Auto(string merkki, int ajetut_km);
private:
string merkki_;
int ajetut_km_;
};
Auto::Auto(string merkki, int ajetut_km) : merkki_(merkki), ajetut_km_(ajetut_km)
{
}
void Auto::Liiku(int km)
{
ajetut_km_ = ajetut_km_ + km;
cout << "Wrooom..." << km << " kilometriä ajettu." << endl;
}
void Auto::KerroAjetutKm()
{
cout << merkki_ << " merkkisellä autolla on ajettu " << ajetut_km_ << " km" << endl;
}
//** ---------- ---------- ---------- **//
class Henkilo
{
public:
Henkilo(string nimi, Auto* car);
void AjaAutoa(int km);
void VaihdaAutoa(Auto* car);
private:
string nimi_;
Auto* car_;
};
Henkilo::Henkilo(string nimi, Auto* car) : nimi_(nimi), car_(car)
{
Auto* car_ = car;
nimi_ = nimi;
}
void Henkilo::AjaAutoa(int km)
{
car_->Liiku(km);
}
void Henkilo::VaihdaAutoa(Auto* car)
{
car_ = car;
}
//** Pre-defined code in the assignment **//
int main()
{
Auto* deksteri = new Auto("Toyota Corolla DX", 25000);
Auto* ferrari = new Auto("Ferrari F50", 1500);
Henkilo* autoilija = new Henkilo("James", deksteri);
deksteri->KerroAjetutKm();
autoilija->AjaAutoa(1000);
deksteri->KerroAjetutKm();
ferrari->KerroAjetutKm();
autoilija->VaihdaAutoa(ferrari);
autoilija->AjaAutoa(20000);
ferrari->KerroAjetutKm();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 181
- 0
8_inheritance/1_class-inheritance.md View File

@ -0,0 +1,181 @@
## 1 Luokan rakentaminen periyttämällä
**Tehtävä:**
Tässä tehtävässä sinun tulee toteuttaa luokka Auto, joka periytyy Ajoneuvo luokasta. Luokan Ajoneuvo määrittely on seuraava:
```
class Ajoneuvo
{
public:
Ajoneuvo(int ajetut, int paino, string merkki, string malli);
protected:
void Liikuta(int km);
int PalautaAjetut();
int PalautaPaino();
string PalautaMerkki();
string PalautaMalli();
private:
int ajetut_;
int paino_;
string merkki_;
string malli_;
};
```
Ajoneuvo-luokka on melko yksinkertainen. Funktio Liikuta saa parametrina kilometrimäärän, jonka mukaisella määrällä kasvatetaan jäsenmuuttujan ajetut_ arvoa.
Funktiot PalautaX palauttavat nimensä mukaiset arvot funktiota kutsuvalle ohjelman osalle. Huomaa, että luokan kaikki funktiot on määritelty protected määreellä, joten niiden palveluja voidaan hyödyntää vain Ajoneuvo-luokan aliluokissa.
Sinun tehtävänäsi on laatia luokan määrittely ja jäsenfunktioden toteutus luokkaan Auto, joka perii luokan Ajoneuvo. Auto-luokka sisältää kaksi autolle ominaista jäsenmuuttujaa: string-tyypin rekisteri_nro_ ja int-tyypin matkustajat_max_, joka kuvaa autolle suurinta sallittua matkustajamäärää.
Auto-luokkaan on tehtävä parametrillinen muodostin, jolle välitetään auton muodostamiseen tarvittavat tiedot (ajetut_, paino_, merkki_, malli_, rekisteri_nro_ ja matkustajat_max_). Osa parametreista välitetään Auto-luokan muodostajassa Ajoneuvo-luokan muodostajalle. Sinun tulisi kyetä päättelemään, mitkä.
Muodostimen lisäksi Auto-luokkaan kirjoitetaan kaksi funktiota, joista ensimmäinen on TulostaAutonTiedot(), joka tulostaa auton tiedot mukaan lukien sen yläluokassa olevat tiedot. Funktio ei palauta arvoa, eikä ota vastaan arvoja. Tulostuksen muoto ilmenee esimerkkitulosteesta.
Toinen varsinainen funktio Auto-luokassa on AjaAutoa(km), jonka tehtävänä on käyttää yliluokan palvelua Liikuta() ajettujen kilometrien kirjaamiseksi. Lisäksi funktio AjaAutoa() tulostaa näytölle ajettujen kilometrien määrän.
Toteuttamaasi periytettyä luokkaa testataan seuraavalla pääohjelmalla (älä kopioi pääohjelmaa vastaukseesi):
```
int main()
{
Auto pirssi(250000, 1700, "Toyota", "Carina II", "TFM-257", 5);
pirssi.TulostaAutonTiedot();
pirssi.AjaAutoa(25000);
pirssi.TulostaAutonTiedot();
return 0;
}
```
Example output:
```
Merkki: Toyota
Malli: Carina II
Paino: 1700
Ajetut kilometrit: 250000
Rekisterinumero: TFM-257
Maksimi matkustajien määrä: 5
Autolla ajettu 25000 kilometriä.
Merkki: Toyota
Malli: Carina II
Paino: 1700
Ajetut kilometrit: 275000
Rekisterinumero: TFM-257
Maksimi matkustajien määrä: 5
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Ajoneuvo
{
public:
Ajoneuvo(int ajetut, int paino, string merkki, string malli);
protected:
void Liikuta(int km);
int PalautaAjetut();
int PalautaPaino();
string PalautaMerkki();
string PalautaMalli();
private:
int ajetut_;
int paino_;
string merkki_;
string malli_;
};
Ajoneuvo::Ajoneuvo(int ajetut, int paino, string merkki, string malli) : ajetut_(ajetut), paino_(paino), merkki_(merkki), malli_(malli)
{
}
void Ajoneuvo::Liikuta(int km)
{
ajetut_ = ajetut_ + km;
}
int Ajoneuvo::PalautaAjetut()
{
return ajetut_;
}
int Ajoneuvo::PalautaPaino()
{
return paino_;
}
string Ajoneuvo::PalautaMerkki()
{
return merkki_;
}
string Ajoneuvo::PalautaMalli()
{
return malli_;
}
//** ---------- ---------- ---------- **//
class Auto:public Ajoneuvo
{
public:
Auto(int ajetut, int paino, string merkki, string malli, string rekisteri_nro, int matkustajat_max);
void TulostaAutonTiedot();
void AjaAutoa(int km);
~Auto();
private:
string rekisteri_nro_;
int matkustajat_max_;
};
Auto::~Auto()
{
}
Auto::Auto(int ajetut, int paino, string merkki, string malli, string rekisteri_nro, int matkustajat_max)
: Ajoneuvo(ajetut, paino, merkki, malli), rekisteri_nro_(rekisteri_nro), matkustajat_max_(matkustajat_max)
{
}
void Auto::TulostaAutonTiedot()
{
cout << "Merkki: " << Ajoneuvo::PalautaMerkki() << endl;
cout << "Malli: " << Ajoneuvo::PalautaMalli() << endl;
cout << "Paino: " << Ajoneuvo::PalautaPaino() << endl;
cout << "Ajetut kilometrit: " << Ajoneuvo::PalautaAjetut() << endl;
cout << "Rekisterinumero: " << rekisteri_nro_ << endl;
cout << "Maksimi matkustajien määrä: " << matkustajat_max_ << endl << endl;
}
void Auto::AjaAutoa(int km)
{
Liikuta(km);
cout << "Autolla ajettu " << km << " kilometriä." << endl << endl;
}
//** Pre-defined code in the assignment **//
int main()
{
Auto pirssi(250000, 1700, "Toyota", "Carina II", "TFM-257", 5);
pirssi.TulostaAutonTiedot();
pirssi.AjaAutoa(25000);
pirssi.TulostaAutonTiedot();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 134
- 0
8_inheritance/2_abstract-class.md View File

@ -0,0 +1,134 @@
## 2 Abstraktin luokan määrittely
**Tehtävä:**
Tehtävänäsi on kirjoittaa luokan Kuvio määrittely. Kyseinen luokka on abstrakti luokka, josta periytetään luokka Nelio.
Määrittele ja toteuta Kuvio-luokkaan seuraavat ominaisuudet:
- char-tyypin jäsenmuuttuja tekstuuri_
- Parametrillinen muodostin, jolle välitetään muodostamisen yhteydessä char-tyypin parametri, jonka arvo sijoitetaan muuttujaan tekstuuri_
- Jäsenfunktio PalautaTekstuuri(), joka palauttaa sitä kutsuttaessa jäsenmuuttujan tekstuuri_ arvon
- Puhtaasti virtuaalinen funktio Piirra, joka ei palauta arvoa, eikä ota vastaan parametreja
Toteuttamaasi abstraktia luokkaa testataan pääohjelmassa, jossa muodostetaan Kuvio-luokasta periytetty nelio-olio jota pyydetään tulostamaan itsensä. Älä kopioi pääohjelmaa vastaukseesi:
```
int main()
{
int sivun_pituus;
char tekstuuri;
cout << "Anna muodostettavan neliön sivun pituus: ";
cin >> sivun_pituus;
cout << "Syötä merkki, jota käytetään neliön tekstuurina: ";
cin >> tekstuuri;
Kuvio* nelio = new Nelio(tekstuuri, sivun_pituus);
nelio->Piirra();
delete nelio;
return 0;
}
```
Example output:
```
Anna muodostettavan neliön sivun pituus: 10
Syötä merkki, jota käytetään neliön tekstuurina: #
##########
##########
##########
##########
##########
##########
##########
##########
##########
##########
```
**Vastaus:**
```
#include<iostream>
using namespace std;
class Kuvio {
public:
Kuvio(char tekstuuri);
char PalautaTekstuuri();
virtual void Piirra() = 0;
~Kuvio();
private:
char tekstuuri_;
};
Kuvio::Kuvio(char tekstuuri) : tekstuuri_(tekstuuri)
{
}
char Kuvio::PalautaTekstuuri()
{
return tekstuuri_;
}
Kuvio::~Kuvio() {}
void Kuvio::Piirra() {}
//** Pre-defined code in the assignment **//
class Nelio : public Kuvio
{
public:
Nelio(char tekstuuri, int sivun_pituus);
void Piirra();
private:
int sivun_pituus_;
};
Nelio::Nelio(char tekstuuri, int sivun_pituus) : Kuvio(tekstuuri), sivun_pituus_(sivun_pituus)
{
}
void Nelio::Piirra()
{
int i, j;
for(i=0; i< sivun_pituus_; i++)
{
for(j=0; j<sivun_pituus_; j++)
{
if(j == sivun_pituus_ - 1)
{
cout << PalautaTekstuuri() << endl;
}
else
{
cout << PalautaTekstuuri();
}
}
}
}
int main()
{
int sivun_pituus;
char tekstuuri;
cout << "Anna muodostettavan neliön sivun pituus: ";
cin >> sivun_pituus;
cout << "Syötä merkki, jota käytetään neliön tekstuurina: ";
cin >> tekstuuri;
Kuvio* nelio = new Nelio(tekstuuri, sivun_pituus);
nelio->Piirra();
delete nelio;
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 190
- 0
8_inheritance/3_inherited-shape.md View File

@ -0,0 +1,190 @@
## 3 Kuviosta periytyvä nelikulmio
**Tehtävä:**
Luvun viimeisessä tehtäväsi sinun tulee kirjoittaa luokan määrittely ja jäsenfunktioiden toteutus luokalle Nelikulmio, joka on edellisessä tehtävässä laaditun abstraktin Kuvio-luokan aliluokka.
Luokan tulee sisältää seuraavat ominaisuudet:
- Jäsenmuuttujat: korkeus_ ja leveys_
- Parametrillinen muodostin, joka välittää Kuvio-luokan muodostimelle Nelikulmio-muodostimen saaman char-tyyppisen parametrin ja alustaa edellisessä mainitut jäsenmuuttujat muodostimelle välitetyin parametrein.
- Funktion Piirra toteutus, joka piirtää nelikulmion sen jäsenmuuttujissa olevien korkeus ja leveys tietojen perusteella. Piirtämiseen käytetään yliluokan jäsenmuuttujassa olevaa tekstuurimerkkiä kuten esimerkkitulosteesta voidaan havaita. Piirtämiseen tarvittava tekstuuri saadaan käyttöön Kuvio-luokan PalautaTekstuuri() funktiolla.
Example output:
```
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 2
Anna muodostettavan nelikulmion sivun korkeus: 4
Anna muodostettavan nelikulmion sivun leveys: 7
Syötä merkki, jota käytetään nelikulmion tekstuurina: O
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 1
Anna muodostettavan neliön sivun pituus: 4
Syötä merkki, jota käytetään neliön tekstuurina: W
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 2
Anna muodostettavan nelikulmion sivun korkeus: 5
Anna muodostettavan nelikulmion sivun leveys: 10
Syötä merkki, jota käytetään nelikulmion tekstuurina: @
Muodostetut kuviot piirrettynä:
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
WWWW
WWWW
WWWW
WWWW
@@@@@@@@@@
@@@@@@@@@@
@@@@@@@@@@
@@@@@@@@@@
@@@@@@@@@@
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Kuvio
{
public:
Kuvio(char tekstuuri);
char PalautaTekstuuri();
virtual void Piirra() = 0;
private:
char tekstuuri_;
};
Kuvio::Kuvio(char tekstuuri) : tekstuuri_(tekstuuri)
{
}
char Kuvio::PalautaTekstuuri()
{
return tekstuuri_;
}
class Nelio : public Kuvio
{
public:
Nelio(char tekstuuri, int sivun_pituus);
void Piirra();
private:
int sivun_pituus_;
};
Nelio::Nelio(char tekstuuri, int sivun_pituus) : Kuvio(tekstuuri), sivun_pituus_(sivun_pituus)
{
}
void Nelio::Piirra()
{
int i, j;
for (i=0; i < sivun_pituus_; i++)
{
for (j=0; j < sivun_pituus_; j++)
{
if (j == sivun_pituus_ - 1)
{
cout << PalautaTekstuuri() << endl;
}
else
{
cout << PalautaTekstuuri();
}
}
}
}
//** ---------- ---------- ---------- **//
class Nelikulmio: public Kuvio
{
public:
Nelikulmio(char tekstuuri, int korkeus, int leveys);
void Piirra();
private:
int korkeus_;
int leveys_;
};
Nelikulmio::Nelikulmio(char tekstuuri, int korkeus, int leveys)
: Kuvio(tekstuuri), korkeus_(korkeus), leveys_(leveys)
{
}
// TODO Remove duplicate functionality
void Nelikulmio::Piirra()
{
int i, j;
for (i=0; i < korkeus_; i++)
{
for (j=0; j < leveys_; j++)
{
if (j == leveys_ - 1)
{
cout << PalautaTekstuuri() << endl;
}
else
{
cout << PalautaTekstuuri();
}
}
}
}
//** Pre-defined code in the assignment **//
int main()
{
int sivun_leveys, sivun_korkeus, i, valinta;
char tekstuuri;
Kuvio* kuviot[3];
for(i=0; i<3; i++)
{
cout << "Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): ";
cin >> valinta;
if (valinta == 1)
{
cout << "Anna muodostettavan neliön sivun pituus: ";
cin >> sivun_leveys;
cout << "Syötä merkki, jota käytetään neliön tekstuurina: ";
cin >> tekstuuri;
kuviot[i] = new Nelio(tekstuuri, sivun_leveys);
}
else
{
cout << "Anna muodostettavan nelikulmion sivun korkeus: ";
cin >> sivun_korkeus;
cout << "Anna muodostettavan nelikulmion sivun leveys: ";
cin >> sivun_leveys;
cout << "Syötä merkki, jota käytetään nelikulmion tekstuurina: ";
cin >> tekstuuri;
kuviot[i] = new Nelikulmio(tekstuuri, sivun_korkeus, sivun_leveys);
}
}
cout << endl << "Muodostetut kuviot piirrettynä:" << endl << endl;
for (i=0; i<3; i++)
{
kuviot[i]->Piirra();
cout << endl;
}
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 182
- 0
8_inheritance/4_different-shapes.md View File

@ -0,0 +1,182 @@
## 4 Erilaisten kuvioiden piirtäminen
**Tehtävä:**
Luvun viimeisessä tehtävässä sinun tulee laatia funktio "TulostaKuviot", joka saa parametrina osoitintaulukon edellisistä tehtävistä tuttuun Kuvio-luokkaan. Taulukko sisältää Kuvio-luokasta periytettyjä oliota, jotka on muodostettu luokista Nelio ja Nelikulmio.
Funktion tulee tulostaa taulukon sisältämät oliot (yhteensä 3 oliota) esimerkkitulosteen mukaisesti hyödyntäen Nelio- ja Nelikulmio-luokkien yliluokassa (Kuvio) määriteltyä "Piirra" funktiota. Piirra-funktio ei saa parametreja, eikä se palauta arvoa.
Laatimasi funktion prototyyppi on kirjoitettu valmiiksi: `void TulostaKuviot(Kuvio* kuviotaulukko[3]);`
Huomaa, että ohjelman eri ajokerroilla taulukon sisältämät oliot ja niiden määrittelyluokat vaihtelevat. Polymorfismin ansiosta tällä ei ole kuitenkaan vaikutusta sinun funktiosi toteutuksessa.
Example output:
```
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 2
Anna muodostettavan nelikulmion sivun korkeus: 3
Anna muodostettavan nelikulmion sivun leveys: 4
Syötä merkki, jota käytetään nelikulmion tekstuurina: %
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 1
Anna muodostettavan neliön sivun pituus: 2
Syötä merkki, jota käytetään neliön tekstuurina: E
Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): 1
Anna muodostettavan neliön sivun pituus: 6
Syötä merkki, jota käytetään neliön tekstuurina: &
Muodostetut kuviot piirrettynä:
%%%%
%%%%
%%%%
EE
EE
&&&&&&
&&&&&&
&&&&&&
&&&&&&
&&&&&&
&&&&&&
```
**Vastaus:**
```
//** Pre-defined code in the assignment **//
#include<iostream>
using namespace std;
class Kuvio
{
public:
Kuvio(char tekstuuri);
char PalautaTekstuuri();
virtual void Piirra() = 0;
private:
char tekstuuri_;
};
Kuvio::Kuvio(char tekstuuri) : tekstuuri_(tekstuuri)
{
}
char Kuvio::PalautaTekstuuri()
{
return tekstuuri_;
}
class Nelio : public Kuvio
{
public:
Nelio(char tekstuuri, int sivun_pituus);
void Piirra();
private:
int sivun_pituus_;
};
Nelio::Nelio(char tekstuuri, int sivun_pituus) : Kuvio(tekstuuri),
sivun_pituus_(sivun_pituus)
{
}
void Nelio::Piirra()
{
int i, j;
for (i=0; i<sivun_pituus_; i++)
{
for(j=0; j<sivun_pituus_; j++)
{
if(j == sivun_pituus_ - 1) {
cout << PalautaTekstuuri() << endl;
}
else
{
cout << PalautaTekstuuri();
}
}
}
}
class Nelikulmio : public Kuvio
{
public:
Nelikulmio(char tekstuuri, int korkeus_, int leveys_);
void Piirra();
private:
int korkeus_;
int leveys_;
};
Nelikulmio::Nelikulmio(char tekstuuri, int korkeus, int leveys) :
Kuvio(tekstuuri), korkeus_(korkeus), leveys_(leveys)
{
}
void Nelikulmio::Piirra()
{
int i, j;
for (i=0; i<korkeus_; i++)
{
for(j=0; j<leveys_; j++)
{
if (j == leveys_ - 1)
{
cout << PalautaTekstuuri() << endl;
}
else
{
cout << PalautaTekstuuri();
}
}
}
}
void TulostaKuviot(Kuvio* kuviotaulukko[3]);
int main()
{
int sivun_leveys, sivun_korkeus, i, valinta;
char tekstuuri;
Kuvio* kuviot[3];
for(i=0; i<3; i++)
{
cout << "Muodostetaanko neliö (syötä 1) vai nelikulmio (syötä muu luku): ";
cin >> valinta;
if (valinta == 1)
{
cout << "Anna muodostettavan neliön sivun pituus: ";
cin >> sivun_leveys;
cout << "Syötä merkki, jota käytetään neliön tekstuurina: ";
cin >> tekstuuri;
kuviot[i] = new Nelio(tekstuuri, sivun_leveys);
}
else
{
cout << "Anna muodostettavan nelikulmion sivun korkeus: ";
cin >> sivun_korkeus;
cout << "Anna muodostettavan nelikulmion sivun leveys: ";
cin >> sivun_leveys;
cout << "Syötä merkki, jota käytetään nelikulmion tekstuurina: ";
cin >> tekstuuri;
kuviot[i] = new Nelikulmio(tekstuuri, sivun_korkeus, sivun_leveys);
}
}
cout << endl << "Muodostetut kuviot piirrettynä:" << endl << endl;
TulostaKuviot(kuviot);
return 0;
}
//** ---------- ---------- ---------- **//
void TulostaKuviot(Kuvio* kuviotaulukko[3]) {
for (int i = 0; i < 3; i++) {
kuviotaulukko[i]->Piirra();
cout << endl;
}
}
```

+ 110
- 0
9_shallow-and-deep-copy/1_copy-operations.md View File

@ -0,0 +1,110 @@
## 1 Kopiointi- ja sijoitusmuodostimen toteuttaminen
**Tehtävä:**
Kurssin viimeisessä tehtävässä sinun tulee määritellä luokka Luku, sekä toteuttaa tähän kuuluvat jäsenfunktiot. Luokka sisältää yhden jäsenmuuttujan luku_, joka on osoitin kokonaislukutyypin (int) tietoon. Kun luokasta muodostetaan olio, on sen oletusmuodostimen varattava osoittimen mukainen muistialue, osoitettava varattu muisti luokan jäsenmuuttujaan ja alustettava varattu tila arvolla 0. Vastaavasti purkajan tehtävänä on vapauttaa luokan tarvitsema muisti kun luku-olio tuhotaan.
Luku-luokassa on kaksi tavallista jäsenfunktiota: Tulosta() ja Muuta(). Edellinen funktio tulostaa luku-olion jäsenmuuttujan osoittaman sisällön esimerkkitulosteen mukaisesti ja jälkimmäinen muuttaa sisällön parametrina välitetyllä arvolla. Tulosta ei siis ota vastaan parametreja eikä palauta arvoa, kun taas Muuta saa kokonaislukuparametrin muttei palauta mitään.
Edellisten lisäksi luokkaan on kirjoitettava kopiointi- ja sijoitusmuodostimet. Kopiomuodostimen on toimittava siten, että luku-olion kopion jäsenmuuttujan viittaama arvo on sama kuin alkuperäisellä luku-oliolla kuitenkin niin, että alkuperäinen ja kopio viittaavat eri muistialueisiin. Muistialueet sisältävät vain saman arvon. Sijoitusoperaattorin toteuttamisessa on toimittava samoin. Jos luku-olio sijoitetaan toiseen, saa sijoituksen kohde sijoitettavan luku-olion tilan mutta muutokset sijoituksen kohteena olevan olion tilassa eivät saa näkyä sijoitettavassa oliossa.
Luokkaa testataan pääohjelmassa, josta siitä tehdään luku-olioita joita kopioidaan ja sijoitetaan toisiinsa.
Example output:
```
Luku on: 100
Luku on: 100
Luku on: 100
Luku on: 200
Luku on: 300
Luku on: 200
```
**Vastaus:**
```
#include <iostream>
using namespace std;
class Luku {
public:
Luku();
~Luku();
void Tulosta();
void Muuta(int luku);
// Introduce copy constructor
Luku(const Luku& obj);
// Introduce assignment operator
Luku& operator=(const Luku& obj);
private:
int * luku_;
};
Luku::Luku()
{
luku_ = new int;
*luku_ = 0;
}
Luku::~Luku()
{
delete luku_;
}
void Luku::Muuta(int luku)
{
*luku_ = luku;
}
void Luku::Tulosta()
{
cout << "Luku on: " << *luku_ << endl;
}
// Define copy constructor: perform deep copy
Luku::Luku(const Luku& obj)
{
luku_ = new int;
*luku_ = *obj.luku_;
}
// Define assignment operator
Luku& Luku::operator=(const Luku& obj)
{
*luku_ = *obj.luku_;
return *this;
}
//** Pre-defined code in the assignment **//
int main()
{
Luku eka;
eka.Muuta(100);
eka.Tulosta(); // Luku on: 100 Print current value of eka
Luku toka(eka);
toka.Tulosta(); // Luku on: 100 copy of eka
eka.Muuta(200);
toka.Tulosta(); // Luku on: 100 copy of original eka, different memory address
toka = eka;
toka.Tulosta(); // Luku on: 200; toka gets same value than eka
eka.Muuta(300);
eka.Tulosta(); // Luku on: 300 // print current value of eka
toka.Tulosta(); // Luku on: 200 // print current value of toka
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 194
- 0
9_shallow-and-deep-copy/2_dogs-and-humans.md View File

@ -0,0 +1,194 @@
## 1 Ihmisiä ja koiria
**Tehtävä**
Kurssin viimeisessä tehtävässä sinun tulee kirjoittaa kaksi luokkaa: Koira ja Isanta. Alla oleva pääohjelma käyttää kirjoittamiasi luokkia ja tehtävän tarkoituksena on, että osaisit rakentaa luokat tulkitsemalla pääohjelmaa, sekä esimerkkitulostusta, jonka pääohjelma muodostaa kun luokat on toteutettu oikein. Seuraavassa muutama vihje, joiden pitäisi helpottaa luokkien rakentamista:
- Isännällä voi olla koira, mutta vaikka koiralla olisi isäntä, se "ei tiedä" isännästään mitään.
- Kun luokasta Ihminen muodostetaan uusi ihminen, ihminen ei saa automaattisesti koiraa vastuulleen.
- Kun ihmistä pyydetään kävelyttämään koiraa, riippuu ihmisen toiminta siitä, onko hänellä koira vastuullaan.
Alla näet pääohjelman, jolla luokkiasi testataan:
```
int main()
{
string koiran_nimi, ihmisen_nimi;
cout << "Anna ihmisen nimi: ";
cin >> ihmisen_nimi;
cout << "Anna koiran nimi: ";
cin >> koiran_nimi;
cout << endl;
Ihminen* isanta = new Ihminen(ihmisen_nimi);
Koira* rekku = new Koira(koiran_nimi);
isanta->KavelytaKoiraa(7);
rekku->Hauku();
isanta->OtaVastuuKoirasta(rekku);
isanta->KavelytaKoiraa(7);
rekku->Hauku();
return 0;
}
```
Example output:
```
Anna ihmisen nimi: Simo
Anna koiran nimi: Rex
Simo: Mutta eihän minulla ole koiraa...
Rex: Hau hau! Olen kävellyt 0 kilometriä.
Simo: Rex käveli juuri 7 kilometriä.
Rex: Hau hau! Olen kävellyt 7 kilometriä.
```
**Vastaus:**
```
#include <iostream>
using namespace std;
class Ihminen;
class Koira
{
public:
Koira(string koiran_nimi);
~Koira();
void Hauku();
string HaeNimi();
void AsetaIsanta(Ihminen* ihminen);
private:
string koiran_nimi_;
Ihminen* ihminen_;
};
class Ihminen
{
public:
Ihminen(string ihmisen_nimi);
~Ihminen();
void KavelytaKoiraa(int matka);
void OtaVastuuKoirasta(Koira* koira);
int HaeMatka();
private:
string ihmisen_nimi_;
int matka_;
Koira* koira_;
};
Koira::Koira(string koiran_nimi) : koiran_nimi_(koiran_nimi)
{
}
Koira::Koira::~Koira()
{
delete ihminen_;
}
string Koira::HaeNimi()
{
return koiran_nimi_;
}
void Koira::AsetaIsanta(Ihminen* ihminen)
{
ihminen_ = ihminen;
}
void Koira::Hauku()
{
int matka;
if (!ihminen_)
{
matka = 0;
}
else
{
matka = ihminen_->HaeMatka();
}
cout << koiran_nimi_ << ": Hau hau! Olen kävellyt " << matka << " kilometriä." << endl;
}
Ihminen::Ihminen(string ihmisen_nimi) : ihmisen_nimi_(ihmisen_nimi)
{
}
Ihminen::~Ihminen()
{
delete koira_;
}
void Ihminen::OtaVastuuKoirasta(Koira* koira)
{
// Sido koira-olio tähän ihmisolioon
koira_ = koira;
// Sido tämä ihmisolio koira-olioon
koira_->AsetaIsanta(this);
}
void Ihminen::KavelytaKoiraa(int matka)
{
if (!koira_)
{
// Jos mitään koira-oliota ei ole sidottu tähän ihmisolioon
cout << ihmisen_nimi_ << ": Mutta eihän minulla ole koiraa..." << endl;
}
else
{
// Jos koira-olio on sidottu tähän ihmisolioon
matka_ = matka;
cout << ihmisen_nimi_ << ": " << koira_->HaeNimi() << " käveli juuri " << matka_ << " kilometriä." << endl;
}
}
int Ihminen::HaeMatka()
{
return matka_;
}
//
//** Pre-defined code in the assignment **//
int main()
{
string koiran_nimi, ihmisen_nimi;
cout << "Anna ihmisen nimi: ";
cin >> ihmisen_nimi;
cout << endl;
cout << "Anna koiran nimi: ";
cin >> koiran_nimi;
cout << endl;
Ihminen* isanta = new Ihminen(ihmisen_nimi);
Koira* rekku = new Koira(koiran_nimi);
isanta->KavelytaKoiraa(7);
rekku->Hauku();
isanta->OtaVastuuKoirasta(rekku);
isanta->KavelytaKoiraa(7);
rekku->Hauku();
return 0;
}
//** ---------- ---------- ---------- **//
```

+ 46
- 2
README.md View File

@ -1,3 +1,47 @@
# cpp-basics
# C++ basics
C++ fundamentals through coding exercises
C++ fundamentals through coding exercises.
Contents of this repository are based on [C++ programming course material](https://campusonline.fi/course/olio-ohjelmointi-c/) provided by Metropolia University of Applied Sciences.
**NOTE**: Assignments and their descriptions are in Finnish for meanwhile. I have a plan to translate them to English.
**NOTE**: In real world, class declarations should _always_ be done in header files. These assignments are quite simple and used single `cpp` files including all code required for programs.
## Contents
- [Fundamentals](1_fundamentals)
- Description: C++ syntax, functions, `for` & `while` loop
- [Classes and methods](2_classes-and-methods)
- Description: Classes and methods in C++
- [Creating a class](3_creating-class)
- Description: Class structure, visibility and data handling
- [Pointers, reference variables and memory handling](4_pointers-vars-and-memory-handling)
- Description: Pointers, reference variables and basic memory handling in C++
- [Object lifetime](5_object-lifetime)
- Description: Object constructors and destructors in C++
- [UML principles](6_uml-principles)
- Description: Understanding and implementing UML schemas as C++ code
- [Class relations](7_class-relations)
- Description: Relations between multiple classes
- [Inheritance](8_inheritance)
- Description: Basics of inheritance, polymorfism, parent & child classes, virtual functions
- [Shallow and deep copy](9_shallow-and-deep-copy)
- Description: Basics of object shallow and deep copy operations in C++

Loading…
Cancel
Save