Ficha 01 · C++ moderno fundamentos
Exercício 1 · auto e range-for
Cria um vector<int> com 10 números. Usa auto em todo o lado possível e range-based for para imprimir, dobrar e somar.
Resposta:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Imprimir
cout << "Originais: ";
for (auto n : nums) cout << n << " ";
cout << endl;
// Dobrar (note auto&)
for (auto& n : nums) {
n *= 2;
}
cout << "Dobrados: ";
for (auto n : nums) cout << n << " ";
cout << endl;
// Somar
auto soma = 0;
for (auto n : nums) soma += n;
cout << "Soma: " << soma << endl;
}
Exercício 2 · Function template
Cria função template T menor(T a, T b) que retorna o menor de dois valores. Testa com int, double e string.
Resposta:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T menor(T a, T b) {
return (a < b) ? a : b;
}
int main() {
cout << menor(3, 7) << endl; // 3
cout << menor(2.5, 1.8) << endl; // 1.8
cout << menor<string>("banana", "ananas") << endl; // ananas
}
Exercício 3 · Class template Pilha
Cria classe template Pilha<T> com métodos push(T), pop(), top(), size(), empty(). Usa vector<T> internamente. Testa com int e string.
Resposta:
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
using namespace std;
template <typename T>
class Pilha {
private:
vector<T> dados;
public:
void push(T val) { dados.push_back(val); }
void pop() {
if (dados.empty()) throw runtime_error("Pilha vazia");
dados.pop_back();
}
T top() const {
if (dados.empty()) throw runtime_error("Pilha vazia");
return dados.back();
}
size_t size() const { return dados.size(); }
bool empty() const { return dados.empty(); }
};
int main() {
Pilha<int> p;
p.push(1);
p.push(2);
p.push(3);
cout << p.top() << endl; // 3
p.pop();
cout << p.top() << endl; // 2
Pilha<string> ps;
ps.push("primeiro");
ps.push("segundo");
cout << ps.top() << endl; // segundo
}
Exercício 4 · STL sort + lambda
Cria vector<pair<string, int>> com 5 (nome, idade). Ordena de duas formas usando lambdas:
1. Por nome (alfabético).
2. Por idade (decrescente).
Resposta:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main() {
vector<pair<string, int>> pessoas{
{"Ana", 25},
{"Bruno", 32},
{"Carla", 19},
{"Diana", 41},
{"Eduardo", 28}
};
// Por nome
sort(pessoas.begin(), pessoas.end(),
[](const auto& a, const auto& b) {
return a.first < b.first;
});
cout << "Por nome:\n";
for (const auto& [nome, idade] : pessoas)
cout << " " << nome << " (" << idade << ")\n";
// Por idade decrescente
sort(pessoas.begin(), pessoas.end(),
[](const auto& a, const auto& b) {
return a.second > b.second;
});
cout << "\nPor idade desc:\n";
for (const auto& [nome, idade] : pessoas)
cout << " " << nome << " (" << idade << ")\n";
}
Exercício 5 · Map e algoritmos
Conta a frequência de palavras numa frase usando map<string, int>. Imprime ordenado por frequência (decrescente).
Resposta:
#include <iostream>
#include <map>
#include <vector>
#include <sstream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
string frase = "a casa é grande a casa é bonita a vida é boa";
map<string, int> contagem;
stringstream ss(frase);
string palavra;
while (ss >> palavra) {
contagem[palavra]++;
}
// Copiar para vector para ordenar
vector<pair<string, int>> v(contagem.begin(), contagem.end());
sort(v.begin(), v.end(),
[](const auto& a, const auto& b) {
return a.second > b.second;
});
for (const auto& [p, n] : v) {
cout << p << ": " << n << endl;
}
}
Exercício 6 · Filter + transform com STL
Dado vector<int> nums{1..20}, usa STL para:
1. Filtrar apenas pares.
2. Elevar ao quadrado.
3. Somar tudo.
Faz sem range-based for — usa copy_if, transform, accumulate.
Resposta:
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
int main() {
vector<int> nums;
for (int i = 1; i <= 20; i++) nums.push_back(i);
// Filter — só pares
vector<int> pares;
copy_if(nums.begin(), nums.end(), back_inserter(pares),
[](int n) { return n % 2 == 0; });
// Transform — quadrado
transform(pares.begin(), pares.end(), pares.begin(),
[](int n) { return n * n; });
// Sum
int soma = accumulate(pares.begin(), pares.end(), 0);
cout << "Pares ao quadrado: ";
for (int n : pares) cout << n << " ";
cout << "\nSoma: " << soma << endl;
// 4 16 36 64 100 144 196 256 324 400
// Soma: 1540
}
Exercício 7 · unique_ptr
Cria classe Pessoa com construtor que imprime "Criada" e destructor que imprime "Destruída". Demonstra que unique_ptr apaga automaticamente. Tenta copiar e mostra que dá erro de compilação. Depois usa move.
Resposta:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Pessoa {
private:
string nome;
public:
Pessoa(string n) : nome(n) {
cout << "Criada: " << nome << endl;
}
~Pessoa() {
cout << "Destruída: " << nome << endl;
}
void cumprimentar() {
cout << "Olá, sou " << nome << endl;
}
};
int main() {
{
auto p = make_unique<Pessoa>("Ana");
p->cumprimentar();
// auto p2 = p; // ❌ ERRO de compilação
auto p2 = move(p); // ✅ move
if (!p) cout << "p é nullptr agora" << endl;
p2->cumprimentar();
}
// "Destruída: Ana" automaticamente aqui
cout << "Fim do main" << endl;
}
Exercício 8 · shared_ptr com lista
Cria vector<shared_ptr<Pessoa>> com 3 pessoas. Faz uma cópia do vector e verifica que use_count() é 2 para cada uma. Liberta o segundo vector e mostra que voltam a 1.
Resposta:
#include <iostream>
#include <memory>
#include <vector>
#include <string>
using namespace std;
class Pessoa {
public:
string nome;
Pessoa(string n) : nome(n) { cout << "+" << nome << endl; }
~Pessoa() { cout << "-" << nome << endl; }
};
int main() {
vector<shared_ptr<Pessoa>> v1;
v1.push_back(make_shared<Pessoa>("Ana"));
v1.push_back(make_shared<Pessoa>("Bruno"));
v1.push_back(make_shared<Pessoa>("Carla"));
cout << "\nuse_count inicial:\n";
for (const auto& p : v1)
cout << " " << p->nome << ": " << p.use_count() << endl;
{
auto v2 = v1; // cópia — incrementa refcounts
cout << "\nApós cópia:\n";
for (const auto& p : v1)
cout << " " << p->nome << ": " << p.use_count() << endl;
} // v2 sai de scope
cout << "\nApós v2 morrer:\n";
for (const auto& p : v1)
cout << " " << p->nome << ": " << p.use_count() << endl;
return 0;
}