Dnevnik ocena

Dovršiti tip Ocene, koji čuva int broj i int* podaci napisati:

Zadaci:

  1. Konstruktor: Inicijalizovati n ocena na nule.
  2. Destruktor: Oslobodi memoriju, a zatim ispiši ~Ocene(): memorija oslobodjena.
  3. 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;).
  4. int& at(int i) i int at(int i) const: Vraća i-tu ocenu i proverava 0 <= i < broj pomoću assert.
  5. int ucitaj_ocene(Ocene& o): Učitava ocene i, u sučaju greške, vraća poziciju prve ocene van 5..10. Pozicije se računaju od 1, a u slučaju uspešnog učitavanja vraća 0.

Napomena: Nijedan delete[] ne sme da se pojavi van strukture Ocene.

Pitanja za razmišljanje:

Ulaz

U prvom redu učitava se broj ocena n $(1 \le n \le 1000)$. U drugom redu učitava se 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:

  1. Ispisati prosek (dve decimale) i broj ocena, svaki u svom redu.
  2. Napraviti b kao kopiju od a, postaviti b.at(0) = 10, i ispisati ocene od b, u jednom redu.
  3. Napraviti c sa jednom ocenom, dodeliti mu c = a, i ispisati ocene od c.
  4. Izvršiti a = a; i ispisati ocene od a (biće nepromenjene).
  5. Na kraju, destruktori ispisuju ~Ocene(): memorija oslobodjena tri puta (za c, 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)
}