DMarlon Studio

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.

C++ · Proyecto: carrito de la compra en DMarlon Studio: el código del ejemplo y su salida en la terminal

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::map constante 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 try por 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.