Commit a4346e13 by Szeberényi Imre

v0

parents
/**
* \file: compat.hpp
*
* Néhány, C++11-től elavulttá (deprecated) minősített nyelvi elem
* illetve működés kompatibilis megvalósítása
*
*
*/
#ifndef COMPAT_HPP
#define COMPAT_HPP
#if __cplusplus < 201103L
// C++2003 vagy régebbi ///////////////////////////
/// THROW_NOTHING makróval verziófüggetlenül lehet megadni, ha egy függvény nem dobhat kivételt
#define THROW_NOTHING throw ()
/// THROW_ANY makróval verziófüggetlenül lehet megadni, ha egy függvény dobhat kivételt
#define THROW_SOMETHING(...) throw (__VA_ARGS__)
#else
// C++11 vagy újabb ////////////////////////////////
/// THROW_NOTHING makróval verziófüggetlenül lehet megadni, ha egy függvény nem dobhat kivételt
#define THROW_NOTHING noexcept
/// THROW_ANY makróval verziófüggetlenül lehet megadni, ha egy függvény dobhat kivételt
#define THROW_SOMETHING(...) noexcept(false)
namespace std {
/// Ronda az std-be piszkolni, de a makró trükközés miatt kell.
/// segédsablon a bind1st-höz.
template <typename F, typename T>
std::function<bool (T) > Bind1st(F f, T arg) {
return std::bind(f, arg, std::placeholders::_1);
}
/// segédsablon a bind2nd-hoz
template <typename F, typename T>
std::function<bool (T) > Bind2nd(F f, T arg) {
return std::bind(f, std::placeholders::_1, arg);
}
}
/// bind1st, és bind2nd lecserélése a nagybetűs sablonra
#define bind1st(a, b) Bind1st(a,b)
#define bind2nd(a, b) Bind2nd(a,b)
#endif
#endif // COMPAT_HPP
/**
* \file gen_array_iter3.hpp
*
* Generikus tömb iterátorral v3.1 (új tagfv.: setsize)
* Előadáson bemutatott kód módosított változata.
* Interfész jobban hasonlít az std::vector-ra.
* Van konstans iterarora is.
*/
#ifndef GEN_ARRAY_ITER3
#define GEN_ARRAY_ITER3
#include <stdexcept>
/**
* Fix méretű generikus tömb.
* @param T - tárolt adattípus
* @param maxsiz - maximális méret
*/
template<class T, size_t maxsiz = 6>
class Array {
size_t siz; // adatok tényleges mennyisége
T t[maxsiz]; // elemek (adatok) tömbje
protected:
/// az erase megvalósításához módosítani kell a méretet
/// ezért bevezettük ezt a függvényt.
/// közvetlen elérés helyett kézben tarthatóbb így.
void setsize(size_t siz) {
if (siz > maxsiz) throw std::out_of_range("Array.setsize(): hibas meret");
this->siz = siz;
}
public:
/// minden implicit tagfüggvény jó, nem kell átdefiniálni
class iterator; // elődeklaráció
class const_iterator; // elődeklaráció
/// default és konstans értékkel feltöltő konstruktor
/// @param n - méret
/// @param value - érték, amivel feltölt
explicit Array(size_t n = 0, const T& value = T()) : siz(0) {
while (siz < n && siz < maxsiz)
t[siz++] = value;
}
/// konstruktor sorozatból
/// @param first - sorozat elejére mutat
/// @param last - utolsó elem után
template <class InputIterator>
Array(InputIterator first, InputIterator last) : siz(0) {
while (first != last && siz < maxsiz) // átmásolunk, amíg lehet
t[siz++] = *first++;
}
/// létrehoz egy iterátort és az elejére állítja
/// @return - iterátor az adatsorozat elejére
iterator begin() {
return iterator(*this); // ld. iterátor konstruktor
}
/// létrehoz egy iterátort és az utolsó elem után állítja
/// @return - iterátor az adatsorozat végére
iterator end() {
return iterator(*this, siz);// ld. iterátor konstruktor
}
/// létrehoz egy konstans objektumra alkalmazható iterátort és az elejére állítja
/// @return - iterátor az adatsorozat elejére
const_iterator begin() const {
return const_iterator(*this);// ld. iterátor konstruktor
}
/// létrehoz egy iterátort és az utolsó elem után állítja
/// @return - iterátor az adatsorozat végére
const_iterator end() const {
return const_iterator(*this, siz);// ld. iterátor konstruktor
}
/// Elemek tényleges száma
/// @return - ténylegesen tárolt elemek száma
size_t size() const { return siz; }
/// Tömb allokált (maximális) kapacitása
/// @return - tömb allokált (maximális) kapacitása
size_t capacity() const { return maxsiz; }
/// Tömb allokált maximális kapacitása
/// Mivel a tömb fix méretű így a max_size és a capacity megegyezik.
/// @return - tömb maximális kapacitása
size_t max_size() const { return maxsiz; }
/// at
/// @param i - index
/// @return - i. elem referenciája, vagy out_of_range hiba
T& at(size_t i) {
if (i >= maxsiz) throw std::out_of_range("Array.at(): hibas index");
if (i >= siz) siz = i+1; // növeljük a tényleges méretet
return t[i];
}
/// at konstans változata.
/// konstans esetén nem változhat a méret
/// @param i - index
/// @return i. elem referenciája, vagy out_of_range hiba
const T& at(size_t i) const {
if (i >= siz) throw std::out_of_range("Array.at(): hibas index");
return t[i];
}
/// iterator osztály
/// input/output (STL::ForwardIterator) iterátorként használható
// class iterator {
class iterator : public std::iterator<std::forward_iterator_tag, T>{
Array *p; // tároljuk, hogy melyik az objektumhoz tartozik az iterátor
size_t idx; // tároljuk az aktuális index értéket
public:
/// default konstruktor
iterator() :p(0), idx(0) {}
/// konstruktor, egy konkrét objektum ix-edik elemére mutat
/// @param a - a konkrét objektum
/// @param ix - ide állítja az indexet
iterator(Array& a, size_t ix = 0)
: p(&a), // az objektumra mutat
idx(ix) {} // erre az elemre áll
/// pre-inkremens
/// csak hatékonyság miatt ref. visszatérésű,
/// értelmetlen lenne balértékként használni
iterator& operator++() {
if (idx != p->siz) ++idx; // nem engedjük túllépni
return *this;
}
/// post-inkremens
iterator operator++(int) {
iterator tmp = *this; // növelés előtti értékkel kell visszatérni
if (idx != p->siz) ++idx; // nem engedjük túllépni
return tmp;
}
/// egyenlőtlenség vizsgálat
/// @param i - jobboldali operandus
bool operator!=(const iterator &i) const {
return(idx != i.idx);
}
/// egyenlőség vizsgálat
/// @param i - jobboldali operandus
bool operator==(const iterator &i) const {
return !operator!=(i);
}
/// indirekció
T& operator*() const {
if (idx != p->siz) return p->t[idx];
else throw std::runtime_error("Hibas indirekcio");
}
/// Szelekció pointerrel (nyíl). Címet kell, hogy adjon.
T* operator->() const {
return &operator*();
}
}; // iterator osztály vége
/// const_iterator osztály.
/// Visszavezetjük az iterator osztályra.
/// A megvalóstás hibája, hogy a kompatibilitas miatt a const_iterator betehető egy
/// iteratorba, így a konstans objektum adata elérhetővé válik balértékként is.
/// Privát öröklés jobb megoldás lenne, úgy azonban minden tagfüggvényt az ősből delegálni kell.
class const_iterator : public iterator {
public:
/// default konstruktor
const_iterator() :iterator() {}
/// konstruktor, egy konkrét objektum ix-edik elemére mutat
/// @param a - a konkrét objektum
/// @param ix - ide állítja az indexet
const_iterator(const Array& a, size_t ix = 0)
: iterator(const_cast<Array&>(a), ix) {} /// Kis trükközés a kasztolással: Levesszük a
/// konstans attribútumot, de nem fogjuk írni.
/// indirekció
const T& operator*() const { /// Ezen keresztül biztosan nem fogjuk írni, de sajnos kompatibilitás
return iterator::operator*(); /// miatt egy const_iterator -> iterator konverzió nem kerül semmibe...
}
/// Szelekció pointerrel (nyil). Címet kell, hogy adjon.
const T* operator->() const {
return &operator*();
}
};
/// Virtuális destruktor.
/// Most nem használjuk, de egy generikus osztály későbbi
/// felhasználási módja kevésbé látszik.
virtual ~Array() {}
}; // generikus tömb vége
#endif
/**
* \file: mystack.hpp
*
*/
#error "itt keszitse el a stack adaptert!"
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="vektor" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/genarray3" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/genarray3" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-pedantic" />
<Add option="-std=c++11" />
<Add option="-Wall" />
</Compiler>
<Unit filename="compat.hpp" />
<Unit filename="gen_array_iter3.hpp" />
<Unit filename="mystack.hpp" />
<Unit filename="vektor.hpp" />
<Unit filename="vektor_test.cpp" />
<Extensions>
<code_completion />
<debugger />
<envvars />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* \file vektor.hpp
*
* Előadáson bemutatott generikus tömbből Vektort készítünk.
*
*/
#ifndef GEN_VEKTOR
#define GEN_VEKTOR
#include "gen_array_iter3.hpp"
template<typename T, size_t maxsiz = 6>
class Vektor : public Array<T, maxsiz> {
public:
/// minden tagfüggvény jó, nem kell átdefiniálni
/// csak a konstruktorokat kell megfelelően paraméterezve továbbhívni
/// default és konstans értékkel feltöltő konstruktor
/// @param n - méret
/// @param value - érték, amivel feltölt
explicit Vektor(size_t n = 0, const T& value = T())
: Array<T, maxsiz>(n, value) {} // alaposztály konstruktora
/// ----------------------------------------------------
/// A további tagfüggvényeket Önnek kell elkészítenie
///-----------------------------------------------------
/// konstruktor sorozatból
/// @param first - sorozat elejére mutat
/// @param last - utolsó elem után
template <class InputIterator>
Vektor(InputIterator first, InputIterator last);
/// push_back
/// vektor végéhez adatot ad
/// @param val - adat
void push_back(const T& val);
/// back
/// vektor utolsó adatának elérése
/// @return referencia az utolsó adat
T& back();
/// pop_back
/// vektor utolsó adatának eldobása
void pop_back();
/// empty
/// @return true, ha nincs adat
bool empty();
/// A továbbiakban egyszerűbben hivatkozhassunk az iterator-ra, mint típusra
typedef typename Array<T, maxsiz>::iterator iterator;
/// törli az adott pozíción levő elemet
/// @param pos - a törlendő elemre mutató iterátor
/// @return az első nem törölt elemre mutató iterátor, ha végéig törölt, akkor end()
iterator erase(iterator pos);
/// törli az adott intervallumba eső elemeket
/// @param first - a törlendő intervalum eleje
/// @param last - a törlendő intervallum vége
/// @return az első nem törölt elemre mutató iterátor, ha végéig törölt, akkor end()
iterator erase(iterator first, iterator last);
}; // Vektor sablon vége
#endif
/**
* \file: vektor_test.cpp
* Egyszerű teszt iterátoros generikus tömb továbbfejlesztéséhez.
* STL algoritmusainak próbálgatásához.
*/
#define ELKESZULT 0
#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include "compat.hpp"
#include "vektor.hpp"
#if ELKESZULT >= 12
#include "mystack.hpp"
#endif
using std::cout;
using std::endl;
/// -----------------------------------------
/// 9. laboron elkészített sablonok: (forEach, ostreamFunktor)
/// forEach sablon
template <typename Iter, class Func>
Func forEach(Iter first, Iter last, Func func) {
while (first != last)
func(*first++);
return func;
}
/// Funktor a kiírásokhoz
template <class T>
class ostreamFunctor {
std::ostream& os;
const char* delim;
public:
ostreamFunctor(std::ostream& os, const char* delim = "") : os(os), delim(delim) {}
void operator()(const T& d) const { os << d << delim; }
};
///------------------------------------------
/// Funktor hogy negatív-e
/// cout_if-ben használjuk
template <typename T>
struct negativ {
bool operator()(const T& val) { return val < 0; }
};
int main() {
/// Egyszerű C tömbök, amiből majd az adatokat vesszük
int it1[] = {-5, -4, -3, -2, -1, 0, 1, -82, 3, 4 }; // 10 adat van
double dt1[] = { .0, 234.1, .2, .3, -444.4, -12.4, 128.799 }; // 7 adat van
try {
#if ELESZULT >= 0
/// létrehozunk egy funktort az kiíráshoz
ostreamFunctor<int> intout(cout, ", ");
/// segítségével kiírjuk az it1 adatait
cout << "it1: ";
forEach(it1, it1+10, intout);
cout << endl;
#endif // ELEKSZULT >= 0
#if ELKESZULT >= 1
/// 1. feladat:
/// Kiírás std::for_each segítségével.
/// A funktort a for_each paraméterlistáján példányosítsa!
/// Próbálja ki!
cout << "it1 (for_each): ";
#error "itt kell kiirnia"
cout << endl;
#endif // ELKESZULT >= 1
#if ELKESZULT >= 2
Vektor<double, 50> otos(8, 5.1);
cout << "otos: ";
#error "itt kell kiirnia"
cout << endl;
#endif // ELKESZULT >= 2
#if ELKESZULT >= 3
Vektor<double, 100> darr(dt1, dt1+7);
cout << "darr: ";
std::for_each(darr.begin(), darr.end(), ostreamFunctor<double>(cout, ", "));
cout << endl;
#endif // ELKESZULT >= 3
#if ELKESZULT >= 4
cout << "push_back proba" << endl;
darr.push_back(100);
cout << "darr: ";
std::for_each(darr.begin(), darr.end(), ostreamFunctor<double>(cout, ", "));
cout << endl;
#endif // ELKESZULT >= 4
#if ELKESZULT >= 5
cout << "back: " << darr.back() << endl;
darr.pop_back();
cout << "darr: ";
std::for_each(darr.begin(), darr.end(), ostreamFunctor<double>(cout, ", "));
cout << endl;
cout << "empty: " << std::boolalpha << darr.empty() << endl;
#endif // ELKESZULT >= 5
#if ELKESZULT >= 6
cout << "it1-ben negativ: ";
#error "ide kell betenni a count_if fuggvenyhivast"
cout << ...
cout << endl;
#endif // ELKESZULT >= 6
#if ELKESZULT >= 7
cout << "darr-ban negativ: ";
#error "ide kell betenni a count_if fuggvenyhivast"
cout << ...
cout << endl;
#endif // ELKESZULT >= 7
#if ELKESZULT >= 8
std::less<int> lt;
cout << "less teszt: " << std::boolalpha << lt(8, 100) << endl;
cout << "darr-ban kisebb, mint 100: ";
cout << std::count_if(darr.begin(), darr.end(), std::bind2nd(std::less<double>(), 100));
cout << endl;
#endif // ELKESZULT >= 8
#if ELKESZULT >= 9
cout << "copy-val darr: ";
std::copy(darr.begin(), darr.end(), std::ostream_iterator<double>(cout, ", "));
cout << endl;
#endif // ELKESZULT >= 9
#if ELKESZULT == 10
std::remove_if(darr.begin(), darr.end(), std::bind2nd(std::less<double>(), 100)); // 100-nál kisebb elemek törlése
cout << "remove_if utan: ";
std::for_each(darr.begin(), darr.end(), ostreamFunctor<double>(cout, ", "));
cout << endl;
#endif // ELKESZULT == 10
#if ELKESZULT >= 11
Vektor<double, 100>::iterator dblit;
dblit = std::remove_if(darr.begin(), darr.end(), std::bind2nd(std::less<double>(), 100)); // 100-nál kisebb elemek törlése
darr.erase(dblit, darr.end());
cout << "remove es erase utan: ";
std::for_each(darr.begin(), darr.end(), ostreamFunctor<double>(cout, ", "));
cout << endl;
#endif // ELKESZULT >= 11
#if ELKESZULT >= 12
MyStack<char, Vektor<char, 15> > cstk;
cstk.push('*');
cstk.push('*');
cstk.push('*');
cstk.push('E');
cstk.push('G');
cstk.push('E');
cstk.push('V');
cstk.push('*');
cstk.push('*');
cstk.push('*');
while (!cstk.empty()) {
cout << cstk.top();
cstk.pop();
}
cout << endl;
cstk.pop(); // hibát kell dobnia
#endif // ELKESZULT >= 12
} catch (std::exception& e) { // az out_of_range, és a runtime_error is
// az excetion-ból származik. Így kompatibilisek
// az alaposztállyal
cout << e.what() << endl;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment