Dnevnik ocena
Dovršiti tip Ocene, koji čuva int broj i int* podaci napisati:
Zadaci:
- Konstruktor: Inicijalizovati
nocena na nule. - Destruktor: Oslobodi memoriju, a zatim ispiši
~Ocene(): memorija oslobodjena. - Konstruktor kopije i dodela kopije: Objekat koji se konstruiše, odnosno objekat kome se dodeljuje, i objekat koji se kopira ne smeju da dele memoriju. Dodela mora biti bezbedna i za samododelu (
a = a;). int& at(int i)iint at(int i) const: Vraćai-tu ocenu i proverava0 <= i < brojpomoćuassert.int ucitaj_ocene(Ocene& o): Učitava ocene i, u sučaju greške, vraća poziciju prve ocene van5..10. Pozicije se računaju od1, a u slučaju uspešnog učitavanja vraća0.
Napomena: Nijedan delete[] ne sme da se pojavi van strukture Ocene.
Pitanja za razmišljanje:
- Zašto
ucitaj_ocenemora da primaOcene&, a neOcene? - U dodeli kopije, zašto se prvo pravi novi niz i kopira, a tek onda oslobađa stari? Šta bi se desilo kod
a = a;sa obrnutim redosledom?
Ulaz
U prvom redu učitava se broj ocena n n ocena.
Izlaz
Ako je neka ocena van 5..10, ispisati nevalidna ocena na poziciji p (p od 1, prva takva ocena), zatim ispisati ~Ocene(): memorija oslobodjena.
U suprotnom:
- Ispisati prosek (dve decimale) i broj ocena, svaki u svom redu.
- Napraviti
bkao kopiju oda, postavitib.at(0) = 10, i ispisati ocene odb, u jednom redu. - Napraviti
csa jednom ocenom, dodeliti muc = a, i ispisati ocene odc. - Izvršiti
a = a;i ispisati ocene oda(biće nepromenjene). - Na kraju, destruktori ispisuju
~Ocene(): memorija oslobodjenatri puta (zac,b,a).
Primer
Ulaz
6
7 9 10 6 9 8
Izlaz
8.17
6
10 9 10 6 9 8
7 9 10 6 9 8
7 9 10 6 9 8
~Ocene(): memorija oslobodjena
~Ocene(): memorija oslobodjena
~Ocene(): memorija oslobodjena
Primer
Ulaz
4
8 5 11 7
Izlaz
nevalidna ocena na poziciji 3
~Ocene(): memorija oslobodjena
Postavka
main.cpp
#include <cassert>
#include <iomanip>
#include <iostream>
namespace matf
{
struct Ocene {
int broj;
int* podaci;
// TODO (1): konstruktor
Ocene(int n)
{
return undefined;
}
// TODO (2): destruktor
~Ocene()
{
return undefined;
}
// TODO (3): konstruktor kopije
Ocene(const Ocene& ostale)
{
return undefined;
}
// TODO (3): dodela kopije
Ocene& operator=(const Ocene& ostale)
{
return undefined;
}
// TODO (4): implementirati at (obe verzije)
// Preduslov 0 <= i < broj
int& at(int i)
{
return undefined;
}
int at(int i) const
{
return undefined;
}
};
// TODO (5): implementirati ucitaj_ocene
// vraca poziciju (od 1) prve ocene van 5..10,
// ili vraca 0
int ucitaj_ocene(Ocene& o)
{
return undefined;
}
double prosek(const Ocene& o)
{
double s = 0;
for (int i = 0; i < o.broj; ++i)
s += o.at(i);
return s / o.broj;
}
int broj_prolaznih(const Ocene& o)
{
int k = 0;
for (int i = 0; i < o.broj; ++i)
if (o.at(i) >= 6)
++k;
return k;
}
void ispisi(const Ocene& o)
{
for (int i = 0; i < o.broj; ++i) {
if (i > 0) std::cout << ' ';
std::cout << o.at(i);
}
std::cout << std::endl;
}
} // namespace matf
int main()
{
int n;
std::cin >> n;
matf::Ocene a(n);
int los = matf::ucitaj_ocene(a);
if (los != 0) {
std::cout << "nevalidna ocena na poziciji " << los << std::endl;
return 0;
}
std::cout << std::fixed << std::setprecision(2) << matf::prosek(a) << std::endl;
std::cout << matf::broj_prolaznih(a) << std::endl;
matf::Ocene b = a; // konstruktor kopije
b.at(0) = 10;
matf::ispisi(b);
matf::Ocene c(1);
c = a; // dodela kopije
matf::ispisi(c);
a = a; // samododela (namerno)
matf::ispisi(a);
return 0;
}
Rešenje
main.cpp
#include <cassert>
#include <iomanip>
#include <iostream>
namespace matf
{
struct Ocene {
int broj;
int* podaci;
// Konstruktor preuzima: n ocena, sve nula.
Ocene(int n) : broj(n), podaci(new int[n]{}) {}
// Destruktor oslobadja - na svakom izlasku iz dosega.
~Ocene()
{
delete[] podaci;
std::cout << "~Ocene(): memorija oslobodjena" << std::endl;
}
// Konstruktor kopije: nov blok, sa istim elementima - a i njena kopija
// ne sme da deli memoriju.
Ocene(const Ocene& ostale) : broj(ostale.broj), podaci(new int[ostale.broj])
{
for (int i = 0; i < broj; ++i)
podaci[i] = ostale.podaci[i];
}
// Dodela kopije: ovaj objekat vec ima blok - prvo napraviti kopiju, pa
// osloboditi stari (da bi o = o; ostalo bezbedno).
Ocene& operator=(const Ocene& ostale)
{
if (this == &ostale)
return *this;
int* novi_podaci = new int[ostale.broj];
for (int i = 0; i < ostale.broj; ++i)
novi_podaci[i] = ostale.podaci[i];
delete[] podaci;
podaci = novi_podaci;
broj = ostale.broj;
return *this;
}
// preduslov: 0 <= i < broj
int& at(int i)
{
assert(i >= 0 && i < broj);
return podaci[i];
}
// preduslov: 0 <= i < broj
int at(int i) const
{
assert(i >= 0 && i < broj);
return podaci[i];
}
};
// Ucitava o.broj ocena u o. Vraca poziciju prve ocene van 5..10,
// ili 0 ako su sve ispravne. Pozicije računa od 1.
int ucitaj_ocene(Ocene& o)
{
for (int i = 0; i < o.broj; ++i) {
std::cin >> o.at(i);
if (o.at(i) < 5 || o.at(i) > 10)
return i + 1;
}
return 0;
}
double prosek(const Ocene& o)
{
double s = 0;
for (int i = 0; i < o.broj; ++i)
s += o.at(i);
return s / o.broj;
}
int broj_prolaznih(const Ocene& o)
{
int k = 0;
for (int i = 0; i < o.broj; ++i)
if (o.at(i) >= 6)
++k;
return k;
}
void ispisi(const Ocene& o)
{
for (int i = 0; i < o.broj; ++i) {
if (i > 0) std::cout << ' ';
std::cout << o.at(i);
}
std::cout << std::endl;
}
} // namespace matf
int main()
{
int n;
std::cin >> n;
matf::Ocene a(n);
int los = matf::ucitaj_ocene(a);
if (los != 0) {
std::cout << "nevalidna ocena na poziciji " << los << std::endl;
return 0; // ~Ocene() oslobadja a ovde
}
std::cout << std::fixed << std::setprecision(2) << matf::prosek(a) << std::endl;
std::cout << matf::broj_prolaznih(a) << std::endl;
matf::Ocene b = a; // konstruktor kopije
b.at(0) = 10;
matf::ispisi(b);
matf::Ocene c(1);
c = a; // dodela kopije
matf::ispisi(c);
a = a; // samododela (namerno)
matf::ispisi(a);
return 0; // ~Ocene() oslobadja c, b, a (tim redom)
}