Иди на текст

Прва вежба

Једна класа са пуно метода

Нерешени задаци

Белешке

Објектно-оријентисана програмска парадигма је конципирана као систем објеката који међусобно интерагују једни са другима, прослеђујући поруке и реагујући на њих.

У сваком објекту су енкапсулирана његова стања и понашања. Често правимо паралелу са објектима из реалног света – студент, аутомобил и сл. Аутомобил поседује нека стања, тј. атрибуте као што су број седишта, максимална брзина, тренутна брзина, али и понашања, тј. методе као што су додај гас, кочи, ... Студент може од атрибута поседовати број индекса, просечна оцена, година студија, а као методе нпр. полагање испита, упис наредне године, испис, ...

Управо објекти шаљу међусобно поруке и реагују на њих путем међусобног позива метода које поседују.

Класа је шаблон из којег се праве, односно инстанцирају објекти. Чест је случај да желимо да заштитимо атрибуте и методе објекта што је могуће употребом спецификаторима приступа (private, protected, public).

  • Приватним (private) чланицама је могуће приступити само уоквиру исте те класе (коришћење приватних атрибута и позивање приватних метода могуће само унутар метода исте те класе).
  • Заштићеним (protected) чланицама је могуће приступити само уоквиру исте те класе и класа изведених из ње.
  • Јавним (public) чланицама је могуће приступати из било ког дела програма.

У програмском језику C++, дефиниција сваке класе се углавном пише у засебној ….h датотеци, а потом се такође у засебној ….cpp датотеци укључи та дефиниција класе и затим имплементују конструктори, деконструктор и методе те класе. Чест је случај да назив обе ове датотеке буде исти као и сам назив класе које оне дефинишу, тј. чије методе имплементују.

Битно је навести include guard-ове унутар ….h датотеке где се дефинише класа, јер је могуће да више фатотека укључује тражену класу, а потом се те датотеке укључују у датотеци где се налази main функција и самим тим може доћи до дупликације дефиниције класе, што води до компајлаторске грешке.

Два честа начина употребе include guard-ова приказана су испод, еквивалентна су и подједнако се примењују.

1
2
3
4
5
6
#pragma once


class Klasa {
    // Telo klase...
}
#ifndef KLASA_H
#define KLASA_H


class Klasa {
    // Telo klase...
}


#endif

#pragma once је очигледно краћа варијанта и потребно је написати само то на почетку ….h датотеке у којој дефинишемо класу. Није дефинисано C++ стандардном, али сваки компајлер који се данас користи подржава ову нестандардну препроцесорску директиву.

Други начин употребљава стандардне препроцесорске директиве и као прва линија ….h датотеке би се писало #ifndef KLASA_H, потом друга линија #define KLASA_H. У наредним линијама би писали све остало потребно за дефиницију класе, а након тога, као последњу линију писали #endif. KLASA_H овде је само пример и може бити неки произвољан назив, али је по конвенцији често формата <име класе>_H или INC_<назив пројекта>_<назив класе>_H.

У ….cpp датотеци се најпре уључује ….h датотека у којој је дефинисана класа, потом је могуће комбиновати име класе и назив метода употребом бинарног резолуционог оператора :: и имплементовати конструкторе, деструкторе и методе класе.

#include "Klasa.h"

Klasa::Klasa() {

}

Klasa::~Klasa() {

}

void Klasa::Metod1() {

}

bool Klasa::Metod2(int a) {
    return a > 10
}

Уколико се назив атрибута поклапа са називом параметара методе, како би направили дистинкцију између њих потребно је употребити this-><назив атрибута> за приступ атрибуту, заменом <назив атрибута> са стварним називом атрибута, док је параметру методе могуће приступати као по обичају. Употреба this-><назив атрибута> синтаксе је наравно увек могућа, чак и уколико се не поклапају називи параметара са називом атрибута.

Задатак 0.

На програмском језику C++ направити класу Skup која ће као приватне чланове имати број елемената скупа и динамички низ елемената типа int, а као јавне чланице следеће методе:

  • подразумевани конструктор који поставља број елемената скупа на 0;
  • конструктор за постављање броја елемената скупа и заузимање неопходног простора у меморији;
  • деструктор
  • inline методу која враћа број елемената скупа;
  • методу која избацује дупликате из скупа;
  • методу која испитује да ли задати елемент припада скупу;
  • методу за уређење елемената скупа у нерастући редослед;
  • методу за учитавање елемената скупа са стандардног улаза и
  • методу за приказ елемената скупа на стандардни излаз.

У функцији main инстанцирати објекат класе Skup у динамичкој зони меморије која садржи 10 елемената, учитати његове елементе са стандардног улаза, испитати да ли неколико произвољно унетих бројева припада том скупу. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати све остале имплементиране методе класе.

Програмски ко̑д

#ifndef SKUP_H
#define SKUP_H


class Skup {
private:
    int brElemenata;
    int *elementi;

public:
    Skup();

    Skup(int brElemenata);

    ~Skup();

    int BrElemenata() const {
        return brElemenata;
    }

    int UkloniDuplikate();

    bool Pripada(int element);

    void Uredi();

    void Ucitaj();

    void Prikazi();
};


#endif
#include <iostream>
#include "Skup.h"

Skup::Skup() {
    brElemenata = 0;
    elementi = nullptr;
}

Skup::Skup(int brElemenata) {
    this->brElemenata = brElemenata;
    this->elementi = new int[brElemenata];
}

Skup::~Skup() {
    delete[] elementi;
}

int Skup::UkloniDuplikate() {
    int stariBr = brElemenata;
    for (int i = 0; i < brElemenata; i++) {
        for (int j = brElemenata - 1; j > i; j--) {
            if (elementi[i] == elementi[j]) {
                for (int k = j; k < brElemenata - 1; k++) {
                    elementi[k] = elementi[k + 1];
                }
                brElemenata--;
            }
        }
    }

    return stariBr - brElemenata;
}

bool Skup::Pripada(int element) {
    for (int i = 0; i < brElemenata; i++) {
        if (element == elementi[i]) {
            return true;
        }
    }

    return false;
}

void Skup::Uredi() {
    for (int i = 0; i < brElemenata - 1; i++) {
        for (int j = i + 1; j < brElemenata; j++) {
            if (elementi[j] > elementi[i]) {
                int pom = elementi[j];
                elementi[j] = elementi[i];
                elementi[i] = pom;
            }
        }
    }
}

void Skup::Ucitaj() {
    for (int i = 0; i < brElemenata; i++) {
        std::cin >> elementi[i];
    }
}

void Skup::Prikazi() {
    for (int i = 0; i < brElemenata; i++) {
        std::cout << elementi[i] << " ";
    }
    std::cout << std::endl;
}
#include <iostream>
#include "Skup.h"

int main() {
    auto skup1 = new Skup(10);
    skup1->Ucitaj();

    std::cout << "Element 5 " << (skup1->Pripada(5) ? "" : "ne ") << "pripada skupu." << std::endl;
    std::cout << "Element 24 " << (skup1->Pripada(24) ? "" : "ne ") << "pripada skupu." << std::endl;
    std::cout << "Element -3 " << (skup1->Pripada(-3) ? "" : "ne ") << "pripada skupu." << std::endl;

    auto skup2 = new Skup(5);

    skup2->Ucitaj();
    std::cout << "Br. elementa: " << skup2->BrElemenata() << std::endl;
    skup2->Prikazi();
    skup2->UkloniDuplikate();
    std::cout << "Br. elementa: " << skup2->BrElemenata() << std::endl;
    skup2->Prikazi();
    skup2->Uredi();
    skup2->Prikazi();

    delete skup1;
    delete skup2;

    return 0;
}

Задатак 1.

На програмском језику C++ направити класу Student која ће као приватне чланове имати име и презиме студента дефинисане као char*, број индекса, максимални број испита, број положених испита, низ оцена запамћен у динамичкој зони меморије (цели бројеви у опсегу од 5 до 10), а као јавне следеће методе чланице:

  • конструктор који иницијализује максималан број испита на факултету,
  • деструктор,
  • inline методе које враћају број индекса и број положених испита,
  • методу која у низ оцена додаје оцену са последњег положеног испита,
  • методу за учитавање података о студенту са стандардног улаза,
  • методу која на стандардном излазу приказује све оцене почевши од највеће до најмање,
  • методу за приказ података о студенту на стандардни излаз,
  • методу која ажурира име и презиме студента.

У функцији main инстанцирати објекат класе Student са произвољно унетим бројем испита, учитати податке о студенту са стандардног улаза и у вектор оцена са положених испита додати неколико оцена. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати све остале инмплементиране методе класе.

Програмски ко̑д

#ifndef STUDENT_H
#define STUDENT_H

class Student {
private:
    char *ime;
    char *prezime;
    int brojIndeksa;
    int maksimalanBrojIspita;
    int brojPolozenihIspita;
    int *ocene;

public:
    Student(int maksimalanBrojIspita);

    ~Student();

    int BrojIndeksa() const {
        return brojIndeksa;
    }

    int BrojPolozenihIspita() const {
        return brojPolozenihIspita;
    }

    bool DodajOcenu(int ocena);

    void UcitajPodatke();

    void IspisiPodatke();

    void IspisiOcene();

    void PromeniImeIPrezime(char *novoIme, char *novoPrezime);
};


#endif
#include <iostream>
#include "Student.h"

Student::Student(int maksimalanBrojIspita) {
    this->maksimalanBrojIspita = maksimalanBrojIspita;
    this->ocene = new int[maksimalanBrojIspita];
    this->ime = new char[50];
    this->prezime = new char[50];
}

Student::~Student() {
    delete[] ocene;
    delete[] ime;
    delete[] prezime;
}

bool Student::DodajOcenu(int novaOcena) {
    if (novaOcena < 5 || novaOcena > 10) {
        return false;
    }

    ocene[brojPolozenihIspita++] = novaOcena;
    return true;
}

void Student::UcitajPodatke() {
    std::cin >> ime;
    std::cin >> prezime;
    std::cin >> brojIndeksa;
}

void Student::IspisiPodatke() {
    std::cout << ime << std::endl
              << prezime << std::endl
              << brojIndeksa << std::endl
              << brojPolozenihIspita << "/" << maksimalanBrojIspita << std::endl;
}

void Student::IspisiOcene() {
    auto sortiraneOcene = new int[brojPolozenihIspita];

    for (int i = 0; i < brojPolozenihIspita; i++) {
        sortiraneOcene[i] = ocene[i];
    }

    for (int i = 0; i < brojPolozenihIspita; i++) {
        for (int j = i + 1; j < brojPolozenihIspita; j++) {
            if (sortiraneOcene[j] > sortiraneOcene[i]) {
                int pom = sortiraneOcene[j];
                sortiraneOcene[j] = sortiraneOcene[i];
                sortiraneOcene[i] = pom;
            }
        }
    }

    for (int i = 0; i < brojPolozenihIspita; i++) {
        std::cout << sortiraneOcene[i] << " ";
    }

    std::cout << std::endl;
}

void Student::PromeniImeIPrezime(char *novoIme, char *novoPrezime) {
    ime = novoIme;
    prezime = novoPrezime;
}
#include <iostream>
#include "Student.h"

int main() {
    auto student1 = Student(43);
    student1.UcitajPodatke();
    student1.DodajOcenu(7);
    student1.DodajOcenu(5);
    student1.DodajOcenu(3);
    student1.DodajOcenu(10);

    auto student2 = new Student(46);
    student2->UcitajPodatke();
    student2->IspisiPodatke();
    student2->PromeniImeIPrezime(new char[]{"Milica"}, new char[]{"Micic"});
    std::cout << student2->BrojIndeksa() << std::endl;
    student2->DodajOcenu(6);
    student2->DodajOcenu(2);
    student2->DodajOcenu(10);
    student2->DodajOcenu(88);
    student2->DodajOcenu(5);
    student2->DodajOcenu(7);
    student2->IspisiPodatke();
    student2->IspisiOcene();
    std::cout << student2->BrojPolozenihIspita() << std::endl;

    delete student2;

    return 0;
}

Задатак 2.

На програмском језику C++ креирати класу Poligon која ће као приватне чланове имати број темена полигона и динамичке низове x и y координата темена, а као јавне следеће методе чланица:

  • конструктор без аругмената који поставља број темена на 0,
  • конструктор који иницијализује број темена у полигону,
  • деструктор,
  • inline методу која враћа број темена полигона,
  • методу која израчунава обим полигона,
  • методу која ичитава координате темена полигона са стандардног улаза,
  • методу која враћа две међусобне најудаљеније тачке у равни,
  • методу која приказује координате темена на стандардни излаз,
  • методу која избацује једно теме из полигона и смањује број темена за 1.

У функцији main иницијализовати објекат класе Poligon са произвољно унетим бројем темена, учитати координате његови темена са стандарног улаза и приказати његов обим на стандардни излаз. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати све остале имплементиране методе класе.

Програмски ко̑д

#ifndef POLIGON_H
#define POLIGON_H

#include <tuple>

class Poligon {
private:
    int n;
    double *x, *y;

public:
    Poligon();

    Poligon(int n);

    ~Poligon();

    int BrojTemena() {
        return n;
    }

    double Obim();

    void Ucitaj();

    std::tuple<int, int, int, int> NajudaljenijeTacke();

    void Prikaz();

    void UkloniTeme();
};

#endif
#include <cmath>
#include <iostream>
#include "Poligon.h"

Poligon::Poligon() {
    n = 0;
    x = nullptr;
    y = nullptr;
}

Poligon::Poligon(int n) {
    this->n = n;
    x = new double[n];
    y = new double[n];
}

Poligon::~Poligon() {
    delete[] x;
    delete[] y;
}

double Poligon::Obim() {
    double obim = 0;
    for (int i = 0; i < n; i++) {
        obim += sqrt(pow(x[(i + 1) % n] - x[i], 2) + pow(y[(i + 1) % n] - y[i], 2));
    }
    return obim;
}

void Poligon::Ucitaj() {
    for (int i = 0; i < n; i++) {
        std::cin >> x[i] >> y[i];
    }
}

std::tuple<int, int, int, int> Poligon::NajudaljenijeTacke() {
    int i1 = 0, i2 = 0;
    double max = 0;
    for (int i = 0; i < n; i++) {
        double d = sqrt(pow(x[(i + 1) % n] - x[i], 2) + pow(y[(i + 1) % n] - y[i], 2));
        if (d > max) {
            max = d;
            i1 = (i + 1) % n;
            i2 = i;
        }
    }
    return {x[i1], y[i1], x[i2], y[i2]};
}

void Poligon::Prikaz() {
    for (int i = 0; i < n; i++) {
        std::cout << "(" << x[i] << ", " << y[i] << ")" << std::endl;
    }
}

void Poligon::UkloniTeme() {
    auto newX = new double[n - 1];
    auto newY = new double[n - 1];

    for (int i = 0; i < n - 1; i++) {
        newX[i] = x[i];
        newY[i] = y[i];
    }

    delete[] x;
    delete[] y;

    n--;

    x = newX;
    y = newY;
}
#include <iostream>
#include "Poligon.h"

int main() {
    auto poligon1 = Poligon(7);
    poligon1.Ucitaj();
    std::cout << poligon1.Obim() << std::endl;

    auto poligon2 = new Poligon(9);
    poligon2->Ucitaj();
    auto tacka = poligon2->NajudaljenijeTacke();
    double x1 = std::get<0>(tacka);
    double y1 = std::get<1>(tacka);
    double x2 = std::get<2>(tacka);
    double y2 = std::get<3>(tacka);
    std::cout << "(" << x1 << ", " << y1 << "); (" << x2 << ", " << y2 << ")" << std::endl;
    std::cout << poligon2->BrojTemena() << std::endl;
    poligon2->Prikaz();
    poligon2->UkloniTeme();
    std::cout << poligon2->BrojTemena() << std::endl;
    poligon2->Prikaz();

    delete poligon2;

    return 0;
}

Задатак 3.

На програмском језику C++ направити класу Image која ће као приватне чланове имати квадратну матрицу целобројних података (који могу имати вредности 0 и 1), назив локације где је слика снимљена (char*), а као јавне следеће методе чланице:

  • подразумевани конструктор који поставља димензију матрице на 0,
  • конструктор за постављање величине матрице,
  • деструктор,
  • inline методу која враћа димензију матрице,
  • методу која инвертује слику (где је била 0, поставља се 1 и обрнуто),
  • методу која учитава садржај слике са стандардног улаза,
  • методу која приказује садржај слике на стандардни излаз,
  • методу која редукује димензије слике простим одсецањем (crop).

У функцији main инстанцирати објекат класе Image произвољне величине, учитати његов садржај са стандардног улаза и инвертовати је. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати и све остале имплементиране методе класе.

Програмски ко̑д

#ifndef IMAGE_H
#define IMAGE_H


class Image {
private:
    short **data;
    char *location;
    int size;
public:
    Image();

    Image(int size);

    ~Image();

    int Dimension() const {
        return size;
    }

    void Invert();

    void Load();

    void Print();

    bool Crop(int newSize);
};


#endif
#include <iostream>
#include "Image.h"

Image::Image() {
    size = 0;
    location = nullptr;
    data = nullptr;
}

Image::Image(int size) {
    this->size = size;
    location = new char[size];
    data = new short*[size];
    for (int i = 0; i < size; i++) {
        data[i] = new short[size];
    }
}

Image::~Image() {
    delete[] location;
    for (int i = 0; i < size; i++) {
        delete[] data[i];
    }
    delete[] data;
}

void Image::Invert() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; ++j) {
            data[i][j] = data[i][j] == 0 ? 1 : 0;
        }
    }
}

void Image::Load() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            std::cin >> data[i][j];
        }
    }
}

void Image::Print() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            std::cout << data[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

bool Image::Crop(int newSize) {
    if (newSize > size) {
        return false;
    }

    auto **newData = new short*[newSize];
    for (int i = 0; i < newSize; i++) {
        newData[i] = new short[newSize];
    }

    for (int i = 0; i < newSize; i++) {
        for (int j = 0; j < newSize; j++) {
            newData[i][j] = data[i][j];
        }
    }

    for (int i = 0; i < size; i++) {
        delete[] data[i];
    }

    delete[] data;

    data = newData;
    size = newSize;

    return true;
}
#include <iostream>
#include "Image.h"

int main() {
    auto image1 = Image(10);
    image1.Load();
    image1.Invert();
    image1.Print();

    auto image2 = new Image(5);
    image2->Load();
    std::cout << image2->Dimension() << std::endl;
    image2->Print();
    image2->Crop(10);
    std::cout << image2->Dimension() << std::endl;
    image2->Print();
    image2->Crop(3);
    std::cout << image2->Dimension() << std::endl;
    image2->Print();

    delete image2;

    return 0;
}

Задатак 4.

На програмском језику C++ направити класу Buffer која ће као приватне чланове имати динамички низ целобројних података, његову величину и тренутни број уписаних елемената, а као јавне следеће методе чланице:

  • подразумевани конструктор који поставља величину бафера на 0,
  • конструктор за постављање величине бафера,
  • деструктор,
  • inline методу која враћа тренутни број елемената у баферу,
  • методу push која уписује податак на крај бафера,
  • методу pop која чита последњи додати податак и избацује га из бафера,
  • методу која приказује садржај бафера на стандардни излаз,
  • методу која дуплира величину бафера,
  • метода која избацује незаузета места из бафера.

У функцији main инстанцирати објекат класе Buffer, у њега уписати првих n природних бројва. Направити још један бафер, али у динамичкој зони меморије, и у њега ископирати садржај првог. Затим из првог бафера избацити m елемената и на стандардни излаз приказати тренутни број елемената у оба бафера и њихове садржаје.

Програмски ко̑д

#ifndef BUFFER_H
#define BUFFER_H


class Buffer {
private:
    int *data;
    int size;
    int count;
public:
    Buffer();

    Buffer(int size);

    Buffer(Buffer &b);

    ~Buffer();

    int Count() {
        return count;
    }

    bool Push(int value);

    int Pop();

    void Print();

    void Duplicate();

    void ClearFree();
};


#endif
#include <iostream>
#include "Buffer.h"

Buffer::Buffer() {
    size = 0;
    data = nullptr;
    count = 0;
}

Buffer::Buffer(int size) {
    this->size = size;
    count = 0;
    data = new int[size];
}

Buffer::Buffer(Buffer &b) {
    this->size = b.size;
    this->count = b.count;
    this->data = new int[b.count];

    for (int i = 0; i < b.count; i++) {
        this->data[i] = b.data[i];
    }
}

Buffer::~Buffer() {
    delete[] data;
}

bool Buffer::Push(int value) {
    if (count >= size) {
        return false;
    }

    data[count++] = value;
    return true;
}

int Buffer::Pop() {
    if (count == 0) {
        return -1;
    }

    return data[count--];
}

void Buffer::Print() {
    for (int i = 0; i < count; i++) {
        std::cout << data[i] << " ";
    }
    std::cout << std::endl;
}

void Buffer::Duplicate() {
    int *newData = new int[size * 2];
    size = size * 2;

    for (int i = 0; i < count; i++) {
        newData[i] = data[i];
    }

    delete[] data;
    data = newData;
}

void Buffer::ClearFree() {
    int *newData = new int[count];
    size = count;
    for (int i = 0; i < count; i++) {
        newData[i] = data[i];
    }

    delete[] data;
    data = newData;
}
#include <iostream>
#include "Buffer.h"

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

    auto buf1 = Buffer(n);

    for (int i = 1; i <= n; i++) {
        buf1.Push(i);
    }

    auto buf2 = new Buffer(buf1);

    for (int i = 0; i < m; i++) {
        buf1.Pop();
    }

    std::cout << buf1.Count() << std::endl;
    buf1.Print();

    std::cout << buf2->Count() << std::endl;
    buf2->Print();

    delete buf2;

    return 0;
}

Задатак 5.

На програмском језику C++ направити класу Vektor која ће као приватне чланове имати динамички низ целобројних података и димензију вектора, а као јазне следеће методе чланице:

  • подразумевани конструктор који поставља димензију вектора на 0,
  • конструктор за постављање величине низа,
  • деструктор,
  • inline методу која поставља k-ти елемент вектора,
  • константну inline методу која враћа вредност k-тог елемента у вектору,
  • методу која уређује елементе низа у неопадајући редослед,
  • методу која рачуна скаларни производ два вектора (ако су услови испуњени),
  • методу која враћа индекс елемената који има вредност најближи средњој вредности свих елемената у вектору.

У функцији main инстанцирати објекат класе Vektor, учитати његове елементе са стандардног улаза, уредити га и на стандардни излаз приказати вредности елемената. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати и све остале имплементиране методе класе.

Програмски ко̑д

#ifndef VEKTOR_H
#define VEKTOR_H


class Vektor {
private:
    int* vec;
    int n;
public:
    Vektor();
    Vektor(int n);
    ~Vektor();

    void SetElement(int k, int val) {
        vec[k] = val;
    }

    const int GetElement(int k) {
        return vec[k];
    }

    void Sort();
    int ScalarProd(const Vektor &v);
    int IdxAvg() const;
};


#endif
#include <cmath>
#include "Vektor.h"

Vektor::Vektor() {
    n = 0;
    vec = nullptr;
}

Vektor::Vektor(int n) {
    this->n = n;
    vec = new int[n];
}

Vektor::~Vektor() {
    delete[] vec;
}

void Vektor::Sort() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n - 1; j++) {
            if (vec[j] > vec[j + 1]) {
                int tmp = vec[j];
                vec[j] = vec[j + 1];
                vec[j + 1] = tmp;
            }
        }
    }
}

int Vektor::ScalarProd(const Vektor& v) {
    if (n != v.n) {
        return 0;
    }

    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += vec[i] * v.vec[i];
    }
    return sum;
}

int Vektor::IdxAvg() const {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += vec[i];
    }

    int avg = sum / n;
    int idx = 0;
    int min = abs(vec[0] - avg);
    for (int i = 1; i < n; i++) {
        if (abs(vec[i] - avg) < min) {
            min = abs(vec[i] - avg);
            idx = i;
        }
    }

    return idx;
}
#include <iostream>

#include "Vektor.h"

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

    auto vek1 = Vektor(n);

    for (int i = 0; i < n; i++) {
        int a;
        std::cin >> a;
        vek1.SetElement(i, a);
    }

    vek1.Sort();

    for (int i = 0; i < n; i++) {
        std::cout << vek1.GetElement(i) << " ";
    }
    std::cout << std::endl;

    auto vek2 = new Vektor(n);

    for (int i = 0; i <= n; i++) {
        vek2->SetElement(i, i * 2 + 1);
    }

    std::cout << vek2->ScalarProd(vek1) << std::endl;
    std::cout << vek2->IdxAvg() << std::endl;

    delete vek2;

    return 0;
}

Задатак 6.

На програмском језику C++ направити класу Minesweeper која ће као приватне чланове имати матрицу која представља модел минског поља и димензије те матрице, као и назив поља (char*). Сваки елемент матрице је типа bool и има вредност true уколико је на том пољу мина. Класа садржи следеће јавне методе чланице:

  • подразумевани конструктор који поставља димензију матрице на 10×10,
  • конструктор за постављање димензија матрице,
  • деструктор,
  • inline методе које враћају димензије поља,
  • методу која враћа број мина које окружују задато поље, односно -1 уколико то поље садржи мину,
  • методу која са стандардног улаза учитава распоред мина (са стандардног улаза се учитавају вредности 0 и 1; ако је учитана вредност 0 на одговарајућој позицији у матрици треба уписати false, у супротном, елемент матрице је true),
  • методу за приказ минског поља на стандардни излаз,
  • методу која избацује све редове и колоне у којима се не налази ни једна мина.

У функцији main инстанцирати објекат класе Minesweeper, учитати распоред мина са стандардног улаза. Са стандардног улаза учитати и позицију једног поља. Уколико се на том пољу налази мина, на стандардни излаз приказати садржај целог минског поља, у супротном приказати број мина које то поље окружују. Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати све остале имплементиране методе класе.

Програмски ко̑д

#ifndef MINESWEEPER_H
#define MINESWEEPER_H

#include <tuple>

class Minesweeper {
    int n;
    int m;
    bool** mines;
    char* name;

    Minesweeper();
    Minesweeper(int n, int m);
    ~Minesweeper();

    int DimN() const {
        return n;
    }

    int DimM() const {
        return m;
    }

    int CountMines(int x, int y);
    void Load();
    void Print();
    void RemoveEmpty();
};


#endif
#include <iostream>
#include "Minesweeper.h"

Minesweeper::Minesweeper() {
    n = 10;
    m = 10;
    mines = new bool *[n];
    for (int i = 0; i < n; i++) {
        mines[i] = new bool[m];
    }
}

Minesweeper::Minesweeper(int n, int m) {
    this->n = n;
    this->m = m;
    mines = new bool *[n];
    for (int i = 0; i < n; i++) {
        mines[i] = new bool[m];
    }
}

Minesweeper::~Minesweeper() {
    for (int i = 0; i < n; i++) {
        delete[] mines[i];
    }
    delete[] mines;
}

int Minesweeper::CountMines(int x, int y) {
    if (mines[x][y]) {
        return -1;
    }

    int count = 0;
    for (int i = x - 1; i <= x + 1; i++) {
        if (i < 0 || i >= n) {
            continue;
        }
        for (int j = y - 1; j <= y + 1; j++) {
            if (j < 0 || j >= m) {
                continue;
            }
            if (mines[i][j]) {
                count++;
            }
        }
    }
    return count;
}

void Minesweeper::Load() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int x;
            std::cin >> x;
            mines[i][j] = x == 1;
        }
    }
}

void Minesweeper::Print() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            std::cout << (mines[i][j] ? "1" : "0");
        }
        std::cout << std::endl;
    }
}

void Minesweeper::RemoveEmpty() {
    for (int i = 0; i < n; i++) {
        bool hasMine = false;
        for (int j = 0; j < m; j++) {
            if (mines[i][j]) {
                hasMine = true;
                break;
            }
        }
        if (!hasMine) {
            for (int j = i; j < n - 1; j++) {
                mines[j] = mines[j + 1];
            }
            n--;
            i--;
        }
    }

    // Remove columns.
    for (int j = 0; j < m; j++) {
        bool hasMine = false;
        for (int i = 0; i < n; i++) {
            if (mines[i][j]) {
                hasMine = true;
                break;
            }
        }
        if (!hasMine) {
            for (int i = 0; i < n; i++) {
                for (int k = j; k < m - 1; k++) {
                    mines[i][k] = mines[i][k + 1];
                }
            }
            m--;
            j--;
        }
    }
}
1
2
3
4
5
6
7
#include <iostream>

int main() {
    // TODO: main funkcija...

    return 0;
}

Задатак 7.

На програмском језику C++ направити класу Matrica која као приватне чланове има матрицу, димензије матрице и назив матрице (char*). Сваки елемент матрице је типа double. Класа садржи следеће јавне методе чланице:

  • конструктор без параметара који поставља димензије матрице на 20×20,
  • констуктор који поставља димензије матрице,
  • деструктор,
  • inline методе које враћају димензије матрице,
  • методу која враћа суму вредности елемента траженог реда,
  • методу која враћа суму вредности елемента тражне колоне,
  • методу за унос елемента матрице са стандардног улаза,
  • методу за приказ елемената на стандардни излаз,
  • методу за рачунање Кронекеровог производа две матрице,
  • методу за рачунање производа две матрице.

У финкцији main инстанцирати објекат класе Matrica, учитати вредности елемената матрице са стандардног улаза. Затим сумирати вредност 1. и 3. колоне, као и 2. и 3. реда, а потом приказати матрицу.

Програмски ко̑д

#ifndef MATRICA_H
#define MATRICA_H


class Matrica {
private:
    int n, m;
    double **data;
    char *ime;

public:
    Matrica();
    Matrica(int n, int m);
    ~Matrica();

    int DimN() const {
        return n;
    }

    int DimM() const {
        return m;
    }

    double SumaReda(int i);
    double SumaKolone(int j);
    void Unos();
    void Prikaz();
    Matrica *Proizvod(Matrica *b);
    Matrica *KronekerovProizvod(Matrica *b);
};


#endif
#include <iostream>
#include "Matrica.h"

Matrica::Matrica() {
    n = 20;
    m = 20;
    data = new double*[n];
    for (int i = 0; i < n; i++) {
        data[i] = new double[m];
    }
}

Matrica::Matrica(int n, int m) {
    this->n = n;
    this->m = m;
    data = new double*[n];
    for (int i = 0; i < n; i++) {
        data[i] = new double[m];
    }
}

Matrica::~Matrica() {
    for (int i = 0; i < n; i++) {
        delete[] data[i];
    }
    delete[] data;
}

double Matrica::SumaReda(int i) {
    double s = 0;
    for (int j = 0; j < m; j++) {
        s += data[i][j];
    }

    return s;
}

double Matrica::SumaKolone(int j) {
    double s = 0;
    for (int i = 0; i < n; i++) {
        s += data[i][j];
    }

    return s;
}

void Matrica::Unos() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            std::cin >> data[i][j];
        }
    }
}

void Matrica::Prikaz() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            std::cout << data[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

Matrica *Matrica::KronekerovProizvod(Matrica *b) {
    int p = this->n * b->n;
    int q = this->m * b->m;

    auto c = new Matrica(p, q);

    for (int i = 0; i < p; i++) {
        for (int j = 0; j < q; j++) {
            c->data[i][j] = this->data[i / b->n][j / b->m] * b->data[i % b->n][j % b->m];
        }
    }

    return c;
}

Matrica *Matrica::Proizvod(Matrica *b) {
    auto c = new Matrica(this->n, b->m);

    for (int i = 0; i < this->n; i++) {
        for (int j = 0; j < b->m; j++) {
            c->data[i][j] = 0;
            for (int k = 0; k < this->m; k++) {
                c->data[i][j] += this->data[i][k] * b->data[k][j];
            }
        }
    }

    return c;
}
1
2
3
4
5
6
7
#include <iostream>

int main() {
    // TODO: main funkcija...

    return 0;
}

Задатак 8.

На програмском језику C++ направити класу String која ће као приватне чланове имати дужину ниске и знаковни низ (низ типа char) запамћен у динамичкој зони мемотије, а као јавне следеће методе чланице:

  • конструктор без параметара који поставља дижину ниске на 0,
  • конструктор који иницијализује дужину знаковног низа и резервише простор у динамичкој зони меморије за његово представљање,
  • деструктор,
  • inline методу која враћа дужину ниске,
  • методу која проналази почетну позицију задате подниске у ниски,
  • методу за учитавање ниске са стандардног улаза,
  • методу за приказ ниске на стандардни излаз.

У функцији main инстанцирати објекат класе String чија је максимална дужина 10 карактера, учитати његову вредност са стандног улаза и на стандардни излаз приказати поруку о томе да ли унета ниска садржи подниску "ana". Сем тога, инстанцирати још један објекат ове класе у динамичкој зони меморије и испробати све остале имплементиране методе класе.

Програмски ко̑д

#ifndef STRING_H
#define STRING_H


class String {
    int length;
    char *data;

public:
    String();
    String(int length);
    ~String();

    int Length() const {
        return length;
    }

    int SubString(String subString);
    void Load();
    void Print();
};


#endif
#include <iostream>
#include "String.h"

String::String() {
    length = 0;
    data = nullptr;
}

String::String(int length) {
    this->length = length;
    data = new char[length];
}

String::~String() {
    delete[] data;
}

int String::SubString(String subString) {
    for (int i = 0; i < length; i++) {
        if (data[i] == subString.data[0]) {
            bool isSubString = true;
            for (int j = 1; j < subString.length; j++) {
                if (data[i + j] != subString.data[j]) {
                    isSubString = false;
                    break;
                }
            }
            if (isSubString) {
                return i;
            }
        }
    }

    return -1;
}

void String::Load() {
    std::cin >> data;
}

void String::Print() {
    std::cout << data << std::endl;
}
1
2
3
4
5
6
7
#include <iostream>

int main() {
    // TODO: main funkcija...

    return 0;
}

Задатак 9.

На програмском језику C++ направити класу Picture која ће као приватне чланове имати квадратну матрицу целобројних података који узимају вредности из опсега од 0 до 512 запамћени у динамичкој зони меморије, а као јавне следеће методе чланице:

  • подразумевани конструктор који поставља димензију матрице на 0,
  • конструктор за постављање димензије матрице и за резервисање простора у динамичкој зони меморије за елементе матрице,
  • деструктор,
  • inline методу која враћа димензију матрице (потребно је одједном вратити обе димензије слике),
  • методу void Brightness(int s) која у сваком елементу матрице додаје прослеђену вредност. Водити рачуна о томе да, након трансформације вредности целобројне матрице остану у опсегу од 0 до 512,
  • методу која учитава садржај слике са стандардног улаза,
  • методу која приказује садржај слике на стандардни излаз,
  • имплементирати resize методу по следећем упутству:
    • Нове димензије слике: int nWidth, int nHeight;
    • Почетна слика има димензије width и height;
    • Израчунају се resize фактори:
      • nXFactor = (double)width/(double)nWidth;
      • nYFactor = (double)height/(double)nHeight;
    • Сваки пиксел одредишне слике на позицији x, y се копира из почетне слике са позиције ((int)(Math.Floor(x * nXFactor)), (int)(Math.Floor(y * nYFactor))).

У функцији main инстанцирати објекат класе Picture величине 10×10, учитати његов садржај са стандардног улаза, а затим просветлити слику за неку прозивољну вредност. Сем тога, инстанцирати још један објекат ове класе и испробати и све остале имплементиране методе класе.

Програмски ко̑д

#ifndef PICTURE_H
#define PICTURE_H


#include <iostream>
#include <tuple>

class Picture {
private:
    int** pixels;
    int width;
    int height;

public:
    Picture();

    Picture(int width, int height);

    ~Picture();

    std::tuple<int, int> Dimensions() {
        return {width, height};
    }

    void Brighten(int s);
    void Load();
    void Show();
    void Resize(int nWidth, int nHeight);
};


#endif
#include "Picture.h"
#include <cmath>

Picture::Picture() {
    width = 0;
    height = 0;
    pixels = new int*[0];
}

Picture::Picture(int width, int height) {
    this->width = width;
    this->height = height;
    pixels = new int*[height];
    for (int x = 0; x < height; x++) {
        pixels[x] = new int[width];
    }
}

Picture::~Picture() {
    for (int x = 0; x < height; x++) {
        delete[] pixels[x];
    }
    delete[] pixels;
}

void Picture::Brighten(int s) {
    for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            pixels[x][y] += std::min(512, pixels[x][y] + s);
        }
    }
}

void Picture::Load() {
    for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            std::cin >> pixels[x][y];
        }
    }
}

void Picture::Show() {
    for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            std::cout << pixels[x][y] << " ";
        }
        std::cout << std::endl;
    }
}

void Picture::Resize(int nWidth, int nHeight) {
    double nXFactor = (double)width/(double)nWidth;
    double nYFactor = (double)height/(double)nHeight;

    int** nPixels = new int*[nHeight];
    for (int x = 0; x < nHeight; x++) {
        nPixels[x] = new int[nWidth];
        for (int y = 0; y < nWidth; y++) {
            nPixels[x][y] = pixels[(int)(std::floor(x * nXFactor))][(int)(std::floor(y * nYFactor))];
        }
    }

    for (int x = 0; x < height; x++) {
        delete[] pixels[x];
    }
    delete[] pixels;

    pixels = nPixels;
}
1
2
3
4
5
6
7
#include <iostream>

int main() {
    // TODO: main funkcija...

    return 0;
}