Entrada de Datos. Rust
SOLUCIONARIO
Entrada de Datos. Rust
2026-07-26
Por
Occam's Razor

use std::io;
use std::io::Write;

fn main() {
    let mut input = String::new();
    let mut input1 = String::new();

    print! ("Introduce dos numerados separados por un espacio? ");
    let _= io::stdout().flush();
    io::stdin().read_line(&mut input).unwrap(); 
    let mut a1 = input.split_whitespace().map(|s| s.parse::<i32>());
    let (n, t)  = (a1.next().unwrap().unwrap(), a1.next().unwrap().unwrap());
    println!("Has introducido {} y {}", n, t);

    println! ("Introduce 10 numeros separados por espacios ? ");
    io::stdin().read_line(&mut input1).unwrap();
    let a1 = input1.split_whitespace().map(|s| s.parse::<i32>());

    for i in a1 { print!( "{} ", i.unwrap());}; println!();
}

La versión Rust utiliza la opción de trocear la cadena de caracteres con el método split de la clase String. Además para la lectura del array, utiliza la función map para convertir a enteros de 32 bits cada una de las cadenas que nos devuelve split.

SOY NOVATO

Te preguntarás que son todas esas llamadas a unwrap en el programa… ya, yo también me lo pregunté en su día. Rust usa el valor enumerado Option y su versión mejorada Result. Estos tipos permiten representar situaciones en las que tenemos que trabajar con un valor… o con nada. El enumerado Option puede contener el valor None o Some valor. Así primero podemos saber si tenemos valor o no, y luego ya acceder a ese valor.

Esto último se puede hacer con el método unwrap que extraerá el valor que nos interesa del valor Option o utilizando la palabra clave match que nos permite machear el valor None directamente. unwrap es equivalente a un bloque match, en el que o retornamos el valor o invocamos panic directamente que normalmente terminará el programa.

Result sigue el mismo concepto pero cuando necesitamos retornar códigos de error. Este tipo define dos variantes Ok(T) (no error y hay un valor que recuperar) o Err(E) (se ha producido un error, y el valor que obtendrás estará relacionado con el error).

 

La línea que realiza todo el trabajo es:

    let a1 = input1.split_whitespace().map(|s| s.parse::<i32>());

Esta línea genera un iterador para recorrer las subcadenadas generadas a partir de separar la primera cadena por los espacios en blanco, para luego aplicar el método parse a cada una de esas subcadenas y así convertir cada una de ellas a entero. El código es más o menos similar a:

    let mut a1 = Vec::new();

    for val in input1.split_whitespace() {
        a1.push (val.parse::<i32>()) 
    }

Aunque no exactamente ya que los tipos son diferentes. En el primer caso a1 es un iterador mientras que en el segundo estamos generando un vector de Result. La diferencia es sutil, mientras en este último ejemplo estamos generando una array y almacenando sus valores. En el código inicial con el iterador, ningún array es creado, todo el proceso de dividir la cadena y convertir a entero se produce al recorrer el iterador cuando lo imprimimos posteriormente, descartando todos esos valores intermedios una vez consumidos.

El método parse es muy potente y nos permite convertir o interpretar muchos tipos e datos. En realidad, nos permite convertir desde cadena a cualquier tipo en Rust que implemente el método FromStr para llevar a cabo esa conversión. Tipos como float, bool o incluso IpAddr pueden ser convertiso usando parse

SOY NOVATO

Podemos pensar en los iteradores como una serie de operaciones que preparamos para que se ejecuten sobre unos ciertos valores de entrada. Esto se conoce como stream processing y se ha popularizado en varios lenguajes recientemente tras la incorporación de elementos de programación funcional como las funciones lambda en los lenguajes. Podemos verlos en Python o Java.

Dependiendo de lo que queramos hacer con los datos los iteradores pueden ser más interesantes ahorrando memoria, por ejemplo. La gran ventaja que ofrecen es el encadenamiento de operaciones así como una serie de formas de procesar los datos con las que conseguir resultados de forma sencilla y rápida. La siguiente línea de código calcularía la suma de todos los valores introducidos por el usuario, sin almacenarlos en memoria (solo cada uno de los valores temporalmemnte)

let sum: i32 = input.split_whitespace().map(str::parse::<i32>).filter_map(Result::ok).sum();
 

Si necesitamos determinar si las entradas del usuario son correctas podemos evaluar Result con match, algo como esto.

    let mut numbers = Vec::new();

    for num in input1.split_whitespaces() {
        match num.parse::<i32>() {
            Ok(n) => numbers.push(n),
            Err(_) => {
                println!("'{}' is not a valid integer.", part);
                return;
            }
        }
    }

Si bien este código creo que es más legible, la forma idiomática de hacerlo en Rust (la recomendada digamos sería la siguiente:

let numbers: Result<Vec<i32>, _> = input1
    .split_whitespace()
    .map(|s| s.parse::<i32>())
    .collect();

match numbers {
    Ok(nums) => {
        println!("Valid input: {:?}", nums);
    }
    Err(_) => {
        println!("Please enter only integers.");
    }
}

Aquí estamos creando un objeto Result donde el valor OK es nuestro vector. El elemento clave es la llamada a collect() que genera precisamente eso. Si todos los valores son correctos (OK) los recolecta en un vector que estará disponible bajo el valor OK del Result resultante (valga la redundancia). Si se produce cualquier error, collect termina y retorna ese error con el valor Err de Result. Observad que si bien, esto es muy potente y elegante, no nos permite saber que valor fue el que produjo el error, solo si todos los datos son correctos o hay algún error.

Resumen

  • En Rust tenemos que leer cadenas de caracteres de la consola y luego trocearlas o interpretarlas adecuiadamente según nuestras necesidades.
  • El método split_whitespace() nos permite dividir cadenas de caracteres fácilmente
  • El método parse::<TYPE> nos permite interpretar cualquier tipo que implemente el método FromStr

SOBRE Occam's Razor
Somos una revista libre que intenta explicar de forma sencilla conceptos tecnológicos y científicos de los que no podemos escapar. Al final, todo es más fácil de lo que parece!

 
Tu publicidad aquí :)