Esercizi Classi Template C++
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;}