11. Eltolt indexelésű tömb
Czirkos Zoltán · 2019.02.27.
Régebbi ZH feladat megoldása.
a) Készítsen adapter sablont (Indexelheto
), ami minden indexelhető (operator[]
) szabványos sorozattárolóra alkalmazható és segítségével egy M
elemet tartalmazó tároló első eleme N
, a második eleme N+1
, harmadik N+2
... N+M-1
indexértékkel érhető el, ahol N, és M tetszőleges egész. Alapértelmezésként N = 0
, a tároló pedig az std::vector
legyen! A sorozattároló minden tagfüggvénye legyen elérhető, kivéve az at()
! Ügyeljen a sorozattárolókra jellemző konstruktorok megvalósítására is! Példa a használatra:
Indexelheto<int, 10> v10(2); // 10-től indexelhető 2 elemű vektor
v10[10] = 1; // első eleme 1
v10[11] = 2; // második eleme 2
b) Hozzon létre az elkészített adapter és az std::deque
felhasználásával egy 20-tól indexelhető 30 elemű egész tömböt!
c) Írjon C++ függvénysablont (keres
), ami egy iterátorokkal megadott adatsorozatban megkeresi az első olyan elemet, amire az adott predikátum igaz értéket ad!
A függvény első két paramétere két iterátor, amivel a szokásos módon megadjuk a jobbról nyílt intervallumot. A függvény 3. paramétere pedig egy predikátum, ami egy egyparaméteres függvény vagy függvényobjektum. Amennyiben nincs a feltételnek megfelelő elem, akkor az adatsorozat végét jelző értékkel (iterátor) térjen vissza a függvény!
Ha jól oldja meg a feladatot, akkor az alábbi kódrészlet lefutása után az eredmény a 3-as indexű elemre (-16) fog mutatni.
bool negativ(int a) { return a < 0; }
int sorozat[] = { 1, 4, 9, -16, 25, 0, 72, 100, 0 };
int *eredmeny = keres(sorozat, sorozat+9, negativ);
d) Készítsen olyan függvényobjektum sablont, ami a keres sablonnal felhasználható az olyan elemek megkeresésére, amelyek nagyobbak a függvényobjektum konstruktorában megadott értéknél!
e) A részfeladatok eredményeit felhasználva írjon kódrészletet, ami a b) részfeladatban létrehozott tömbből kiírja a szabványos kimenetre az első 26-nál nagyobb értéket! (Feltételezheti, hogy van ilyen.)
#include <iostream>
#include <vector>
#include <deque>
template <typename T, int N = 0, typename TAROLO = std::vector<T>>
class Indexelheto : public TAROLO {
private:
T & at(size_t idx);
T const & at(size_t idx) const;
public:
Indexelheto(size_t meret = 0, T adat = T()) : TAROLO(meret, adat) {}
template <typename ITERATOR>
Indexelheto(ITERATOR begin, ITERATOR end) : TAROLO(begin, end) {}
T & operator[](int idx) { return TAROLO::operator[](idx-N); }
T const & operator[](int idx) const { return TAROLO::operator[](idx-N); }
};
/*
Megj. ez nem tökéletes megoldás igazából, mert sérti az OOP egyik alapelvét.
A "minden függvénye elérhető, kivéve az at()" igazából NEM öröklési viszony.
Ha a madarak tudnak repülni, akkor a strucc nem madár. Ha fogunk egy
std::vector<int> referenciát, és ráállítjuk egy Indexelheto<int>-re, akkor
simán meghívható azon keresztül az at()... Ahogy az indexet nem eltoló
operator[] is, mivel az sem virtuális az std::vectorban. Privát öröklést
kellene csinálni, de akkor meg using-olni kell egyesével az összes tagfüggvényt.
*/
template <typename ITER, typename PRED>
ITER keres(ITER begin, ITER end, PRED p) {
for (ITER it = begin; it != end; ++it) {
if (p(*it))
return it;
}
return end;
}
template <typename T>
class Nagyobb {
private:
T minel;
public:
Nagyobb(T minel = T()) : minel(minel) {}
bool operator() (T mi) const {
return mi > minel;
}
};
bool negativ(int a) {
return a < 0;
}
int main() {
int sorozat[] = { 1, 4, 9, -16, 25, 0, 72, 100, 0};
int *eredmeny = keres(sorozat, sorozat+9, negativ);
std::cout << *eredmeny << std::endl;
Indexelheto<int, 10, std::deque<int>> d(sorozat, sorozat+9);
std::cout << *keres(d.begin(), d.end(), Nagyobb<int>(26)) << std::endl;
return 0;
}