Lov na bagove

Program učitava n ocena i ispisuje medijanu, broj ocena iznad 8, i najbolju ocenu. Sadrži četiri greške u radu sa memorijom.

Prevesti sa -g -fsanitize=address,undefined i pokrenuti na probnom ulazu. ASan se zaustavlja na prvoj grešci: pročitati vrstu greške i liniju, ispraviti, pokrenuti opet. Ponoviti dok izvršavanje ne bude bez dodatnog izveštaja.

g++ -std=c++17 -Wall -Wextra -g -fsanitize=address,undefined main.cpp

Za svaku grešku zapisati njeno ime (curenje memorije, viseći pokazivač, dvostruko oslobađanje, ili pristup van niza) i ispravku u jednoj liniji.

Ulaz

U prvom redu učitava se broj ocena n $(1 \le n \le 1000)$. U drugom redu učitava se n ocena (celi brojevi 5..10).

Izlaz

Ispisati medijanu nakon sortiranja. Ispisati broj ocena strogo većih od 8. Ispisati najveću ocenu.

Primer

Ulaz

6
7 9 10 6 9 8

Izlaz

9
3
10

Postavka

main.cpp

// Program sadrzi CETIRI greske u radu sa memorijom.
// Prevesti sa -g -fsanitize=address i pokrenuti na probnom ulazu.
//
// Za svaku gresku zapisati njeno ime sa predavanja (curenje memorije, viseci
// pokazivac, dvostruko oslobadjanje, ili pristup van niza) i ispravku.

#include <algorithm>
#include <iostream>

namespace matf
{
  int* ucitaj_ocene(int n)
  {
    int* g = new int[n];
    for (int i = 0; i < n; ++i)
      std::cin >> g[i];
    return g;
  }

  int medijana(const int* g, int n)
  {
    int* sortirano = new int[n];
    for (int i = 0; i < n; ++i)
      sortirano[i] = g[i];
    std::sort(sortirano, sortirano + n);
    return sortirano[n / 2];
  }

  int broj_iznad(const int* g, int n, int granica)
  {
    int k = 0;
    for (int i = 0; i <= n; ++i)
      if (g[i] > granica)
        ++k;
    return k;
  }

  const int* najbolja(const int* g, int n)
  {
    const int* b = g;
    for (int i = 1; i < n; ++i)
      if (g[i] > *b)
        b = g + i;
    return b;
  }

} // namespace matf

int main()
{
  int n;
  std::cin >> n;

  int* ocene = matf::ucitaj_ocene(n);
  int* rezerva = ocene;

  std::cout << matf::medijana(ocene, n) << std::endl;
  std::cout << matf::broj_iznad(ocene, n, 8) << std::endl;

  const int* b = matf::najbolja(ocene, n);

  delete[] ocene;

  std::cout << *b << std::endl;

  delete[] rezerva;

  return 0;
}

Rešenje

main.cpp

#include <algorithm>
#include <iostream>

namespace matf
{
  int* ucitaj_ocene(int n)
  {
    int* g = new int[n];
    for (int i = 0; i < n; ++i)
      std::cin >> g[i];
    return g;
  }

  // O(n log n)
  int medijana(const int* g, int n)
  {
    int* sortirano = new int[n];
    for (int i = 0; i < n; ++i)
      sortirano[i] = g[i];
    std::sort(sortirano, sortirano + n);
    int m = sortirano[n / 2];
    delete[] sortirano; // ispravka curenja memorije
    return m;
  }

  // O(n)
  int broj_iznad(const int* g, int n, int granica)
  {
    int k = 0;
    for (int i = 0; i < n; ++i) // ispravka pristupa van granica niza
      if (g[i] > granica)
        ++k;
    return k;
  }

  // O(n); pokazivac na najbolju ocenu.
  const int* najbolja(const int* g, int n)
  {
    const int* b = g;
    for (int i = 1; i < n; ++i)
      if (g[i] > *b)
        b = g + i;
    return b;
  }

} // namespace matf

int main()
{
  int n;
  std::cin >> n;

  int* ocene = matf::ucitaj_ocene(n);

  std::cout << matf::medijana(ocene, n) << std::endl;
  std::cout << matf::broj_iznad(ocene, n, 8) << std::endl;

  const int* b = matf::najbolja(ocene, n);
  std::cout << *b << std::endl;

  delete[] ocene;
  // ispravka dvostruku oslobadjanje memorije;
  // ispravka viseci pokazivac

  return 0;
}