INFORMATIKA 3

Matematika BSc - BME TTK - 2026 tavaszi félév


7. gyakorlat - megoldások



1. feladat. Definiáljunk egy Teglalap osztályt, és származtassuk ebből a Negyzet osztályt, melyek téglalapokat ill. négyzeteket reprezentálnak. A Teglalap osztály adattagjai reprezentálják a magasságot ill. szélességet, és rendelkezzen a következő tagfüggvényekkel: A Negyzet osztály rendelkezzen egy egyparaméterű konstruktorral, amely a Teglalap osztály konstruktorán alapszik. Ezen felül legyenek ugyanazok a tagfüggvényei, mint a Teglalap osztálynak, de a magasságot ill. a szélességet megváltoztató függvények változtassák meg mindkettőt.

Megoldás:

teglalap.h

#ifndef TEGLALAP_H
#define TEGLALAP_H

class Teglalap {
protected:
    double magassag;
    double szelesseg;

public:
    Teglalap(double magassag, double szelesseg);

    double getMagassag() const;
    double getSzelesseg() const;

    virtual void setMagassag(double magassag);
    virtual void setSzelesseg(double szelesseg);

    double terulet() const;
    double kerulet() const;

    virtual ~Teglalap() = default;
};

#endif // TEGLALAP_H


teglalap.cpp

#include "teglalap.h"

Teglalap::Teglalap(double magassagParam, double szelessegParam) 
    : magassag(magassagParam), szelesseg(szelessegParam) {}

double Teglalap::getMagassag() const {
    return magassag;
}

double Teglalap::getSzelesseg() const {
    return szelesseg;
}

void Teglalap::setMagassag(double magassagParam) {
    magassag = magassagParam;
}

void Teglalap::setSzelesseg(double szelessegParam) {
    szelesseg = szelessegParam;
}

double Teglalap::terulet() const {
    return magassag * szelesseg;
}

double Teglalap::kerulet() const {
    return 2 * (magassag + szelesseg);
}


negyzet.h

#ifndef NEGYZET_H
#define NEGYZET_H

#include "teglalap.h"

class Negyzet : public Teglalap {
public:
    Negyzet(double oldal);

    void setMagassag(double oldal);
    void setSzelesseg(double oldal);
};

#endif // NEGYZET_H


negyzet.cpp

#include "negyzet.h"

Negyzet::Negyzet(double oldal) : Teglalap(oldal, oldal) {}

void Negyzet::setMagassag(double oldal) {
    magassag = oldal;
    szelesseg = oldal;
}

void Negyzet::setSzelesseg(double oldal) {
    magassag = oldal;
    szelesseg = oldal;
}


3. feladat. Definiáljunk egy Alakzat osztályt, amely egy síkidomot reprezentál. Legyenek adattagjai, melyek a síkidom pozícióját határozzák meg. Származtassunk belőle különböző osztályokat, pl. kör, téglalap, paralelogramma, sokszög stb. osztályokat. Legyenek az Alakzat osztálynak tisztán virtuális terulet és kerulet tagfüggvényei, és valósítsuk meg ezeket a származtatott osztályokban. Deklaráljunk olyan tömböt/tárolót, amelyben különböző típusú síkidomokat tárolhatunk.

Megoldás:

alakzat.h

#ifndef ALAKZAT_H
#define ALAKZAT_H

#include "point.h"
using namespace std;

namespace bme {

    class Alakzat {
    protected:
        Point p;

    public:
        Alakzat(double x, double y) : p(x, y) {}

        virtual double terulet() const = 0;
        virtual double kerulet() const = 0;

        Point pozicio() const { return p; };

        virtual ~Alakzat() = default;
    };

}

#endif // ALAKZAT_H


teglalap.h

#ifndef TEGLALAP_H
#define TEGLALAP_H

#include "alakzat.h"

namespace bme {

    class Teglalap : public Alakzat {
    private:
        double magassag;
        double szelesseg;

    public:
        Teglalap(double x, double y, double magassag, double szelesseg);

        double terulet() const override;
        double kerulet() const override;
    };

}

#endif // TEGLALAP_H


teglalap.cpp

#include "alakzat.h"
#include "teglalap.h"

namespace bme {

    Teglalap::Teglalap(double x, double y, double magassag, double szelesseg)
        : Alakzat(x, y), magassag(magassag), szelesseg(szelesseg) {
    }

    double Teglalap::terulet() const {
        return magassag * szelesseg;
    }

    double Teglalap::kerulet() const {
        return 2 * (magassag + szelesseg);
    }

}


kor.h

#ifndef KOR_H
#define KOR_H

#include "alakzat.h"

namespace bme {

    class Kor : public Alakzat {
    private:
        double sugar;

    public:
        Kor(double x, double y, double sugar);

        double terulet() const override;
        double kerulet() const override;
    };

}

#endif // KOR_H


kor.cpp

#define _USE_MATH_DEFINES
#include "kor.h"
#include "alakzat.h"
#include <cmath>

namespace bme {

    Kor::Kor(double x, double y, double sugar) : Alakzat(x, y), sugar(sugar) {}

    double Kor::terulet() const {
        return M_PI * sugar * sugar;
    }

    double Kor::kerulet() const {
        return 2 * M_PI * sugar;
    }

}


main.cpp

#include <iostream>
#include <vector>
#include "alakzat.h"
#include "teglalap.h"
#include "kor.h"

using namespace std;
using namespace bme;

int main() {
    // Tároló különböző síkidomok számára
    vector<Alakzat*> alakzatok;

    alakzatok.push_back(new Teglalap(0, 0, 5, 10));
    alakzatok.push_back(new Kor(2, 3, 4));

    for (size_t i = 0; i < alakzatok.size(); ++i) {
        cout << "Pozicio: " << (*alakzatok[i]).pozicio() << "\n";
        cout << "Terulet: " << (*alakzatok[i]).terulet() << "\n";
        cout << "Kerulet: " << (*alakzatok[i]).kerulet() << "\n\n";
    }

    for (size_t i = 0; i < alakzatok.size(); ++i) {
        delete alakzatok[i];
    }

    return 0;
}



4. feladat. Készítsünk egy matematikai kivételek kezelésére szolgáló osztályt, amely az std::exception leszármazottja. Származtassunk ebből további, speciális hibák esetén (pl. 0-val való osztás, szinguláris objektummal végzett tilos művelet, nem megfelelő dimenziókból származó hiba) dobandó kivételeket. Írjuk felül a what() tagfüggvényt, mely szövegesen leírja az adott hibát. Írjuk át a korábban írt Rational osztályt, amely racionális számokat tárol. Dobjunk kivételt, ha a konstruktorban a nevezőt 0-ra állítják, ha 0-val akarnak osztani, ill. ha a 0-nak akarják a reciprokát venni. Használjuk a fent készített megfelelő kivételosztályt.

Megoldás:

mathexcept.h

#ifndef MATHEXCEPT_H
#define MATHEXCEPT_H

#include <exception>

using namespace std;

namespace bme {

    class MathException : public exception {
    public:
        MathException() {}
        const char* what() const noexcept override;
    };

    class DivByZeroExcept : public MathException {
    public:
        DivByZeroExcept() {}
        const char* what() const noexcept override;

    };

    class DimensionExcept : public MathException {
    public:
        DimensionExcept() {}
        const char* what() const noexcept override;

    };

    class SingularityExcept : public MathException {
    public:
        SingularityExcept() {}
        const char* what() const noexcept override;

    };

}
#endif


mathexcept.cpp

#include "mathexcept.h"

const char* bme::MathException::what() const noexcept {
    return "ERROR: Mathematical error.";
}

const char* bme::DivByZeroExcept::what() const noexcept {
    return "ERROR: Division by zero.";
}

const char* bme::DimensionExcept::what() const noexcept {
    return "ERROR: Invalid dimensions.";
}

const char* bme::SingularityExcept::what() const noexcept
{
    return "ERROR: Invalid operation on a singular object.";
}


rational.h

#ifndef RATIONAL_H
#define RATIONAL_H

#include <iostream>

using namespace std;

namespace bme {

    class Rational {
    private:
        int numerator;
        int denominator;

    public:
        Rational();
        Rational(int num, int denom);

        int getNumerator() const;
        int getDenominator() const;

        Rational operator+(const Rational&) const;
        Rational operator-(const Rational&) const;
        Rational operator*(const Rational&) const;
        Rational operator/(const Rational&) const;
        bool operator==(const Rational&) const;
        bool operator!=(const Rational&) const;

        Rational reciprocal() const;

        friend ostream& operator<<(ostream& os, const Rational& r);
    };

    ostream& operator<<(ostream& os, const Rational& r);

}

#endif


rational.cpp

#include "rational.h"
#include <iostream>
#include "mathexcept.h"

using namespace std;

namespace bme {

    Rational::Rational() {
        numerator = 0;
        denominator = 1;
    }

    Rational::Rational(int num, int denom) {
        if (denom == 0) {
            throw DivByZeroExcept(); // Nevező nem lehet 0
        }
        numerator = num;
        denominator = denom;
    }

    int Rational::getNumerator() const {
        return numerator;
    }

    int Rational::getDenominator() const {
        return denominator;
    }

    Rational Rational::operator+(const Rational& other) const {
        int commonDenom = denominator * other.denominator;
        int newNumerator = numerator * other.denominator + other.numerator * denominator;
        return Rational(newNumerator, commonDenom);
    }

    Rational Rational::operator-(const Rational& other) const {
        int commonDenom = denominator * other.denominator;
        int newNumerator = numerator * other.denominator - other.numerator * denominator;
        return Rational(newNumerator, commonDenom);
    }

    Rational Rational::operator*(const Rational& other) const {
        int newNumerator = numerator * other.numerator;
        int newDenominator = denominator * other.denominator;
        return Rational(newNumerator, newDenominator);
    }

    Rational Rational::operator/(const Rational& other) const {
        if (other.numerator == 0) {
            throw DivByZeroExcept(); // 0-val való osztás
        }
        int newNumerator = numerator * other.denominator;
        int newDenominator = denominator * other.numerator;
        return Rational(newNumerator, newDenominator);
    }

    bool Rational::operator==(const Rational& other) const {
        return numerator * other.denominator == denominator * other.numerator;
    }

    bool Rational::operator!=(const Rational& other) const {
        return !(*this == other);
    }

    Rational Rational::reciprocal() const {
        if (numerator == 0) {
            throw DivByZeroExcept(); // 0 reciprokának vétele
        }
        return Rational(denominator, numerator);
    }

    ostream& operator<<(ostream& os, const Rational& r) {
        os << "(" << r.numerator << "/" << r.denominator << ")";
        return os;
    }
}


Egy teszt:

main.cpp

#include "rational.h"
#include "mathexcept.h"
#include <iostream>

using namespace std;
using namespace bme;

int main() {
    try {
        // Teszt: helyes racionális szám létrehozása
        Rational r1(3, 4);
        cout << "Rational r1: " << r1 << endl;

        // Teszt: helytelen nevező (0)
        Rational r2(1, 0);
    }
    catch (const MathException& e) {
        cerr << e.what() << endl;
    }

    try {
        // Teszt: osztás 0-val
        Rational r3(1, 2);
        Rational r4(0, 1);
        Rational result = r3 / r4;
        cout << "Result of division: " << result << endl;
    }
    catch (const MathException& e) {
        cerr << e.what() << endl;
    }

    try {
        // Teszt: 0 reciprokának vétele
        Rational r5(0, 1);
        Rational reciprocal = r5.reciprocal();
        cout << "Reciprocal: " << reciprocal << endl;
    }
    catch (const MathException& e) {
        cerr << e.what() << endl;
    }

    try {
        // Teszt: helyes műveletek
        Rational r6(1, 3);
        Rational r7(2, 5);
        Rational sum = r6 + r7;
        Rational diff = r6 - r7;
        Rational prod = r6 * r7;
        Rational quot = r6 / r7;

        cout << "Sum: " << sum << endl;
        cout << "Difference: " << diff << endl;
        cout << "Product: " << prod << endl;
        cout << "Quotient: " << quot << endl;
    }
    catch (const MathException& e) {
        cerr << e.what() << endl;
    }

    return 0;
}


5. feladat. Írjunk MxN-es mátrixokat reprezentáló template osztályt (ahol a template paraméter az elemek típusa). Írjunk konstruktort, ami paraméterként a mátrix méreteit kapja meg. Az elemhozzáférést megvalósító operátor ill. tagfüggvény implementációjában helytelen indexek esetén dobjunk kivételt. A mátrixhoz lehessen hozzáadni, belőle kivonni más MxN-es-es mátrixokat, valamint más mátrixszal is össze lehessen szorozni, amennyiben a dimenziók nem megfelelőek a dobjunk kivételt. Írjunk függvényt, amely négyzetes mátrix esetén kiszámolja a mátrix inverzét, 0 determináns esetén dobjunk kivételt (elég 2x2-es mátrix esetén megvalósítani). A kivételkezeléshez használjuk az előző feladatban készített kivételosztályokat.

Megoldás:

matrix2.hpp

#ifndef MATRIX2_HPP
#define MATRIX2_HPP

#include "mathexcept.h"
#include <stdexcept>
#include <iostream>
#include <vector>

using namespace std;

namespace bme {

    template <typename T>
    class Matrix2 {
    private:
        size_t rows, cols;
        vector<vector<T>> data;

    public:
        Matrix2(size_t m, size_t n) : rows(m), cols(n), data(m, vector<T>(n, T())) {}

        T& operator()(size_t i, size_t j) {
            if (i >= rows || j >= cols) {
                throw out_of_range("Index out of bounds!");
            }
            return data[i][j];
        }

        const T& operator()(size_t i, size_t j) const {
            if (i >= rows || j >= cols) {
                throw out_of_range("Index out of bounds!");
            }
            return data[i][j];
        }

        Matrix2<T> operator+(const Matrix2<T>& other) const {
            if (rows != other.rows || cols != other.cols) {
                throw DimensionExcept();
            }
            Matrix2<T> result(rows, cols);
            for (size_t i = 0; i < rows; ++i) {
                for (size_t j = 0; j < cols; ++j) {
                    result(i, j) = data[i][j] + other(i, j);
                }
            }
            return result;
        }

        Matrix2<T> operator-(const Matrix2<T>& other) const {
            if (rows != other.rows || cols != other.cols) {
                throw DimensionExcept();
            }
            Matrix2<T> result(rows, cols);
            for (size_t i = 0; i < rows; ++i) {
                for (size_t j = 0; j < cols; ++j) {
                    result(i, j) = data[i][j] - other(i, j);
                }
            }
            return result;
        }

        Matrix2<T> operator*(const Matrix2<T>& other) const {
            if (cols != other.rows) {
                throw DimensionExcept();
            }
            Matrix2<T> result(rows, other.cols);
            for (size_t i = 0; i < rows; ++i) {
                for (size_t j = 0; j < other.cols; ++j) {
                    for (size_t k = 0; k < cols; ++k) {
                        result(i, j) += data[i][k] * other(k, j);
                    }
                }
            }
            return result;
        }

        Matrix2<T> inverse() const {
            if (rows != 2 || cols != 2) {
                throw DimensionExcept();
            }

            T det = data[0][0] * data[1][1] - data[0][1] * data[1][0];
            if (det == T(0)) {
                throw SingularityExcept();
            }

            Matrix2<T> result(2, 2);
            result(0, 0) = data[1][1] / det;
            result(0, 1) = -data[0][1] / det;
            result(1, 0) = -data[1][0] / det;
            result(1, 1) = data[0][0] / det;

            return result;
        }

        void print() const {
            for (size_t i = 0; i < rows; ++i) {
                for (size_t j = 0; j < cols; ++j) {
                    cout << data[i][j] << " ";
                }
                cout << "\n";
            }
        }
    };

}


#endif


Egy teszt:

main.cpp

#include "matrix2.hpp"
#include "mathexcept.h"
#include <iostream>

using namespace bme;

int main() {
    try {
        Matrix2<double> mat1(2, 2);
        mat1(0, 0) = 4; mat1(0, 1) = 12;
        mat1(1, 0) = 2; mat1(1, 1) = 6;

        cout << "Matrix 1:\n";
        mat1.print();

        cout << "\nInverse of Matrix 1:\n";
        Matrix2<double> inv = mat1.inverse();
        inv.print();
    }
    catch (const MathException& e) {
        cerr << e.what() << "\n";
    }

    try {
        Matrix2<double> mat1(2, 2);
        mat1(0, 0) = 4; mat1(0, 1) = 12;
        mat1(1, 0) = 2; mat1(1, 1) = 6;

        cout << "Matrix 1:\n";
        mat1.print();

        Matrix2<double> mat2(2, 1);
        mat2(0, 0) = 1; //mat2(0, 1) = 0;
        mat2(1, 0) = 0; //mat2(1, 1) = 1;
        cout << "Matrix 2:\n";
        mat2.print();
        cout << "\nSum of Matrix 1 and Matrix 2:\n";
        Matrix2<double> sum = mat1 + mat2;
        sum.print();

    }
    catch (const MathException& e) {
        cerr << e.what() << "\n";
    }

    return 0;
}