Ejercicio: Uso de un bucle para iterar por datos

Completado

En este ejercicio, modificará el programa de fábrica de automóviles para usar un bucle a fin de iterar por los pedidos de automóviles.

Se actualizará la función main para agregar una expresión de bucle a fin de procesar el conjunto completo de pedidos. La estructura de bucle permite reducir la redundancia en el código. Al simplificar el código, se puede aumentar fácilmente la cantidad de pedidos.

En la función car_factory, se agregará otro bucle para evitar el estado de alarma en tiempo de ejecución en un valor fuera de los límites.

El desafío consiste en finalizar el código de ejemplo para que se compile y se ejecute.

Para trabajar en el código de ejemplo de este ejercicio, tiene dos opciones:

  • Copiar el código y editarlo en el entorno de desarrollo local.
  • Abrir el código en un Área de juegos de Rust preparada.

Nota:

En el código de ejemplo, busque la macro todo!. Esta macro indica el código que debe completarse o actualizarse.

Carga del programa

Si ha cerrado el código del programa del último ejercicio, puede volver a abrirlo en esta Área de juegos de Rust preparada.

Asegúrese de recompilar el programa y de que todavía se ejecuta sin errores del compilador.

Repetición de acciones con una expresión de bucle

Es necesario actualizar el programa para admitir más pedidos. La estructura de código actual usa instrucciones redundantes para admitir seis pedidos. La redundancia es complicada y difícil de mantener.

Se puede simplificar la estructura mediante una expresión de bucle para repetir las acciones a fin de crear cada pedido. Con el código simplificado, se puede crear rápidamente un gran número de pedidos.

  1. En la función main, quite las instrucciones siguientes. Este bloque de código define y establece la variable order, llama a la función car_factory y a la macro println! para los pedidos de automóviles, e inserta cada pedido en el mapa hash orders.

        // Order 6 cars
        // - Increment "order" after each request
        // - Add each order <K, V> pair to "orders" hash map
        // - Call println! to show order details from the hash map
    
        // Initialize order variable
        let mut order = 1;
    
        // Car order #1: Used, Hard top
        car = car_factory(order, 1000);
        orders.insert(order, car);
        println!("Car order {}: {:?}", order, orders.get(&order));
    
        ...
    
        // Car order #6: Used, Hard top
        order = order + 1;
        car = car_factory(order, 4000);
        orders.insert(order, car);
        println!("Car order {}: {:?}", order, orders.get(&order));
    
  2. Reemplace las instrucciones quitadas por el bloque de código siguiente:

        // Start with zero miles
        let mut miles = 0;
    
        todo!("Add a loop expression to fulfill orders for 6 cars, initialize `order` variable to 1") {
    
            // Call car_factory to fulfill order
            // Add order <K, V> pair to "orders" hash map
            // Call println! to show order details from the hash map        
            car = car_factory(order, miles);
            orders.insert(order, car);
            println!("Car order {}: {:?}", order, orders.get(&order));
    
            // Reset miles for order variety
            if miles == 2100 {
                miles = 0;
            } else {
                miles = miles + 700;
            }
        }
    
  3. Agregue una expresión de bucle que repita las acciones a fin de crear pedidos para seis automóviles. Necesitará una variable order inicializada en 1.

  4. Compile el programa. Asegúrese de que el código se compila sin errores.

Debería mostrarse una salida similar a esta de ejemplo:

Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("Used", 1400) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 700) })

Aumento de pedidos de automóviles a 11

Ahora en el programa se usa un bucle para cumplimentar los pedidos de seis automóviles. ¿Qué ocurre si se piden más de seis automóviles?

  1. Actualice la expresión de bucle en la función main para pedir 11 automóviles:

        todo!("Update the loop expression to create 11 cars");
    
  2. Recompile el programa. En tiempo de ejecución, el programa entra en estado de alarma.

    Compiling playground v0.0.1 (/playground)
        Finished dev [unoptimized + debuginfo] target(s) in 1.26s
        Running `target/debug/playground`
    thread 'main' panicked at 'index out of bounds: the len is 4 but the index is 4', src/main.rs:34:29
    

Ahora se verá cómo resolver este problema.

Prevención del estado de alarma en tiempo de ejecución con una expresión de bucle

En la función car_factory, se usa una expresión if/else a fin de comprobar el valor del índice color para la matriz colors:

    // Prevent panic: Check color index for colors array, reset as needed
    // Valid color = 1, 2, 3, or 4
    // If color > 4, reduce color to valid index
    let mut color = order as usize;
    if color > 4 {        
        // color = 5 --> index 1, 6 --> 2, 7 --> 3, 8 --> 4
        color = color - 4;
    }

La matriz colors tiene cuatro elementos y el intervalo del índice color válido es de 0 a 3. La expresión condicional comprueba si el índice color es mayor que 4. (No se comprueba si el índice color es igual a 4. Más adelante en la función, cuando indexamos en la matriz para asignar el color del automóvil, restamos uno del valor del índice: color - 1. Un valor color de 4 se procesa como colors[3] en la matriz).

La expresión if/else actual funciona bien para evitar que el tiempo de ejecución entre en estado de alarma cuando se piden ocho automóviles o menos. Pero si se piden 11 automóviles, el programa entra en estado de alarma en el noveno pedido. Es necesario ajustar la expresión para que sea más sólida. Para realizar esta mejora, se usará otra expresión de bucle.

  1. En la función car_factory, reemplace la instrucción condicional if/else por una expresión de bucle. Revise las instrucciones de pseudocódigo siguientes para evitar un estado de alarma en tiempo de ejecución si el valor del índice color es mayor que 4.

        // Prevent panic: Check color index, reset as needed
        // If color = 1, 2, 3, or 4 - no change needed
        // If color > 4, reduce to color to a valid index
        let mut color = order as usize;
        todo!("Replace `if/else` condition with a loop to prevent run-time panic for color > 4");
    

    Sugerencia

    En este caso, el cambio de una condición if/else a una expresión de bucle es muy sencilla.

  2. Compile el programa. Asegúrese de que el código se compila sin errores.

Debería ver la siguiente salida:

Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("Used", 1400) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 700) })
Car order 7: Some(Car { color: "Red", motor: Manual, roof: true, age: ("Used", 1400) })
Car order 8: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 9: Some(Car { color: "Blue", motor: Automatic, roof: true, age: ("New", 0) })
Car order 10: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 11: Some(Car { color: "Red", motor: Manual, roof: true, age: ("Used", 1400) })

Solución

Puede comparar la salida del programa con la solución de este ejercicio en esta Área de juegos de Rust.