Fizikus C++ labor

1. hét: make és C ismétlés2. hét: pontosság és pontatlanság3. hét: azonos nevű függvények, referencia
4. hét: egyszerű osztályok5. hét: konstruktor és operator overloading6. hét: osztály dinamikus adattaggal
9. hét: >> és << használata I/O-ra, statikus tagok10. hét / 1: STL vector10. hét / 2: STL string, algorithm
11. hét: generikus algoritmusok és osztályok12. hét: öröklés13. hét: heterogén kollekció
14. hét: C++11 kitekintő15. hét: Nagyházi bemutatás

10. hét: generikus algoritmusok és osztályok

0. feladat

Készítsünk generikus maximumkereső függvényt! Készítsünk specializációt const char*-ra!

template<typename T> int maxkeres(T *t, int n) {
int maxindex = 0;
for (int i = 1; i<n; i++)
if (t[i]>t[maxindex])
maxindex = i;
return maxindex;
}
#include <cstring>
template<> int maxkeres(char **t, int n) {
int maxindex = 0;
for (int i = 1; i<n; i++)
if (strcmp(t[i], t[maxindex])>0)
maxindex = i;
return maxindex;
}
#include <iostream>
int main() {
int ti[5] = { 6, -5, 0, 9, 3 };
double td[6] = { 3.14, 2.71, -88.8, 12.1, 6, 0 };
char *ts[4] = { "Cecil","Aladar", "Denes", "Bela" };
using namespace std;
cout << ti[maxkeres<int>(ti, 5)] << endl;
cout << td[maxkeres(td, 6)] << endl;
cout << ts[maxkeres(ts, 4)] << endl;
return 0;
}

1. feladat

Készíts generikus rendezőfüggvényt! A függvény egy tömböt kap paraméterként, és a benne lévő elemeket növekvő sorrendbe rendezi. Mik az elvárások a tömbben tárolt elemekkel kapcsolatban? Készíts specializációt char* sztringekre mutató pointerek tömbjének rendezéséhez! (Ebben az esetben nem működik két elem összehasonlítására a < operátor, helyette pl. strcmp() használható.)

2. feladat

Alakítsd generikus osztállyá a 6. heti laboron készült vektor osztályt! Teszteld az osztály működését double és const char* típusú tárolt elemekkel való példányosítással!

Mintamegoldások

1. feladat
#include <iostream>
#include <string>

template<typename T>
void rendez(T * tomb, int n){
    for (int i = 0; i < n - 1; i++){
        int minindex = i;
        for (int j = i + 1; j < n; j++)
            if (tomb[j] < tomb[minindex])
                minindex = j;
        if (minindex != i){
            T temp = tomb[i];
            tomb[i] = tomb[minindex];
            tomb[minindex] = temp;
        }
    }
}

template<>
void rendez(const char ** tomb, int n){
    for (int i = 0; i < n - 1; i++){
        int minindex = i;
        for (int j = i + 1; j < n; j++)
            if (strcmp(tomb[j],tomb[minindex])<0)
                minindex = j;
        if (minindex != i){
            const char* temp = tomb[i];
            tomb[i] = tomb[minindex];
            tomb[minindex] = temp;
        }
    }
}

int main(){
    double t[5] = { 4, 3, 7, 5, 2 };
    rendez(t, 5);
    for (int i = 0; i < 5; i++)
        std::cout << t[i] << std::endl;
    const char *s[5] = { "ropi", "cukor", "alma", "zizi", "krumpliszirom" };
    rendez(s, 5);
    for (int i = 0; i < 5; i++)
        std::cout << s[i] << std::endl;
    return 0;
}

 

2. feladat
#include <iostream>
#include <stdexcept>

template <typename T>
class vektor{
private:
    T *t;
    int n;
public:
    vektor() :t(NULL), n(0){}
    ~vektor(){ delete[]t; }
    vektor(const vektor &masik);
    const vektor &operator=(const vektor &masik);
    T &operator[](int i){
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return t[i];
    }
    const T &operator[](int i)const{
        if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
        return t[i];
    }
    void push_back(const T&);
    int getSize()const{ return n; }
    void reset(){ delete[]t; t = NULL; n = 0; }
};

template <typename T>
vektor<T>::vektor(const vektor<T> &masik) :n(masik.n){
    t = new T[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
}

template <typename T>
const vektor<T> &vektor<T>::operator=(const vektor<T> & masik){
    if (this == &masik)
        return *this;
    delete[]t;
    n = masik.n;
    t = new T[n];
    for (int i = 0; i < n; i++)
        t[i] = masik.t[i];
    return *this;
}

template <typename T>
void vektor<T>::push_back(const T& uj){
    T *p = new T[n + 1];
    for (int i = 0; i < n; i++)
        p[i] = t[i];
    p[n] = uj;
    n++;
    delete[]t;
    t = p;
}

template <typename T>
vektor<T> first(const vektor<T> &v, int n){
    vektor<T> uj;
    for (int i = 0; i < n; i++)
        uj.push_back(v[i]);
    return uj;
}


template <typename T>
std::istream &operator>>(std::istream &is, vektor<T> &v){
    v.reset();
    T d;
    while ((is >> d) && d >= 0)
        v.push_back(d);
    return is;
}

template <>
std::istream &operator>>(std::istream &is, vektor<const char*> &v){
    throw std::bad_typeid("operator>> cannot be usedd with const char*");
    return is;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const vektor<T> &v){
    for (int i = 0; i < v.getSize(); i++){
        os << v[i] << ' ';
    }
    os << -1;
    return os;
}

template <typename T>
T vek_average(const vektor<T> &v){
    T sum = 0;
    for (int i = 0; i < v.getSize(); i++)
        sum += v[i];
    return v.getSize()>0 ? sum / v.getSize() : 0;
}

template <typename T>
vektor<T> above_average(const vektor<T> &v){
    vektor<T> ret;
    T aver = vek_average(v);
    for (int i = 0; i < v.getSize(); i++)
        if (v[i]>aver)
            ret.push_back(v[i]);
    return ret;
}

template <typename T>
void print_above_average(const vektor<T> &v){
    T aver = vek_average(v);
    for (int i = 0; i < v.getSize(); i++)
        if (v[i]>aver)
            std::cout << v[i] << ' ';
    std::cout << std::endl;
}

int main(){
    vektor<double> v;
    std::cin >> v;
    std::cout << v << std::endl;
    vektor<double> v2 = above_average(v);
    std::cout << v2 << std::endl; // Így persze odateszi a -1-et is a végére
    print_above_average(v); // Így meg nem.
    
    vektor<const char*> s;
    s.push_back("alma");
    s.push_back("zizi");
    s.push_back("chips");
    s.push_back("ropi");
    s.push_back("cukor");
    s[2] = "krumpliszirom";
    std::cout << s << std::endl;
    return 0;
}