3. gyakorlat - megoldások
1. feladat. Definiáljunk egy osztályt, ami racionális számokat reprezentál.
A szám értékét tároljuk két int változóban. Definiáljunk legalább
kétféle konstruktort, a +, -, *, /, == és != operátorokat értelemszerűen, és legyen egy tagfüggvénye az osztálynak,
amely visszaadja a szám reciprokát. Használjuk az előadáson bemutatott gcd függvényt
egy tagfüggvényben, ami leegyszerűsíti a törtet. Definiáljunk továbbá egy << operátort is,
amivel kiírhatjuk a szám értékét.
Megoldás:
rational.h
#ifndef RATIONAL_H
#define RATIONAL_H
#include <iostream>
#include "gcd.h"
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& simplifyIt();
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;
};
ostream& operator<<(ostream& os, const Rational& r);
}
#endif
rational.cpp
#include "Rational.h"
#include <iostream>
#include "gcd.h"
using namespace std;
namespace bme {
Rational::Rational(): numerator(0), denominator(1) {}
Rational::Rational(int num, int denom) {
if (denom == 0) {
cerr << "Denominator cannot be zero, Rational is set to 0/1." << endl;
numerator = 0;
denominator = 1;
}
else {
numerator = num;
denominator = denom;
}
}
int Rational::getNumerator() const {
return numerator;
}
int Rational::getDenominator() const {
return denominator;
}
Rational& Rational::simplifyIt() {
int _gcd = gcd(numerator, denominator);
if (_gcd != 0) {
numerator /= _gcd;
denominator /= _gcd;
}
return *this;
}
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) {
cerr << "ERROR: cannot divide by zero." << endl;
return Rational(0, 1);
}
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) {
cerr << "ERROR: cannot calculate reciprocal of zero." << endl;
return Rational(0, 1);
}
return Rational(denominator, numerator);
}
ostream& operator<<(ostream& os, const Rational& r) {
os << "(" << r.getNumerator() << "/" << r.getDenominator() << ")";
return os;
}
}
Egy teszt:
#include <iostream>
#include "Rational.h"
using namespace std;
using namespace bme;
int main() {
Rational r1(3, 4);
Rational r2(5, 6);
Rational sum = r1 + r2;
cout << "Sum: " << sum << endl;
cout << "Simplified sum: " << sum.simplifyIt() << endl;
Rational diff = r1 - r2;
cout << "Difference: " << diff << endl;
Rational product = r1 * r2;
cout << "Product: " << product << endl;
Rational quotient = r1 / r2;
cout << "Quotient: " << quotient << endl;
Rational reciprocal = r1.reciprocal();
cout << "Reciprocal of " << r1 << ": " << reciprocal << endl;
cout << "r1 == r2: " << (r1 == r2 ? "true" : "false") << endl;
cout << "r1 != r2: " << (r1 != r2 ? "true" : "false") << endl;
return 0;
}
2. feladat: Definiáljunk egy osztályt, amely egy háromszöget reprezentál. Használjuk az előadáson készített Point
osztályt a csúcsok tárolására. Írjunk tagfüggvényeket, amik visszaadják a háromszög kerületét, terü-
letét, súlypontját
Megoldás:
A Point osztály első (a 3. előadáson bemutatott) verziójának a dokumentációja és forráskódja elérhető
itt.
triangle.h
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include "point.h"
#include <cmath>
#include <iostream>
namespace bme {
class Triangle {
private:
Point p1, p2, p3;
public:
Triangle(const Point& _p1, const Point& _p2, const Point& _p3);
double perimeter() const;
double area() const;
Point centroid() const;
void print() const;
};
}
#endif
triangle.cpp
#include "triangle.h"
#include <cmath>
#include <iostream>
using namespace std;
namespace bme {
Triangle::Triangle(const Point& _p1, const Point& _p2, const Point& _p3) : p1(_p1), p2(_p2), p3(_p3) {}
double Triangle::perimeter() const {
return dist(p1, p2) + dist(p2, p3) + dist(p3, p1);
}
double Triangle::area() const {
double a = dist(p1, p2);
double b = dist(p2, p3);
double c = dist(p3, p1);
double s = (a + b + c) / 2.0;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
Point Triangle::centroid() const {
return (p1+p2+p3)/3.0;
}
void Triangle::print() const {
cout << "Triangle vertices: " << p1 << ", " << p2 << ", " << p3 << endl;
cout << "Perimeter: " << perimeter() << endl;
cout << "Area: " << area() << endl;
cout << "Centroid: " << centroid() << endl;
}
}
Egy teszt:
#include "triangle.h"
using namespace bme;
int main() {
Point p1(0, 0);
Point p2(4, 0);
Point p3(0, 3);
Triangle t(p1, p2, p3);
t.print();
return 0;
}
3. feladat: Definiáljunk egy osztályt, amely $[a;b]$ zárt intervallumokat reprezentál,
ahol a, b valós számok. Az osztálynak legyen egy default konstruktora, valamint egy konstruktora,
amely paraméterként megkapja az intervallum két végpontját. Legyenek tagfüggvényei, amelyek visszaadják az intervallum végpontjait, ill.
amelyekkel ezek beállíthatók, továbbá legyen egy tagfüggvénye, amely eldönti, hogy az intervallum
metsz-e egy paraméterként megadott intervallumot. Definiáljuk
a < operátort, ami lexikografikusan rendezi az intervallumot, azaz [a;b]<[c;d]
pontosan akkor teljesül, ha a<c vagy (a=c és b<d). Definiáljuk a << operátort
is, amivel az intervallumot kiírhatjuk a képernyőre, valamint az == és != operátorokat
értelemszerűen.
Megoldás:
interval.h
#ifndef INTERVAL_H
#define INTERVAL_H
#include <iostream>
using namespace std;
class Interval {
private:
double a;
double b;
public:
Interval();
Interval(double _a, double _b);
double getA() const;
double getB() const;
void setA(double _a);
void setB(double _b);
bool intersects(const Interval& other) const;
bool operator==(const Interval& other) const;
bool operator!=(const Interval& other) const;
bool operator<(const Interval& other) const;
};
ostream& operator<<(ostream& os, const Interval& interval);
#endif
interval.cpp
#include "interval.h"
#include <iostream>
using namespace std;
Interval::Interval() {
a = 0;
b = 0;
}
Interval::Interval(double _a, double _b) {
if (_a > _b) {
cerr << "The left endpoint must be less than or equal to the right endpoint, inverval set to [0;0].";
a = 0;
b = 0;
}
a = _a;
b = _b;
}
double Interval::getA() const {
return a;
}
double Interval::getB() const {
return b;
}
void Interval::setA(double _a) {
a = _a;
}
void Interval::setB(double _b) {
b = _b;
}
bool Interval::intersects(const Interval& other) const {
return !((b < other.a) || (other.b < a));
}
bool Interval::operator==(const Interval& other) const {
return (a == other.a) && (b == other.b);
}
bool Interval::operator!=(const Interval& other) const {
return !((*this) == other);
}
bool Interval::operator<(const Interval& other) const {
return (a < other.a) || ((a == other.a) && (b < other.b));
}
ostream& operator<<(ostream& os, const Interval& interval) {
os << "[" << interval.getA() << "; " << interval.getB() << "]";
return os;
}
Egy teszt:
#include <iostream>
#include "interval.h"
using namespace std;
int main() {
Interval interval1(1, 5);
Interval interval2(3, 7);
Interval interval3(6, 10);
cout << "Interval 1: " << interval1 << endl;
cout << "Interval 2: " << interval2 << endl;
cout << "Interval 3: " << interval3 << endl;
cout << "Interval 1 intersects Interval 2: " << (interval1.intersects(interval2) ? "Yes" : "No") << endl;
cout << "Interval 1 intersects Interval 3: " << (interval1.intersects(interval3) ? "Yes" : "No") << endl;
cout << "Interval 1 == Interval 2: " << (interval1 == interval2 ? "Yes" : "No") << endl;
cout << "Interval 1 != Interval 3: " << (interval1 != interval3 ? "Yes" : "No") << endl;
cout << "Interval 1 < Interval 2: " << (interval1 < interval2 ? "Yes" : "No") << endl;
cout << "Interval 2 < Interval 3: " << (interval2 < interval3 ? "Yes" : "No") << endl;
return 0;
}
4. feladat:
Definiáljunk egy osztályt, ami a 3 elemű testet reprezentálja. Definiáljuk a +, −, ∗ és / operátorokat
a testműveleteknek megfelelően. Definiáljuk az == és ! = operátorokat is. Definiáljuk a << operátort
is, amivel a test elemeit kiírhatjuk a képernyőre.
Megoldás:
field3.h
#ifndef FIELD3_H
#define FIELD3_H
#include<iostream>
using namespace std;
class Field3 {
private:
int val;
public:
Field3();
Field3(int _val);
int Val()const;
bool operator==(const Field3& other)const;
bool operator!=(const Field3& other)const;
Field3 operator+(const Field3& other)const;
Field3 operator-(const Field3& other)const;
Field3 operator*(const Field3& other)const;
Field3 operator/(const Field3& other)const;
};
ostream& operator<<(ostream& os, const Field3& interval);
#endif
field3.cpp
#include "field3.h"
#include <iostream>
Field3::Field3() : val(0) {}
Field3::Field3(int _val) {
val = _val % 3;
if (val < 0) {
val += 3;
}
}
int Field3::Val()const {
return val;
}
bool Field3::operator==(const Field3& other)const {
return val == other.val;
}
bool Field3::operator!=(const Field3& other)const {
return !(*this == other);
}
Field3 Field3::operator+(const Field3& other)const {
return Field3(val + other.val);
}
Field3 Field3::operator-(const Field3& other)const {
return Field3(val - other.val);
}
Field3 Field3::operator*(const Field3& other)const {
return Field3(val * other.val);
}
Field3 Field3::operator/(const Field3& other)const {
if (other.Val() == 0) {
cerr << "ERROR: Division by zero, return value is 0." << endl;
return Field3(0);
}
return Field3(val * other.val); //3 elemű testben egy nem nulla elem
//multiplikatív inverze önmaga
}
ostream& operator<<(ostream& os, const Field3& a) {
os << a.Val();
return os;
}
Egy teszt:
#include "field3.h"
#include <iostream>
using namespace std;
int main() {
Field3 a(1);
Field3 b(2);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "a+b = " << a + b << endl;
cout << "a-b = " << a - b << endl;
cout << "a*b = " << a * b << endl;
cout << "a/b = " << a / b << endl;
cout << "a/0 = " << a / Field3(0) << endl;
return 0;
}