Objektum elvű alkalmazások fejlesztése Programozási tételek újrafelhasználása 1. Készítette: Gregorics Tibor
Hozzunk létre a programozási tételeket általánosan leíró kódkönyvtárat (osztály-sablon könyvtárat), amely felhasználásával a visszavezetéssel tervezett programjainkat minimális erőfeszítéssel implementálhatjuk.
Egy feladat megoldása egy tevékenység objektum lesz. 1. Az objektum osztályát származtatással hozzuk létre, 2. miután annak ősosztályát a kódkönyvtárból példányosítottuk, 3. az objektumhoz pedig egy felsoroló objektumot rendelünk.
bool l = false; for (t.first(); !l && !t.end(); t.next()){ l = cond(elem = t.current()); }
bool l = false; for (t.first(); !t.end(); t.next()){ if(!cond(t.current())) continue; Value val = func(t.current()); if(l) if( opt < val ){ opt = val; optitem = t.current(); int db = 0; for (t.first(); !t.end(); t.next()){ }else{ if( cond(t.current()) ) ++db; l=true; } opt = val; optitem = t.current(); } }
init(); for(t.first(); !t.end() && whileCond(t.current()); t.next()){ body(t.current()); }
felsorolt elemek típusa template
void Procedure- ::run() { if(_enor==NULL) throw MISSING_ENUMERATOR;
felsoroló objektumra mutató pointer
default: _enor->first() init(); for( first(); loopCond(); _enor->next()) { body(_enor->current()); !_enor->end() && whileCond(_enor->current()) } }
default: true
template class Procedure { protected: Enumerator- *_enor;
felsorolt elemek típusa felsoroló objektumra mutató pointer
Procedure():_enor(NULL){} felüldefiniálható metódusok virtual void init()= 0; virtual void body(const Item& current) = 0; virtual void first() {_enor->first();} virtual bool whileCond(const Item& current) const { return true;} virtual bool loopCond() const { return !_enor->end()&& whileCond(_enor->current());}
ősciklus
public: konkrét felsoroló enum Exceptions { MISSING_ENUMERATOR }; objektum hozzáadása void run(); void addEnumerator(Enumerator- * en) { _enor = en;} virtual ~Procedure(){} };
procedure.hpp
template class Enumerator { public: virtual void first() virtual void next() virtual bool end() const virtual Item current() const virtual ~Enumerator(){} };
= = = =
0; 0; 0; 0;
enumerator.hpp
Item
Procedure + run() + addEnumerator() # init() # first() # body(Item) # loopCond(Item) # whileCond(Item)
: : : : : : :
+first() +next() +current() +end()
void void
void void
void
: void : void : Item : bool
bool bool
ArrayEnumerator - vect - ind + first() + next() + current() + end()
Enumerator
-*enor
Item
Item
: array of Item : int : void : void : Item : bool
SeqInFileEnumerator -f - df + first() + next() + current() + end()
Item
: file of Item : Item : void : void : Item : bool
template class ArrayEnumerator : public Enumerator- { protected: std::vector
- *_vect; unsigned int _ind; public: ArrayEnumerator(std::vector
- *v):_vect(v){} void void bool Item
first() next() end() const current()const
{ { { {
_ind = 0;} ++_ind;} return _ind>=_vect->size();} return (*_vect)[_ind];}
};
arrayenumerator.hpp
template class SeqInFileEnumerator : public Enumerator- { protected: std::ifstream _f; Item _df; public: enum Exceptions { OPEN_ERROR }; SeqInFileEnumerator(const std::string& str) #include _f.open(str.c_str()); if(_f.fail()) throw OPEN_ERROR; if(typeid(Item)==typeid(char)) _f.unsetf(std::ios::skipws); } ~SeqInFileEnumerator(){ _f.close(); } Az Item-re legyen értelmes az operator>> void void bool Item };
first() { next() { end() const { current() const {
next();} _f >> _df;} return _f.fail();} return _df; }
seqinfileenumerator.hpp
Item
Procedure +run() +addEnumerator() # init() # first() # body(Item) # loopCond(Item) # whileCond(Item)
Item, … MaxSearch
Enumerator
-*enor : : : : : : :
void void
void void
void
+first() +next() +current() +end()
Item
: void : void : Item : bool
bool bool
Item, … LinSearch
Item, … Summation
Item Counting
Item Selection
template > class MaxSearch : public Procedure- az Item típusú elemek { Value típusú értékeit protected: hasonlítjuk össze bool _l; Item _optelem; Value _opt; ősciklusban használt Compare _better; metódusok felüldefiniálása
újabb felüldefiniálható void init(){ _l = false;} metódusok void body(const Item& current); virtual Value func(const Item& e) const = 0; virtual bool cond(const Item& e) const { return true;} public: eredmény lekérdezése bool found() const { return _l;} Value opt() const { return _opt;} Item optElem() const { return _optelem;} };
maxsearch.hpp
template void MaxSearch- ::body(const Item& current) { Value val = func(current); if ( !cond(current) ) return; if (_l){ a Compare típusú _better if (_better(val,_opt)){ összehasonlító objektum _opt = val; mutatja meg, hogy _optelem = current; val jobb-e, mint az _opt } } else { _l = true; _opt = val; _optelem = current; } }
maxsearch.hpp
template class Greater{ public: bool operator()(const Value& l, const Value& r) { return l > r; Ha Compare a Greater, akkor } _better(2,5) azonos a 2>5 értékével. }; Ha Compare a Less, akkor _better(2,5) azonos a 2<5 értékével.
template class Less{ public: bool operator()(const Value& l, const Value& r) { return l < r; } };
compare.hpp
Item
Procedure +run() +addEnumerator() # init() # body(Item) # first() # loopCond(Item) # whileCond(Item)
: : : : : : :
void void
void void
void bool bool
Item, Value, Compare MaxSearch # init() # body(Item) # func(Item) # cond(Item) + found() + opt() + optElem()
: void : void : Value : bool : bool : Value : Item
Enumerator
-*enor +first() +next() +current() +end()
Item
: void : void : Item : bool
Greater
Value
+operator(Item, Item) : bool
Less +operator(Item, Item) : bool
Value
Adott egy egész számokat tartalmazó szöveges fájl, amelyben keressük a legnagyobb páratlan számot! „Melyik a legnagyobb páratlan szám?” A feladat visszavezethető a feltételes maximum keresésre 1.
Vizsgált elemek típusa (Item): egész számok
2.
Az Item→Value függvény (func): identitás
3.
Összehasonlítandó értékek típusa (Value): egész számok
4.
Összehasonlítás (Compare): „nagyobb” reláció (Greater)
5.
Feltétel (cond): a szám páratlan
6.
Felsoroló: szöveges állomány egész számainak felsorolója
Procedure +run() +addEnumerator() …
Item : void : void
Item, Value, Compare MaxSearch # init() # body(Item) # func(Item) # cond(Item) + found() + opt() + optElem()
: void : void : Value : bool : bool : Value : Item
MyMaxSearch : int : bool
SeqInFileEnumerator
int
int
int, int, Greater # func(int e) # cond(int e)
Enumerator
-enor*
Item
-enor* -better
Greater
+operator(Item, Item) : bool
return e%2!=0
return e
Item
Value
12 -5 23 input.txt 44 130 56 3 -120
class MyMaxSearch : public MaxSearch{ protected: int func(const int& e) const { return e;} bool cond(const int& e) const { return e%2!=0;} }; int main(){
tevékenység objektum felsoroló objektum
MyMaxSearch pr; SeqInFileEnumerator file_enum("input.txt"); pr.addEnumerator(&file_enum);
pr.run();
működés
Hiányzik a kivételkezelés!
if (pr.found()) cout << "A legnagyobb páratlan szám:" << pr.optElem(); else cout << "Nincs páratlan szám"; return 0; }
main.cpp
new addEnumerator() run() found() optElem()
new
: MyMaxSearch
first() next() end() current() : SeqInFileEnumerator
: MyMaxSearch
: SeqInFileEnumerator
new new addEnumerator() run()
found() optElem()
first() next() end() current()
Egy forgalom számlálás során egy hónapon keresztül számolták, hogy az egyes órákban hány utas lép be egy adott metróállomás területére. (A méréseket hétfőn kezdték, de lehet, hogy nem minden nap és ne minden órában végeztek megfigyelést.) Az időt egy négyjegyű számmal kódolták, amelynek első két jegye a nap hónapbeli sorszámát, utolsó két jegye az órát mutatja. Egy szöveges fájlban időkód-létszám párok formájában rögzítették a méréseket. A hétvégi napok közül mikor (nap, óra) léptek be legkevesebben az állomás területére?
„Mikor léptek be legkevesebben a hétvégi időpontok közül?” A feladat visszavezethető a feltételes minimum keresésre 1.
Vizsgált elemek (Item): mérések, azaz időkód-létszám (egész szám) párok
2.
Az Item→Value függvény (func): egy mérésből kiemeli a létszámot
3.
Összehasonlítandó értékek (Value): létszám (egész számok)
4.
Összehasonlítás (Compare): „kisebb” (Less) reláció
5.
Feltétel (cond): a mérés hétvégére esik
6.
Felsoroló: szöveges állomány méréseit sorolja fel
0108 0112 0116 0207 …
struct Pair{ int time; int number;
23 44 130 120
input.txt
int day() const { return time/100; } int hour() const { return time%100; } friend ifstream& operator>>(ifstream&, Pair&); };
Szekvenciális inputfájl Pair típusú elemeinek felsorolásához kell
ifstream& operator>>(ifstream& f, Pair& df) { f >> df.time >> df.number; return f; }
main.cpp
class MyMinSearch: public MaxSearch<Pair, int, Less > { protected: int func(const Pair &e) const { return e.number; } bool cond(const Pair &e) const { return (e.day()%7==6 || e.day()%7==0;} };
main.cpp
int main() { MyMinSearch pr; SeqInFileEnumerator<Pair> file_enum("input.txt"); pr.addEnumerator(&file_enum); pr.run(); if (pr.found()){ Pair p = pr.optElem(); cout << "A " << p.day() << ". napon a " << p.hour() << "-kor lépett a legkevesebb, " << pr.opt() << " fő az állomásra" << endl; }else cout << "Nincs hétvégi adat" << endl; return 0; }
main.cpp