Partilhar: WhatsApp
aulify
UC UC02839 · T. Desenv. Software

Ficha 01 · C++ moderno fundamentos

auto, templates, STL, lambdas
Versão · Aluno
Tempo · 45 minutos
Aluno(a)
Turma
Data

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