Usando Componentes STL em C++

C++Beginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá como usar vários componentes da Biblioteca de Templates Padrão C++ (STL - Standard Template Library) para criar e manipular estruturas de dados como vetores, listas, mapas, conjuntos e muito mais. Você explorará as operações básicas desses containers da STL, incluindo adição, remoção e iteração através de elementos. Além disso, você descobrirá como aproveitar os algoritmos da STL para ordenar, pesquisar e processar dados dentro desses containers. Ao final deste laboratório, você terá uma sólida compreensão de como aproveitar o poder e a flexibilidade da STL C++ para construir aplicações eficientes e robustas.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 90%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Criar e Manipular um Container Vector

Nesta etapa, você aprenderá sobre o container vector da Biblioteca de Templates Padrão C++ (STL), que é um array dinâmico que pode crescer e diminuir de tamanho. Vetores são incrivelmente úteis para armazenar e manipular coleções de elementos.

Primeiro, abra o WebIDE e crie um novo arquivo chamado vector_demo.cpp no diretório ~/project. Exploraremos as operações básicas de vetores passo a passo.

touch ~/project/vector_demo.cpp

Adicione o seguinte código ao arquivo vector_demo.cpp:

#include <iostream>
#include <vector>

int main() {
    // Create an empty vector of integers
    std::vector<int> numbers;

    // Add elements to the vector using push_back()
    numbers.push_back(10);
    numbers.push_back(20);
    numbers.push_back(30);

    // Print the size of the vector
    std::cout << "Vector size: " << numbers.size() << std::endl;

    // Access elements using index
    std::cout << "First element: " << numbers[0] << std::endl;
    std::cout << "Second element: " << numbers[1] << std::endl;

    // Iterate through the vector using a range-based for loop
    std::cout << "All elements: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Remove the last element
    numbers.pop_back();

    // Check the new size after removing an element
    std::cout << "Vector size after pop_back(): " << numbers.size() << std::endl;

    return 0;
}

Compile e execute o programa:

g++ vector_demo.cpp -o vector_demo
./vector_demo

Exemplo de saída:

Vector size: 3
First element: 10
Second element: 20
All elements: 10 20 30
Vector size after pop_back(): 2

Pontos-chave sobre vetores:

  • Use #include <vector> para incluir a biblioteca vector
  • std::vector<type> cria um vetor de um tipo específico
  • push_back() adiciona elementos ao final do vetor
  • size() retorna o número de elementos
  • Acesse elementos usando o índice []
  • pop_back() remove o último elemento
  • O loop for baseado em intervalo (range-based for loop) é uma maneira fácil de iterar através de vetores

Usar List para Operações de Lista Ligada

Nesta etapa, você aprenderá sobre o container list da STL C++, que implementa uma lista duplamente ligada (doubly-linked list). Listas fornecem operações eficientes de inserção e exclusão em qualquer posição no container.

Abra o WebIDE e crie um novo arquivo chamado list_demo.cpp no diretório ~/project:

touch ~/project/list_demo.cpp

Adicione o seguinte código ao arquivo list_demo.cpp:

#include <iostream>
#include <list>

int main() {
    // Create an empty list of integers
    std::list<int> numbers;

    // Add elements to the list
    numbers.push_back(10);    // Add to the end
    numbers.push_front(5);    // Add to the beginning
    numbers.push_back(20);

    // Print the list size
    std::cout << "List size: " << numbers.size() << std::endl;

    // Iterate through the list
    std::cout << "List elements: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Remove elements
    numbers.pop_front();  // Remove first element
    numbers.pop_back();   // Remove last element

    // Insert an element at a specific position
    auto it = numbers.begin();
    numbers.insert(it, 15);

    // Print updated list
    std::cout << "Updated list: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Check if list is empty
    std::cout << "Is list empty? "
              << (numbers.empty() ? "Yes" : "No") << std::endl;

    return 0;
}

Compile e execute o programa:

g++ list_demo.cpp -o list_demo
./list_demo

Exemplo de saída:

List size: 3
List elements: 5 10 20
Updated list: 15 10
Is list empty? No

Pontos-chave sobre listas:

  • Use #include <list> para incluir a biblioteca list
  • push_back() adiciona elementos ao final
  • push_front() adiciona elementos ao início
  • pop_front() e pop_back() removem elementos
  • insert() permite adicionar elementos em uma posição específica
  • begin() retorna um iterador para o primeiro elemento
  • empty() verifica se a lista está vazia

Implementar Pares Chave-Valor com Map

Nesta etapa, você aprenderá sobre o container map da STL C++, que armazena pares chave-valor em uma ordem de chave classificada e única. Maps são úteis para criar dicionários ou arrays associativos.

Abra o WebIDE e crie um novo arquivo chamado map_demo.cpp no diretório ~/project:

touch ~/project/map_demo.cpp

Adicione o seguinte código ao arquivo map_demo.cpp:

#include <iostream>
#include <map>
#include <string>

int main() {
    // Create a map to store student names and their ages
    std::map<std::string, int> students;

    // Insert key-value pairs
    students["Alice"] = 20;
    students["Bob"] = 22;
    students["Charlie"] = 21;

    // Access values using keys
    std::cout << "Alice's age: " << students["Alice"] << std::endl;

    // Check if a key exists
    if (students.count("David") == 0) {
        std::cout << "David is not in the map" << std::endl;
    }

    // Iterate through the map
    std::cout << "All students:" << std::endl;
    for (const auto& student : students) {
        std::cout << student.first << ": " << student.second << std::endl;
    }

    // Remove a key-value pair
    students.erase("Bob");

    // Check the size of the map
    std::cout << "Number of students: " << students.size() << std::endl;

    return 0;
}

Compile e execute o programa:

g++ map_demo.cpp -o map_demo
./map_demo

Exemplo de saída:

Alice's age: 20
David is not in the map
All students:
Alice: 20
Bob: 22
Charlie: 21
Number of students: 2

Pontos-chave sobre maps:

  • Use #include <map> para incluir a biblioteca map
  • map<KeyType, ValueType> cria um map com os tipos de chave e valor especificados
  • Acesse valores usando colchetes []
  • count() verifica se uma chave existe
  • Itere através de maps usando loop for baseado em intervalo (range-based for loop)
  • erase() remove um par chave-valor
  • size() retorna o número de elementos

Armazenar Elementos Únicos Usando Set

Nesta etapa, você aprenderá sobre o container set da STL C++, que armazena elementos únicos em uma ordem classificada. Sets automaticamente evitam valores duplicados e mantêm os elementos em uma ordem específica.

Abra o WebIDE e crie um novo arquivo chamado set_demo.cpp no diretório ~/project:

touch ~/project/set_demo.cpp

Adicione o seguinte código ao arquivo set_demo.cpp:

#include <iostream>
#include <set>

int main() {
    // Create a set of integers
    std::set<int> numbers;

    // Insert elements
    numbers.insert(10);
    numbers.insert(20);
    numbers.insert(30);
    numbers.insert(10);  // Duplicate, will not be added

    // Print the size of the set
    std::cout << "Set size: " << numbers.size() << std::endl;

    // Iterate through the set
    std::cout << "Set elements: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Check if an element exists
    if (numbers.count(20) > 0) {
        std::cout << "20 is in the set" << std::endl;
    }

    // Remove an element
    numbers.erase(20);

    // Check the size after removal
    std::cout << "Set size after removal: " << numbers.size() << std::endl;

    // Clear the set
    numbers.clear();

    // Check if the set is empty
    std::cout << "Is set empty? "
              << (numbers.empty() ? "Yes" : "No") << std::endl;

    return 0;
}

Compile e execute o programa:

g++ set_demo.cpp -o set_demo
./set_demo

Exemplo de saída:

Set size: 3
Set elements: 10 20 30
20 is in the set
Set size after removal: 2
Is set empty? Yes

Pontos-chave sobre sets:

  • Use #include <set> para incluir a biblioteca set
  • set<type> cria um set de elementos únicos
  • insert() adiciona elementos (duplicatas são ignoradas)
  • count() verifica a existência de um elemento
  • erase() remove um elemento
  • clear() remove todos os elementos
  • empty() verifica se o set está vazio
  • Elementos são automaticamente classificados

Ordenar Elementos com o Algoritmo STL sort

Nesta etapa, você aprenderá como usar o algoritmo de ordenação STL para organizar elementos em ordem crescente ou decrescente. A biblioteca <algorithm> fornece capacidades de ordenação poderosas para vários containers.

Abra o WebIDE e crie um novo arquivo chamado sort_demo.cpp no diretório ~/project:

touch ~/project/sort_demo.cpp

Adicione o seguinte código ao arquivo sort_demo.cpp:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // Create a vector of integers
    std::vector<int> numbers = {5, 2, 8, 1, 9, 3};

    // Print original vector
    std::cout << "Original vector: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Sort the vector in ascending order
    std::sort(numbers.begin(), numbers.end());

    // Print sorted vector
    std::cout << "Sorted vector (ascending): ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Sort the vector in descending order
    std::sort(numbers.begin(), numbers.end(), std::greater<int>());

    // Print vector sorted in descending order
    std::cout << "Sorted vector (descending): ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

Compile e execute o programa:

g++ sort_demo.cpp -o sort_demo
./sort_demo

Exemplo de saída:

Original vector: 5 2 8 1 9 3
Sorted vector (ascending): 1 2 3 5 8 9
Sorted vector (descending): 9 8 5 3 2 1

Pontos-chave sobre a ordenação STL:

  • Inclua a biblioteca <algorithm> para ordenação
  • std::sort() funciona com vários containers
  • A ordenação padrão é em ordem crescente
  • std::greater<type>() ordena em ordem decrescente
  • A ordenação é feita in-place, modificando o container original
  • Funciona eficientemente com diferentes tipos de container

Encontrar Elementos Usando Algoritmos STL

Nesta etapa, você aprenderá como usar algoritmos STL para encontrar e pesquisar elementos em containers. A biblioteca <algorithm> fornece funções poderosas para pesquisar e localizar elementos.

Abra o WebIDE e crie um novo arquivo chamado find_demo.cpp no diretório ~/project:

touch ~/project/find_demo.cpp

Adicione o seguinte código ao arquivo find_demo.cpp:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // Create a vector of integers
    std::vector<int> numbers = {5, 2, 8, 1, 9, 3, 8};

    // Find first occurrence of a specific element
    auto it = std::find(numbers.begin(), numbers.end(), 8);
    if (it != numbers.end()) {
        std::cout << "First occurrence of 8 at index: "
                  << std::distance(numbers.begin(), it) << std::endl;
    }

    // Count occurrences of an element
    int count = std::count(numbers.begin(), numbers.end(), 8);
    std::cout << "Number of 8s in the vector: " << count << std::endl;

    // Find if any element is greater than 6
    bool has_large_element = std::any_of(numbers.begin(), numbers.end(),
        [](int n) { return n > 6; });
    std::cout << "Vector has element > 6: "
              << (has_large_element ? "Yes" : "No") << std::endl;

    // Find the minimum and maximum elements
    auto min_it = std::min_element(numbers.begin(), numbers.end());
    auto max_it = std::max_element(numbers.begin(), numbers.end());

    std::cout << "Minimum element: " << *min_it << std::endl;
    std::cout << "Maximum element: " << *max_it << std::endl;

    return 0;
}

Compile e execute o programa:

g++ find_demo.cpp -o find_demo
./find_demo

Exemplo de saída:

First occurrence of 8 at index: 2
Number of 8s in the vector: 2
Vector has element > 6: Yes
Minimum element: 1
Maximum element: 9

Pontos-chave sobre os algoritmos de busca STL:

  • std::find() localiza a primeira ocorrência de um elemento
  • std::count() conta as ocorrências de um elemento
  • std::any_of() verifica se algum elemento atende a uma condição
  • std::min_element() e std::max_element() encontram valores extremos
  • Funções lambda podem ser usadas para condições de busca personalizadas
  • Iteradores de retorno apontam para os elementos encontrados

Iterar Através de Contêineres

Nesta etapa, você aprenderá diferentes maneiras de iterar através de containers STL usando várias técnicas de iteração. Exploraremos loops for baseados em intervalo, iteradores e iteração tradicional baseada em índice.

Abra o WebIDE e crie um novo arquivo chamado iteration_demo.cpp no diretório ~/project:

touch ~/project/iteration_demo.cpp

Adicione o seguinte código ao arquivo iteration_demo.cpp:

#include <iostream>
#include <vector>
#include <list>
#include <map>

int main() {
    // Vector iteration
    std::vector<int> numbers = {10, 20, 30, 40, 50};

    // Method 1: Range-based for loop (most modern and readable)
    std::cout << "Vector iteration (range-based for):" << std::endl;
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Method 2: Iterator-based iteration
    std::cout << "Vector iteration (iterators):" << std::endl;
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // Method 3: Index-based iteration
    std::cout << "Vector iteration (index-based):" << std::endl;
    for (size_t i = 0; i < numbers.size(); ++i) {
        std::cout << numbers[i] << " ";
    }
    std::cout << std::endl;

    // Map iteration
    std::map<std::string, int> ages = {
        {"Alice", 25},
        {"Bob", 30},
        {"Charlie", 35}
    };

    std::cout << "Map iteration:" << std::endl;
    for (const auto& pair : ages) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

Compile e execute o programa:

g++ iteration_demo.cpp -o iteration_demo
./iteration_demo

Exemplo de saída:

Vector iteration (range-based for):
10 20 30 40 50
Vector iteration (iterators):
10 20 30 40 50
Vector iteration (index-based):
10 20 30 40 50
Map iteration:
Alice: 25
Bob: 30
Charlie: 35

Pontos-chave sobre a iteração de containers:

  • Loops for baseados em intervalo são os mais modernos e legíveis
  • Iteradores fornecem controle preciso sobre a travessia do container
  • A iteração baseada em índice funciona bem com containers de acesso aleatório
  • A palavra-chave auto ajuda com a inferência de tipo
  • Diferentes containers suportam diferentes métodos de iteração

Usar Stack e Queue da STL

Nesta etapa, você aprenderá sobre dois importantes adaptadores de container da STL: stack (pilha) e queue (fila). Esses containers fornecem operações especializadas para gerenciamento de dados last-in-first-out (LIFO - último a entrar, primeiro a sair) e first-in-first-out (FIFO - primeiro a entrar, primeiro a sair).

Abra o WebIDE e crie um novo arquivo chamado stack_queue_demo.cpp no diretório ~/project:

touch ~/project/stack_queue_demo.cpp

Adicione o seguinte código ao arquivo stack_queue_demo.cpp:

#include <iostream>
#include <stack>
#include <queue>

int main() {
    // Stack demonstration
    std::stack<int> myStack;

    // Push elements onto the stack
    myStack.push(10);
    myStack.push(20);
    myStack.push(30);

    std::cout << "Stack operations:" << std::endl;
    std::cout << "Top element: " << myStack.top() << std::endl;

    // Remove top element
    myStack.pop();
    std::cout << "Top element after pop: " << myStack.top() << std::endl;
    std::cout << "Stack size: " << myStack.size() << std::endl;

    // Queue demonstration
    std::queue<std::string> myQueue;

    // Add elements to the queue
    myQueue.push("Alice");
    myQueue.push("Bob");
    myQueue.push("Charlie");

    std::cout << "\nQueue operations:" << std::endl;
    std::cout << "Front element: " << myQueue.front() << std::endl;
    std::cout << "Back element: " << myQueue.back() << std::endl;

    // Remove front element
    myQueue.pop();
    std::cout << "Front element after pop: " << myQueue.front() << std::endl;
    std::cout << "Queue size: " << myQueue.size() << std::endl;

    return 0;
}

Compile e execute o programa:

g++ stack_queue_demo.cpp -o stack_queue_demo
./stack_queue_demo

Exemplo de saída:

Stack operations:
Top element: 30
Top element after pop: 20
Stack size: 2

Queue operations:
Front element: Alice
Back element: Charlie
Front element after pop: Bob
Queue size: 2

Pontos-chave sobre stack e queue:

  • Stack (LIFO - Last In, First Out)
    • push() adiciona um elemento ao topo
    • pop() remove o elemento do topo
    • top() retorna o elemento do topo
  • Queue (FIFO - First In, First Out)
    • push() adiciona um elemento ao final
    • pop() remove o elemento da frente
    • front() retorna o primeiro elemento
    • back() retorna o último elemento
  • Ambos têm o método size() para verificar o número de elementos
  • Inclua os cabeçalhos <stack> e <queue>

Lidar com a Segurança de Exceção em Contêineres

Nesta etapa, você aprenderá como lidar com exceções e garantir operações seguras com containers STL. O tratamento de exceções ajuda a prevenir falhas no programa e fornece um gerenciamento de erros robusto.

Abra o WebIDE e crie um novo arquivo chamado exception_safety_demo.cpp no diretório ~/project:

touch ~/project/exception_safety_demo.cpp

Adicione o seguinte código ao arquivo exception_safety_demo.cpp:

#include <iostream>
#include <vector>
#include <stdexcept>

void demonstrateVectorSafety() {
    std::vector<int> numbers;

    try {
        // Attempt to access an element from an empty vector
        std::cout << "Attempting to access element from empty vector:" << std::endl;
        numbers.at(0);  // This will throw an out_of_range exception
    }
    catch (const std::out_of_range& e) {
        std::cout << "Out of Range Error: " << e.what() << std::endl;
    }

    // Safe element addition
    try {
        numbers.push_back(10);
        numbers.push_back(20);
        std::cout << "Vector size: " << numbers.size() << std::endl;

        // Safe element access
        std::cout << "First element: " << numbers.at(0) << std::endl;
        std::cout << "Second element: " << numbers.at(1) << std::endl;
    }
    catch (const std::exception& e) {
        std::cout << "An error occurred: " << e.what() << std::endl;
    }
}

int main() {
    // Demonstrate vector exception safety
    demonstrateVectorSafety();

    return 0;
}

Compile e execute o programa:

g++ exception_safety_demo.cpp -o exception_safety_demo
./exception_safety_demo

Exemplo de saída:

Attempting to access element from empty vector:
Out of Range Error: vector
Vector size: 2
First element: 10
Second element: 20

Pontos-chave sobre a segurança de exceções em containers:

  • Use blocos try-catch para lidar com possíveis exceções
  • std::out_of_range é lançado ao acessar elementos de vetor inválidos
  • O método at() realiza a verificação de limites, ao contrário do operador []
  • Capture exceções específicas primeiro, depois as mais gerais
  • Sempre lide com possíveis exceções para evitar falhas no programa
  • Use classes de exceção padrão de <stdexcept>

Resumo

Neste laboratório, você aprendeu sobre vários componentes da Biblioteca de Modelos Padrão (STL - Standard Template Library) do C++ e como usá-los de forma eficaz. Você começou explorando o container vector, que é um array dinâmico que pode crescer e diminuir de tamanho. Você aprendeu como adicionar e remover elementos, acessá-los usando índices e iterar pelo vector usando um loop for baseado em intervalo.

Em seguida, você se aprofundou no container list, que é uma implementação de lista duplamente ligada. Você descobriu como realizar operações comuns de lista ligada, como inserir, excluir e percorrer elementos. Você também explorou o container map, que permite armazenar pares chave-valor, e o container set, que armazena elementos únicos. Além disso, você aprendeu a usar algoritmos STL como sort e find para manipular e pesquisar elementos dentro desses containers. Por fim, você explorou os containers stack e queue, e discutiu a importância da segurança de exceções ao trabalhar com componentes STL.