🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Esercizi Classi Template C++

Codegrind Team•Jul 12 2024

Ecco degli esercizi semplici con soluzione per praticare le basi delle classi template in C++.

Esercizio 1

Creare una classe template semplice per memorizzare un valore e stamparlo.
#include <iostream>

template <typename T>
class Contenitore {
private:
    T valore;
public:
    Contenitore(T v) : valore(v) {}
    void stampa() {
        std::cout << "Valore: " << valore << std::endl;
    }
};

int main() {
    Contenitore<int> c1(42);
    Contenitore<std::string> c2("Ciao");
    c1.stampa();
    c2.stampa();
    return 0;
}

Esercizio 2

Creare una classe template per una coppia di valori e stamparli.
#include <iostream>

template <typename T1, typename T2>
class Coppia {
private:
    T1 primo;
    T2 secondo;
public:
    Coppia(T1 p, T2 s) : primo(p), secondo(s) {}
    void stampa() {
        std::cout << "Primo: " << primo << ", Secondo: " << secondo << std::endl;
    }
};

int main() {
    Coppia<int, double> c1(1, 2.5);
    Coppia<std::string, int> c2("Ciao", 100);
    c1.stampa();
    c2.stampa();
    return 0;
}

Esercizio 3

Creare una classe template per una pila (stack) con operazioni push e pop.
#include <iostream>
#include <vector>

template <typename T>
class Pila {
private:
    std::vector<T> dati;
public:
    void push(T val) {
        dati.push_back(val);
    }
    T pop() {
        if (dati.empty()) {
            throw std::out_of_range("Pila vuota");
        }
        T val = dati.back();
        dati.pop_back();
        return val;
    }
    bool vuota() const {
        return dati.empty();
    }
};

int main() {
    Pila<int> pila;
    pila.push(1);
    pila.push(2);
    pila.push(3);
    std::cout << "Pop: " << pila.pop() << std::endl;
    std::cout << "Pop: " << pila.pop() << std::endl;
    std::cout << "Pop: " << pila.pop() << std::endl;
    return 0;
}

Esercizio 4

Creare una classe template per una coda (queue) con operazioni enqueue e dequeue.
#include <iostream>
#include <queue>

template <typename T>
class Coda {
private:
    std::queue<T> dati;
public:
    void enqueue(T val) {
        dati.push(val);
    }
    T dequeue() {
        if (dati.empty()) {
            throw std::out_of_range("Coda vuota");
        }
        T val = dati.front();
        dati.pop();
        return val;
    }
    bool vuota() const {
        return dati.empty();
    }
};

int main() {
    Coda<int> coda;
    coda.enqueue(1);
    coda.enqueue(2);
    coda.enqueue(3);
    std::cout << "Dequeue: " << coda.dequeue() << std::endl;
    std::cout << "Dequeue: " << coda.dequeue() << std::endl;
    std::cout << "Dequeue: " << coda.dequeue() << std::endl;
    return 0;
}

Esercizio 5

Creare una classe template per un array dinamico con operazioni di aggiunta e accesso.
#include <iostream>

template <typename T>
class ArrayDinamico {
private:
    T* dati;
    std::size_t dimensione;
public:
    ArrayDinamico(std::size_t dim) : dimensione(dim) {
        dati = new T[dim];
    }
    ~ArrayDinamico() {
        delete[] dati;
    }
    void set(std::size_t index, T val) {
        if (index >= dimensione) {
            throw std::out_of_range("Indice fuori limite");
        }
        dati[index] = val;
    }
    T get(std::size_t index) const {
        if (index >= dimensione) {
            throw std::out_of_range("Indice fuori limite");
        }
        return dati[index];
    }
    std::size_t size() const {
        return dimensione;
    }
};

int main() {
    ArrayDinamico<int> arr(5);
    for (std::size_t i = 0; i < arr.size(); ++i) {
        arr.set(i, i + 1);
    }
    for (std::size_t i = 0; i < arr.size(); ++i) {
        std::cout << "arr[" << i << "] = " << arr.get(i) << std::endl;
    }
    return 0;
}

Esercizio 6

Creare una classe template per un dizionario (mappa) semplice con operazioni di aggiunta e ricerca.
#include <iostream>
#include <map>

template <typename K, typename V>
class Dizionario {
private:
    std::map<K, V> dati;
public:
    void aggiungi(const K& chiave, const V& valore) {
        dati[chiave] = valore;
    }
    V cerca(const K& chiave) const {
        auto it = dati.find(chiave);
        if (it != dati.end()) {
            return it->second;
        } else {
            throw std::out_of_range("Chiave non trovata");
        }
    }
    bool esiste(const K& chiave) const {
        return dati.find(chiave) != dati.end();
    }
};

int main() {
    Dizionario<std::string, int> diz;
    diz.aggiungi("uno", 1);
    diz.aggiungi("due", 2);
    diz.aggiungi("tre", 3);
    std::cout << "Valore associato a 'due': " << diz.cerca("due") << std::endl;
    std::cout << "Esiste chiave 'quattro'? " << (diz.esiste("quattro") ? "Sì" : "No") << std::endl;
    return 0;
}

Esercizio 7

Creare una classe template per un punto 2D con operazioni di set e get delle coordinate.
#include <iostream>

template <typename T>
class Punto2D {
private:
    T x, y;
public:
    Punto2D(T x, T y) : x(x), y(y) {}
    void setX(T x) {
        this->x = x;
    }
    void setY(T y) {
        this->y = y;
    }
    T getX() const {
        return x;
    }
    T getY() const {
        return y;
    }
};

int main() {
    Punto2D<int> p1(1, 2);
    Punto2D<double> p2(3.5, 4.5);
    std::cout << "Punto1: (" << p1.getX() << ", " << p1.getY() << ")" << std::endl;
    std::cout << "Punto2: (" << p2.getX() << ", " << p2.getY() << ")" << std::endl;
    return 0;
}

Esercizio 8

Creare una classe template per una frazione con operazioni di somma e sottrazione.
#include <iostream>

template <typename T>
class Frazione {
private:
    T numeratore, denominatore;


public:
    Frazione(T num, T denom) : numeratore(num), denominatore(denom) {}

    Frazione somma(const Frazione& altra) const {
        return Frazione(numeratore * altra.denominatore + altra.numeratore * denominatore,
                        denominatore * altra.denominatore);
    }

    Frazione sottrai(const Frazione& altra) const {
        return Frazione(numeratore * altra.denominatore - altra.numeratore * denominatore,
                        denominatore * altra.denominatore);
    }

    void stampa() const {
        std::cout << numeratore << "/" << denominatore << std::endl;
    }
};

int main() {
    Frazione<int> f1(1, 2);
    Frazione<int> f2(1, 3);
    Frazione<int> somma = f1.somma(f2);
    Frazione<int> differenza = f1.sottrai(f2);

    std::cout << "Somma: ";
    somma.stampa();
    std::cout << "Differenza: ";
    differenza.stampa();
    return 0;
}

Esercizio 9

Creare una classe template per un intervallo (range) con operazioni di inclusione ed esclusione.
#include <iostream>

template <typename T>
class Intervallo {
private:
    T inizio, fine;
public:
    Intervallo(T i, T f) : inizio(i), fine(f) {}
    bool include(const T& val) const {
        return val >= inizio && val <= fine;
    }
    bool escludi(const T& val) const {
        return val < inizio || val > fine;
    }
};

int main() {
    Intervallo<int> intervallo(10, 20);
    int val1 = 15, val2 = 25;
    std::cout << "Il valore " << val1 << " è incluso? " << (intervallo.include(val1) ? "Sì" : "No") << std::endl;
    std::cout << "Il valore " << val2 << " è escluso? " << (intervallo.escludi(val2) ? "Sì" : "No") << std::endl;
    return 0;
}

Esercizio 10

Creare una classe template per un albero binario di ricerca con operazioni di inserimento e ricerca.
#include <iostream>

template <typename T>
class Nodo {
public:
    T dato;
    Nodo* sinistro;
    Nodo* destro;

    Nodo(T val) : dato(val), sinistro(nullptr), destro(nullptr) {}
};

template <typename T>
class AlberoBinario {
private:
    Nodo<T>* radice;

    void inserisci(Nodo<T>*& nodo, T val) {
        if (!nodo) {
            nodo = new Nodo<T>(val);
        } else if (val < nodo->dato) {
            inserisci(nodo->sinistro, val);
        } else {
            inserisci(nodo->destro, val);
        }
    }

    bool cerca(Nodo<T>* nodo, T val) const {
        if (!nodo) {
            return false;
        } else if (val == nodo->dato) {
            return true;
        } else if (val < nodo->dato) {
            return cerca(nodo->sinistro, val);
        } else {
            return cerca(nodo->destro, val);
        }
    }

    void dealloca(Nodo<T>* nodo) {
        if (nodo) {
            dealloca(nodo->sinistro);
            dealloca(nodo->destro);
            delete nodo;
        }
    }

public:
    AlberoBinario() : radice(nullptr) {}

    void inserisci(T val) {
        inserisci(radice, val);
    }

    bool cerca(T val) const {
        return cerca(radice, val);
    }

    ~AlberoBinario() {
        dealloca(radice);
    }
};

int main() {
    AlberoBinario<int> albero;
    albero.inserisci(5);
    albero.inserisci(3);
    albero.inserisci(8);
    albero.inserisci(1);
    albero.inserisci(4);

    std::cout << "Cerca 3: " << (albero.cerca(3) ? "Trovato" : "Non trovato") << std::endl;
    std::cout << "Cerca 7: " << (albero.cerca(7) ? "Trovato" : "Non trovato") << std::endl;

    return 0;
}