9. Funktorok

Czirkos Zoltán · 2019.02.27.

Funktorok használata a rendezésben, IMSc: Titkosítás örökléssel és sablonnal a funktorhoz

1. Funktorok használata a rendezésben

#include <iostream>
#include <string>
#include <algorithm>

/* bináris predikátum: int a < int b */
bool kisebb(int a, int b) {
    return a < b;
}

/* nagyobb-e: bináris predikátum ez is, a > b, de
 * számolja, hogy hány összehasonlítást kértek tőle. */
template <typename T>
class NagyobbE {
  private:
    int hanyszor;

  public:
    NagyobbE() : hanyszor(0) {}
    bool operator() (T const & a, T const & b) {
        hanyszor++;
        return a > b;
    }
    int get_hanyszor() const {
        return hanyszor;
    }
};

/* rendezés adott predikátum szerint. visszaadja a
 * predikátumot, mert lehet, hogy funktor, és változott. */
template <typename T, typename PRED>
PRED rendez(T* tomb, size_t n, PRED valamilyenebb) {
    for (size_t i = 0; i < n-1; i++) {
        size_t min = i;
        for (size_t j = i+1; j < n; j++) {
            if (valamilyenebb(tomb[j], tomb[min]))
                min = j;
        }
        std::swap(tomb[i], tomb[min]);
    }
    return valamilyenebb;
}


int main() {
    int tomb[10] = { 7, 4, 9, 7, 3, 6, 7, 7, 2, 1 };

    NagyobbE<int> n;
    n = rendez(tomb, 10, n);
    std::cout << n.get_hanyszor() << " db összehasonlítás volt\n";

    for (size_t i = 0; i < 10; ++i)
        std::cout << tomb[i] << ", ";
    std::cout << std::endl;

    return 0;
}

2. Titkosítás örökléssel a funktorhoz

#include <iostream>
#include <string>

class Titkosito {
    public:
        virtual char operator() (char c) = 0;
        virtual ~Titkosito() {}
};

void titkosit(std::string & str, Titkosito & t) {
    for (size_t i = 0; i < str.length(); ++i)
        str[i] = t(str[i]);
}

/* Caesar titkosítás A->B kulccsal */
class ABCaesar : public Titkosito {
    public:
        char operator() (char c) {
            if (c == 'z')
                return 'a';
            else
                return c+1;
        }
};

/* Caesar titkosítás megadható kulccsal */
class Caesar : public Titkosito {
    private:
        char kulcs;

    public:
        Caesar(char kulcs) : kulcs(kulcs) {}
        char operator() (char c) {
            return (c-'a' + kulcs-'a')%('z'-'a'+1) + 'a';
        }
};

/* Vigenere-féle titkosítás */
class Vigenere : public Titkosito {
    private:
        int hanyadik = 0;
        std::string kulcs;
    public:
        Vigenere(std::string kulcs) : kulcs(kulcs) {}
        char operator() (char c) {
            char k = kulcs[hanyadik];
            hanyadik = (hanyadik+1) % kulcs.length();
            return (c-'a' + k-'a')%('z'-'a'+1) + 'a';
        }
        void reset() {
            hanyadik = 0;
        }
};

int main() {
    std::string szoveg = "alma";

    //~ ABCaesar abc;
    //~ Caesar   c('d');
    Vigenere t("szupertitkoskulcs");
    titkosit(szoveg, t);

    std::cout << szoveg << std::endl;
}

3. Titkosítás sablonnal a funktorhoz

#include <iostream>
#include <string>

template <typename FUNC>
void titkosit_template(std::string & str, FUNC t) {
    for (size_t i = 0; i < str.length(); ++i)
        str[i] = t(str[i]);
}

/* Caesar titkosítás A->B kulccsal */
class ABCaesar {
    public:
        char operator() (char c) {
            if (c == 'z')
                return 'a';
            else
                return c+1;
        }
};

/* Caesar titkosítás megadható kulccsal */
class Caesar {
    private:
        char kulcs;

    public:
        Caesar(char kulcs) : kulcs(kulcs) {}
        char operator() (char c) {
            return (c-'a' + kulcs-'a')%('z'-'a'+1) + 'a';
        }
};

/* Vigenere-féle titkosítás */
class Vigenere {
    private:
        int hanyadik = 0;
        std::string kulcs;
    public:
        Vigenere(std::string const & kulcs) : kulcs(kulcs) {}
        char operator() (char c) {
            char k = kulcs[hanyadik];
            hanyadik = (hanyadik+1) % kulcs.length();
            return (c-'a' + k-'a')%('z'-'a'+1) + 'a';
        }
        void reset() {
            hanyadik = 0;
        }
};


int main() {
    std::string szoveg = "alma";

    ABCaesar abc;
    //~ Caesar   c('d');
    //~ Vigenere t("pop");
    titkosit_template(szoveg, abc);

    std::cout << szoveg << std::endl;
}