Utilizar componentes de la STL en C++

C++Beginner
Practicar Ahora

Introducción

En este laboratorio, aprenderás cómo utilizar varios componentes de la Biblioteca Estándar de Plantillas (Standard Template Library, STL) de C++ para crear y manipular estructuras de datos como vectores, listas, mapas, conjuntos y más. Explorarás las operaciones básicas de estos contenedores de la STL, incluyendo la adición, eliminación e iteración a través de los elementos. Además, descubrirás cómo aprovechar los algoritmos de la STL para ordenar, buscar y procesar datos dentro de estos contenedores. Al final de este laboratorio, tendrás una comprensión sólida de cómo aprovechar el poder y la flexibilidad de la STL de C++ para construir aplicaciones eficientes y robustas.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 90%. Ha recibido una tasa de reseñas positivas del 100% por parte de los estudiantes.

Crear y manipular el contenedor vector

En este paso, aprenderás sobre el contenedor vector de la Biblioteca Estándar de Plantillas (Standard Template Library, STL) de C++, que es un arreglo dinámico que puede crecer y encogerse en tamaño. Los vectores son increíblemente útiles para almacenar y manipular colecciones de elementos.

Primero, abre el WebIDE y crea un nuevo archivo llamado vector_demo.cpp en el directorio ~/project. Exploraremos las operaciones básicas de los vectores paso a paso.

touch ~/project/vector_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre los vectores:

  • Utiliza #include <vector> para incluir la biblioteca de vectores
  • std::vector<type> crea un vector de un tipo específico
  • push_back() agrega elementos al final del vector
  • size() devuelve el número de elementos
  • Accede a los elementos utilizando el índice []
  • pop_back() elimina el último elemento
  • El bucle for basado en rangos es una forma fácil de iterar a través de los vectores

Utilizar la lista (list) para operaciones de lista enlazada

En este paso, aprenderás sobre el contenedor list de la STL de C++, que implementa una lista doblemente enlazada. Las listas ofrecen operaciones de inserción y eliminación eficientes en cualquier posición del contenedor.

Abre el WebIDE y crea un nuevo archivo llamado list_demo.cpp en el directorio ~/project:

touch ~/project/list_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre las listas:

  • Utiliza #include <list> para incluir la biblioteca de listas
  • push_back() agrega elementos al final
  • push_front() agrega elementos al principio
  • pop_front() y pop_back() eliminan elementos
  • insert() permite agregar elementos en una posición específica
  • begin() devuelve un iterador al primer elemento
  • empty() comprueba si la lista está vacía

Implementar pares clave-valor con map

En este paso, aprenderás sobre el contenedor map de la STL de C++, que almacena pares clave-valor en un orden de claves único y ordenado. Los mapas son útiles para crear diccionarios o arreglos asociativos.

Abre el WebIDE y crea un nuevo archivo llamado map_demo.cpp en el directorio ~/project:

touch ~/project/map_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre los mapas:

  • Utiliza #include <map> para incluir la biblioteca de mapas
  • map<KeyType, ValueType> crea un mapa con tipos de clave y valor especificados
  • Accede a los valores utilizando corchetes cuadrados []
  • count() comprueba si una clave existe
  • Itera a través de los mapas utilizando un bucle for basado en rangos
  • erase() elimina un par clave-valor
  • size() devuelve el número de elementos

Almacenar elementos únicos utilizando set

En este paso, aprenderás sobre el contenedor set de la STL de C++, que almacena elementos únicos en un orden ordenado. Los sets evitan automáticamente valores duplicados y mantienen los elementos en un orden específico.

Abre el WebIDE y crea un nuevo archivo llamado set_demo.cpp en el directorio ~/project:

touch ~/project/set_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre los sets:

  • Utiliza #include <set> para incluir la biblioteca de sets
  • set<type> crea un set de elementos únicos
  • insert() agrega elementos (los duplicados se ignoran)
  • count() comprueba la existencia de un elemento
  • erase() elimina un elemento
  • clear() elimina todos los elementos
  • empty() comprueba si el set está vacío
  • Los elementos se ordenan automáticamente

Ordenar elementos con el algoritmo de ordenación STL

En este paso, aprenderás cómo utilizar el algoritmo de ordenamiento de la STL (Standard Template Library) para organizar elementos en orden ascendente o descendente. La biblioteca <algorithm> ofrece poderosas capacidades de ordenamiento para varios contenedores.

Abre el WebIDE y crea un nuevo archivo llamado sort_demo.cpp en el directorio ~/project:

touch ~/project/sort_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre el ordenamiento de la STL:

  • Incluye la biblioteca <algorithm> para el ordenamiento.
  • std::sort() funciona con varios contenedores.
  • El ordenamiento predeterminado es en orden ascendente.
  • std::greater<type>() ordena en orden descendente.
  • El ordenamiento se realiza in-place (en el mismo lugar), modificando el contenedor original.
  • Funciona de manera eficiente con diferentes tipos de contenedores.

Encontrar elementos utilizando algoritmos STL

En este paso, aprenderás cómo utilizar los algoritmos de la STL (Standard Template Library) para encontrar y buscar elementos en contenedores. La biblioteca <algorithm> ofrece funciones poderosas para buscar y localizar elementos.

Abre el WebIDE y crea un nuevo archivo llamado find_demo.cpp en el directorio ~/project:

touch ~/project/find_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre los algoritmos de búsqueda de la STL:

  • std::find() localiza la primera aparición de un elemento.
  • std::count() cuenta las apariciones de un elemento.
  • std::any_of() comprueba si algún elemento cumple una condición.
  • std::min_element() y std::max_element() encuentran los valores extremos.
  • Se pueden utilizar funciones lambda para condiciones de búsqueda personalizadas.
  • Los iteradores devueltos apuntan a los elementos encontrados.

Iterar a través de contenedores

En este paso, aprenderás diferentes formas de iterar a través de contenedores de la STL utilizando diversas técnicas de iteración. Exploraremos los bucles for basados en rangos, los iteradores y la iteración tradicional basada en índices.

Abre el WebIDE y crea un nuevo archivo llamado iteration_demo.cpp en el directorio ~/project:

touch ~/project/iteration_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre la iteración de contenedores:

  • Los bucles for basados en rangos son los más modernos y legibles.
  • Los iteradores brindan un control detallado sobre el recorrido del contenedor.
  • La iteración basada en índices funciona bien con contenedores de acceso aleatorio.
  • La palabra clave auto ayuda con la inferencia de tipos.
  • Diferentes contenedores admiten diferentes métodos de iteración.

Utilizar stack y queue de la STL

En este paso, aprenderás sobre dos importantes adaptadores de contenedores de la STL (Standard Template Library): la pila (stack) y la cola (queue). Estos contenedores proporcionan operaciones especializadas para la gestión de datos con el principio de último en entrar, primero en salir (LIFO, por sus siglas en inglés) y primero en entrar, primero en salir (FIFO, por sus siglas en inglés).

Abre el WebIDE y crea un nuevo archivo llamado stack_queue_demo.cpp en el directorio ~/project:

touch ~/project/stack_queue_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre la pila y la cola:

  • Pila (LIFO - Último en Entrar, Primero en Salir)
    • push() agrega un elemento en la cima.
    • pop() elimina el elemento de la cima.
    • top() devuelve el elemento de la cima.
  • Cola (FIFO - Primero en Entrar, Primero en Salir)
    • push() agrega un elemento al final.
    • pop() elimina el elemento del frente.
    • front() devuelve el primer elemento.
    • back() devuelve el último elemento.
  • Ambos tienen el método size() para comprobar el número de elementos.
  • Incluye las cabeceras <stack> y <queue>.

Manejar la seguridad frente a excepciones de contenedores

En este paso, aprenderás cómo manejar excepciones y garantizar operaciones seguras con los contenedores de la STL (Standard Template Library). El manejo de excepciones ayuda a prevenir la caída del programa y proporciona una gestión robusta de errores.

Abre el WebIDE y crea un nuevo archivo llamado exception_safety_demo.cpp en el directorio ~/project:

touch ~/project/exception_safety_demo.cpp

Agrega el siguiente código al archivo 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;
}

Compila y ejecuta el programa:

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

Ejemplo de salida:

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

Puntos clave sobre la seguridad ante excepciones en contenedores:

  • Utiliza bloques try-catch para manejar posibles excepciones.
  • Se lanza std::out_of_range cuando se intenta acceder a elementos inválidos de un vector.
  • El método at() realiza comprobaciones de límites, a diferencia del operador [].
  • Captura primero las excepciones específicas y luego las más generales.
  • Siempre maneja las posibles excepciones para prevenir la caída del programa.
  • Utiliza las clases de excepciones estándar de <stdexcept>.

Resumen

En este laboratorio, aprendiste sobre varios componentes de la Biblioteca Estándar de Plantillas (Standard Template Library, STL) de C++ y cómo utilizarlos de manera efectiva. Comenzaste explorando el contenedor vector, que es un arreglo dinámico que puede aumentar y disminuir de tamaño. Aprendiste cómo agregar y eliminar elementos, acceder a ellos utilizando índices y recorrer el vector utilizando un bucle for basado en rangos.

A continuación, profundizaste en el contenedor list, que es una implementación de lista doblemente enlazada. Descubriste cómo realizar operaciones comunes de listas enlazadas, como insertar, eliminar y recorrer elementos. También exploraste el contenedor map, que te permite almacenar pares clave-valor, y el contenedor set, que almacena elementos únicos. Además, aprendiste cómo utilizar algoritmos de la STL, como sort y find, para manipular y buscar elementos dentro de estos contenedores. Finalmente, exploraste los contenedores stack y queue, y se discutió la importancia de la seguridad ante excepciones cuando se trabaja con componentes de la STL.