📢 Nuovo Corso Bootstrap Completo disponibile!

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;
}