Lección 20 · 20 de 20
Proyecto: carrito de la compra · C++
Combine en C++ map, funciones, referencias, excepciones, lectura de datos e iomanip en un carrito de la compra con su ticket.

El proyecto final reúne lo aprendido en un carrito de la compra. El catálogo es un `std::map` que va de cada producto a su precio: const porque nadie debe cambiarlo, y global, fuera de main, para que lo pueda usar cualquier función.
add recibe el carrito por referencia para modificarlo, el producto como const std::string& y las unidades con valor por defecto 1. Antes de sumar comprueba los datos y, si algo no cuadra, lanza std::invalid_argument con un mensaje claro.
Los pedidos se leen de input.txt con while (std::cin >> item >> units), que termina cuando no quedan más. Cada pedido va en su propio try: el caviar, que no está en el catálogo, y el queso sin unidades se descartan con un aviso, y el resto sigue adelante. La última llamada, add(cart, "bread"), usa el valor por defecto.
cart[item] += units acumula: las dos líneas de manzanas suman 10. El ticket recorre el carrito con un enlace estructurado, [name, count], en orden alfabético, y `<iomanip>` alinea las columnas con dos decimales.
Al final, el operador ternario aplica un 10 % de descuento si el total supera 5 euros: 7.88 se queda en 7.09. Con una ventana FLTK en lugar de la consola, esta misma lógica sería una aplicación de escritorio nativa en DMarlon Studio.
Código · main.cpp
#include <iomanip>#include <iostream>#include <map>#include <stdexcept>#include <string>const std::map<std::string, double> catalog = { {"apple", 0.35}, {"bread", 1.20}, {"cheese", 4.75}, {"milk", 0.99}};void add(std::map<std::string, int>& cart, const std::string& item, int units = 1) { if (catalog.count(item) == 0) throw std::invalid_argument("unknown product " + item); if (units <= 0) throw std::invalid_argument("no units of " + item); cart[item] += units;}int main() { std::map<std::string, int> cart; std::string item; int units = 0; // each order: product and units while (std::cin >> item >> units) { try { add(cart, item, units); } catch (const std::exception& e) { std::cout << "Skipped: " << e.what() << '\n'; } } add(cart, "bread"); // one unit by default std::cout << std::fixed << std::setprecision(2); double total = 0; for (const auto& [name, count] : cart) { double price = catalog.at(name); total += count * price; std::cout << std::left << std::setw(7) << name << std::right << std::setw(3) << count << " x" << std::setw(5) << price << std::setw(7) << count * price << '\n'; } std::cout << "Total " << total << ", to pay " << (total > 5 ? total * 0.90 : total) << '\n'; return 0;}Entrada (lo que se teclea) · input.txt
apple 6 milk 2 caviar 1 bread 1 cheese 0 apple 4
Salida · c++ -std=c++17 main.cpp -o main && ./main
Skipped: unknown product caviar Skipped: no units of cheese apple 10 x 0.35 3.50 bread 2 x 1.20 2.40 milk 2 x 0.99 1.98 Total 7.88, to pay 7.09
Para recordar
- Un
std::mapconstante sirve de catálogo de precios. - Pase por referencia lo que la función debe modificar.
- Valide los datos y lance una excepción si no son correctos.
- Un
trypor pedido: un error no detiene el resto. <iomanip>convierte los datos en un ticket legible.
Ejercicio
Guarde también el ticket en receipt.txt con un std::ofstream y haga que add rechace con una excepción cualquier pedido de más de 20 unidades.