6. gyakorlat - megoldások
1. feladat. Készítsünk programot, ami a felhasználótól kéri be síkbeli pontok koordinátáit, majd kiszámolja a
ponthalmaz súlypontját. Adjunk lehetőséget a felhasználónak arra, hogy minden lépésnél eldöntse,
hogy hozzáad-e újabb pontot a ponthalmazhoz, esetleg töröl-e egy már meglévő pontot, vagy pedig
kiszámoltatja a súlypontot. Használjuk cin input stream-et és a switch utasítást az opciók közül
való választásra (nem szükséges lekezelni azokat az eseteket, ha a felhasználó rossz inputot ad meg).
Használjuk az előadáson írt bme::Point osztályt. Módosítsuk a
programot úgy, hogy a pontokhoz súlyokat rendelhessünk, és az súlyozott átlagot számoljon.
Megoldás:
#include <iostream>
#include <vector>
#include "point.h"
using namespace bme;
using namespace std;
void calculateWeightedCentroid(const vector<Point>& points, const vector<double>& weights) {
if (points.empty()) {
cout << "Nincs elerheto pont.\n";
return;
}
double sumX = 0, sumY = 0, totalWeight = 0;
for (size_t i = 0; i < points.size(); ++i) {
sumX += points[i].getX() * weights[i];
sumY += points[i].getY() * weights[i];
totalWeight += weights[i];
}
if (totalWeight == 0) {
cout << "Osszsuly nem lehet nulla.\n";
return;
}
cout << "Sulypont: (" << (sumX / totalWeight) << ", " << (sumY / totalWeight) << ")\n";
}
int main() {
vector<Point> points;
vector<double> weights;
int choice;
do {
cout << "1: Uj pont hozzaadasa\n2: Pont torlese\n3: Sulypont szamitasa\n0: Kilepes\n";
cout << "Valasztas: ";
cin >> choice;
switch (choice) {
case 1: {
double x, y, weight;
cout << "Adja meg a pont koordinatait (x y) es sulyat: ";
cin >> x >> y >> weight;
points.push_back(Point(x, y));
weights.push_back(weight);
break;
}
case 2: {
if (points.empty()) {
cout << "Nincs torolheto pont.\n";
break;
}
int index;
cout << "Adja meg a torlendo pont indexet (0-tol kezdve): ";
cin >> index;
if (index >= 0 && index < points.size()) {
points.erase(points.begin() + index);
weights.erase(weights.begin() + index);
} else {
cout << "Ervenytelen index.\n";
}
break;
}
case 3:
calculateWeightedCentroid(points, weights);
break;
case 0:
cout << "Kilepes...\n";
break;
default:
cout << "Ervenytelen valasztas!\n";
}
} while (choice != 0);
return 0;
}
2. feladat. Definiáljunk egy Counted nevű osztályt, amely számon tartja,
hogy a program futása közben hány példánya létezik. Azaz, legyen egy static
tagfüggvénye, amely visszaadja, hogy az adott pillanatban mennyi Counted
objektum található a memóriában.
Megoldás:
counted.h
#ifndef COUNTED_H
#define COUNTED_H
class Counted {
private:
static int n_objects;
public:
Counted() { n_objects++; }
~Counted() { n_objects--; }
static int count() { return n_objects; }
};
#endif
counted.cpp
#include "Counted.h"
int Counted::n_objects = 0;
Egy tesztprogram:
#include "counted.h"
#include <iostream>
using namespace std;
int main() {
Counted X, Y;
Counted* array;
array = new Counted[20];
cout << "There are " << Counted::count()
<< " Counted objects in memory" << endl;
delete[] array;
cout << "And now there are " << Counted::count()
<< " Counted objects in memory" << endl;
return 0;
}
3. feladat.
Csináljunk egy SmartArray osztályt, amely úgy működik, mint
egy int tömb, de tetszőleges indexet megadhatunk neki. A deklaráció így nézzen ki:
SmartArray X(k);
Ez a példány viselkedjen úgy, mint egy int-ekből álló k elemű tömb,
de az indexelés ne csak 0 és k-1 közt legyen lehetséges: az X[i]
adja
vissza az i modulo k maradékának megfelelő indexű elemet, ahol
k a tömb elemszáma. Írjunk másoló konstruktort és értékadó = operátort
is az osztályhoz.
Megoldás:
smart_array.h
#ifndef SMART_ARRAY_H
#define SMART_ARRAY_H
namespace bme {
class SmartArray {
private:
int N;
int* data;
int adjust_index(int k)const;
public:
SmartArray(const SmartArray& other);
SmartArray(int nels);
~SmartArray() { delete[] data; }
int get_N() const { return N; }
int& operator[](int k) { return data[adjust_index(k)]; }
const int& operator[](int k)const { return data[adjust_index(k)]; }
SmartArray& operator=(const SmartArray& other);
};
}
#endif
smart_array.cpp
#include "smart_array.h"
namespace bme {
int SmartArray::adjust_index(int k) const {
k %= N;
if (k < 0) k += N;
return k;
}
SmartArray::SmartArray(const SmartArray& other) {
N = other.N;
data = new int[N];
for (int i = 0; i < N; ++i) {
data[i] = other.data[i];
}
}
SmartArray::SmartArray(int nels) {
N = (nels > 1) ? nels : 1;
data = new int[N];
}
SmartArray& SmartArray::operator=(const SmartArray& other) {
if (this != &other) {
delete[] data;
N = other.N;
data = new int[N];
for (int i = 0; i < N; ++i) {
data[i] = other.data[i];
}
}
return *this;
}
}
4. feladat. Írjunk template swap függvényt,
amely paraméterül kap két változó referenciát,
melyek típusa (azonos) template paraméter, és megcseréli ezek értékét.
Megoldás:
#include <iostream>
using namespace std;
template<typename T>
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
cout << "Csere elott: x = " << x << ", y = " << y << endl;
mySwap(x, y);
cout << "Csere utan: x = " << x << ", y = " << y << endl;
double a = 3.14, b = 2.71;
cout << "Csere elott: a = " << a << ", b = " << b << endl;
mySwap(a, b);
cout << "Csere utan: a = " << a << ", b = " << b << endl;
return 0;
}
5. feladat.
Írjunk template függvényeket, amik visszaadják
halmazok unióját, metszetét, különbségét. Használjuk a set osztályt.
Megoldás:
#include <iostream>
#include <set>
using namespace std;
template<typename T>
set<T> set_union_custom(const set<T>& a, const set<T>& b) {
set<T> result = a;
for (const T& elem : b) {
result.insert(elem);
}
return result;
}
template<typename T>
set<T> set_intersection_custom(const set<T>& a, const set<T>& b) {
set<T> result;
for (const T& elem : a) {
if (b.find(elem) != b.end()) {
result.insert(elem);
}
}
return result;
}
template<typename T>
set<T> set_difference_custom(const set<T>& a, const set<T>& b) {
set<T> result;
for (const T& elem : a) {
if (b.find(elem) == b.end()) {
result.insert(elem);
}
}
return result;
}
int main() {
set<int> A = { 1, 2, 3, 4 };
set<int> B = { 3, 4, 5, 6 };
auto unio = set_union_custom(A, B);
auto metszet = set_intersection_custom(A, B);
auto kulonbseg = set_difference_custom(A, B);
cout << "Unió: ";
for (int x : unio) cout << x << " ";
cout << "\nMetszet: ";
for (int x : metszet) cout << x << " ";
cout << "\nKülönbség (A - B): ";
for (int x : kulonbseg) cout << x << " ";
cout << endl;
return 0;
}
6. feladat.
Írjunk template függvényt, amely paraméterül kap egy x változót, melynek típusa template paraméter,
továbbá egy n nemnegatív egész számot, és visszaadja az x+2*x+...+n*x értéket (melynek típusa
megegyezik az x típusával).
Megoldás:
template<typename T>
T sum_multiples(T x, int n) {
T result = x;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
result += x;
}
}
return result;
}
7. feladat.
Írjunk egy VectorND osztályt, amely egy n dimenziós vektort reprezentál, ahol a koordináták típusa,
valamint a vektor dimenziója is egy-egy template paraméter. Definiáljuk az összeadást, skalárral való
szorzást, valamint a skaláris szorzatot is.
Megoldás:
vectornd.hpp
#ifndef VECTORND_HPP
#define VECTORND_HPP
#include <iostream>
using namespace std;
template<typename T, size_t N>
class VectorND {
private:
T data[N];
public:
VectorND() {
for (size_t i = 0; i < N; ++i) {
data[i] = T(0);
}
}
// init egy REFERENCIA egy N elemű T típusú elemeket tartalmazó tömb elejére
// pointer átadása nem biztonságos!
VectorND(const T(&init)[N]) {
for (size_t i = 0; i < N; ++i) {
data[i] = init[i];
}
}
T& operator[](size_t index) {
return data[index];
}
const T& operator[](size_t index) const {
return data[index];
}
VectorND<T, N> operator+(const VectorND<T, N>& other) const {
VectorND<T, N> result;
for (size_t i = 0; i < N; ++i) {
result[i] = data[i] + other[i];
}
return result;
}
VectorND<T, N> operator*(const T& scalar) const {
VectorND<T, N> result;
for (size_t i = 0; i < N; ++i) {
result[i] = data[i] * scalar;
}
return result;
}
T dot(const VectorND<T, N>& other) const {
T result = T(0);
for (size_t i = 0; i < N; ++i) {
result += data[i] * other[i];
}
return result;
}
};
template<typename T, size_t N>
ostream& operator<<(ostream& os, const VectorND<T, N>& vec) {
os << "(";
for (size_t i = 0; i < N; ++i) {
os << vec[i];
if (i != N - 1) os << ", ";
}
os << ")";
return os;
}
#endif
8. feladat. Írjunk egy Matrix osztályt, amely mátrixokat reprezentál, és melynek
elemtípusa, valamint
a sor- és oszlopszáma is egy-egy template
paraméter. Definiáljuk az összeadást, skalárral való szorzást és a mátrixszorzást is.
Megoldás:
matrix.hpp
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include <iostream>
#include <vector>
using namespace std;
template<typename T, size_t Rows, size_t Cols>
class Matrix {
private:
vector<vector<T>> data;
public:
// Default konstruktor: minden elem 0
Matrix() {
for (size_t i = 0; i < Rows; ++i) {
vector<T> row(Cols, T(0)); // Egy sor létrehozása 0 értékekkel
data.push_back(row);
}
}
// a paraméter referencia egy két dimenziós tömb elejére
// pointer biztonságosan nem adható át!
Matrix(const T(&init)[Rows][Cols]) {
for (size_t i = 0; i < Rows; ++i) {
vector<T> row;
for (size_t j = 0; j < Cols; ++j) {
row.push_back(init[i][j]);
}
data.push_back(row);
}
}
T& operator()(size_t i, size_t j) {
return data[i][j];
}
const T& operator()(size_t i, size_t j) const {
return data[i][j];
}
Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols>& other) const {
Matrix<T, Rows, Cols> result;
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;
}
// Skalárral szorzás
Matrix<T, Rows, Cols> operator*(const T& scalar) const {
Matrix<T, Rows, Cols> result;
for (size_t i = 0; i < Rows; ++i) {
for (size_t j = 0; j < Cols; ++j) {
result(i, j) = data[i][j] * scalar;
}
}
return result;
}
// Mátrixszorzás (ha a méretek passzolnak)
template<size_t OtherCols>
Matrix<T, Rows, Cols> operator*(const Matrix<T, Cols, OtherCols>& other) const {
Matrix<T, Rows, OtherCols> result;
for (size_t i = 0; i < Rows; ++i) {
for (size_t j = 0; j < OtherCols; ++j) {
T sum = T(0);
for (size_t k = 0; k < Cols; ++k) {
sum += data[i][k] * other(k, j);
}
result(i, j) = sum;
}
}
return result;
}
};
template<typename T, size_t Rows, size_t Cols>
ostream& operator<<(ostream& os, const Matrix<T, Rows, Cols>& mat) {
for (size_t i = 0; i < Rows; ++i) {
for (size_t j = 0; j < Cols; ++j) {
os << mat(i, j) << " ";
}
os << endl;
}
return os;
}
#endif
main.cpp
#include "matrix.hpp"
#include<iostream>
using namespace std;
int main() {
// Mátrix inicializálása 2D tömbbel
double initA[2][2] = { {1.0, 2.0}, {3.0, 4.0} };
double initB[2][2] = { {5.0, 6.0}, {7.0, 8.0} };
Matrix<double, 2, 2> A(initA);
Matrix<double, 2, 2> B(initB);
auto C = A + B;
auto D = A * 2.0;
auto E = A * B;
cout << "A + B:\n" << C << endl;
cout << "A * 2:\n" << D << endl;
cout << "A * B:\n" << E << endl;
return 0;
}