Primeros pasos en Rust - Entrada/Salida Estándar

Apuntes de Rust - Parte 2


Comentarios

Iniciemos con los diferentes tipos de comentarios en Rust. Ejemplo:

// La función main es el punto de entrada del programa 
fn main() {
    // println imprime un texto en pantalla
    println!("Hello, World!");
}

Recuerde que los comentarios son líneas de texto utilizadas para documentar código. Se usa, al igual que en otros lenguajes de programación, el par de caracteres // para crear un comentario de una sola línea.

En Rust también puede crear bloques de comentarios, con los caracteres /* y \/* . Ejemplo:

fn main() {
    /*
      declara una variable llamada x
      y asigna un valor inicial (en este caso x está inicializada en 1)
    */
    let x = 1;
    println!("x = {}", x);
}

Puede ver que el comentario de bloque se extiende por varias líneas del archivo. Por lo tanto, también se conoce como comentarios de varias líneas. El bloque anterior es equivalente a:

fn main() {
    // declara una variable llamada x
    // y asigna un valor inicial (en este caso x está inicializada en 1)
    let x = 1;
    println!("x = {}", x);
}

Escribir comentarios en el código (útiles y precisos) es una buena práctica de desarrollo.


Salida Estandar

En Rust se utilza elmacro println! para imprimir cadenas de texto, números y variables en la consola.

fn main() {
    println!("¡Hola, mundo!");
}

En Rust, una macro es una característica que permite la definición de código generativo. Una macro en Rust se define utilizando la palabra clave macro_rules! seguida de un nombre para la macro y un conjunto de reglas que especifican cómo se debe expandir y generar el código. Las macros en Rust pueden aceptar argumentos y generar código en función de esos argumentos.

Las macros en Rust se utilizan para automatizar tareas repetitivas, generar código o extender la sintaxis del lenguaje. Permiten escribir código más expresivo y conciso al introducir abstracciones y patrones de generación de código.

println! es un ejemplo de macros en Rust. La macro println! se utiliza para imprimir texto en la consola. Las macros en Rust son una poderosa herramienta que permite la generación de código flexible y la personalización del lenguaje.

En Rust, existen dos variaciones de la función print:

  • print!() imprime los valores proporcionados en la salida de la consola sin agregar un salto de línea al final.

Ejemplo:

let nombre = "Jesse";
let edad = 37;
print!("Mi nombre es {} y tengo {} años.", nombre, edad);

Salida:

Mi nombre es Jesse y tengo 37 años.
  • println!() también imprime los valores proporcionados en la salida de la consola, pero agrega automáticamente un salto de línea al final.

Ejemplo:

let nombre = "Jesse";
let edad = 37;
println!("Mi nombre es {}.", nombre);
println!("Tengo {} años.", edad);

Salida:

Mi nombre es Jesse.
Tengo 37años.

Podemos utilizar println! para imprimir varias variables en una sola linea. Por ejemplo:

let variable_1 = "Cadena 1";
let variable_2 = "Cadena 2";
let variable_3 = "Cadena 3";
print!("valor -> variable_1 {}, variable_2 {}, variable_3 {}", variable_1, variable_2, variable_3);

Sin embargo, también podemos especificar la numeración de los marcadores de posición para imprimir las variables en un orden diferente. Por ejemplo:

let variable_1 = "Cadena 1";
let variable_2 = "Cadena 2";
let variable_3 = "Cadena 3";
print!("valor -> variable_3 {2}, variable_2 {1}, variable_1 {0}", variable_1, variable_2, variable_3);

Finalmente, también podemos usar los nombres de las variables directamente dentro del marcador de posición. Por ejemplo:

let variable_1 = "Cadena 1";
let variable_2 = "Cadena 2";
print!("valor -> variable_1 {variable_1}, variable_2 {variable_2}");

Nota: En Rust, podemos imprimir una nueva línea utilizando la secuencia de escape \n.


Entrada Estandar

Para comprender la entrada estandar, utilicemos el siguiente ejemplo:

use std::io;

fn main() {
    println!("Escriba su nombre: ");
    let mut nombre: String = String::new();

    io::stdin()
        .read_line(&mut nombre)
        .expect("Error al leer la entrada del usuario");

    println!("Bienvenido, {nombre}");
}

Este código obtiene un dato de entrada del usuario y luego imprime un mensaje como salida. Para esto importamos la biblioteca de entrada/salida “io” al ámbito utilizando la palabra reservada use. La biblioteca “io” proviene de la biblioteca estándar, conocida como “std”.

La palabra reservada use se utiliza para importar módulos, funciones, estructuras de datos u otros elementos de un ámbito externo al ámbito actual. Permite acceder a esos elementos directamente sin tener que calificar su nombre completo con el ámbito de origen.

use nombre_del_modulo::nombre_del_elemento;

let mut nombre crea una variable mutable llamada nombre. El signo igual (\=) le indica a Rust que queremos asignar un valor a la variable ahora. A la derecha del signo igual se encuentra el valor al que nombre está vinculado, que es el resultado de llamar a String::new, una función que devuelve una nueva instancia de un String.

let mut nombre: String = String::new();

String es un tipo de cadena proporcionado por la biblioteca estándar que es una secuencia de texto codificada en UTF-8 y que puede crecer en tamaño.

La sintaxis :: en la línea ::new indica que new es una función asociada al tipo String. Una función asociada es una función implementada en un tipo, en este caso en String. Esta función new crea una nueva cadena vacía. La Función new es un constructor, recordemos que un constructor es una función que crea un nuevo valor de algún tipo.

La línea completa let mut nombre = String::new(); ha creado una variable mutable que actualmente está vinculada a una nueva instancia vacía de un String.

Ahora invocaremos a la función stdin del módulo io, lo que nos permitirá manejar la entrada del usuario.

io::stdin()
        .read_line(&mut nombre)
        .expect("Error al leer la entrada del usuario");

A continuación, la línea .read_line(&mut nombre) llama al método read_line en el controlador de entrada estándar para obtener la entrada del usuario. También pasamos &mut nombre como argumento a read_line para indicarle en qué cadena almacenar la entrada del usuario.

La función read_line tiene la tarea de tomar lo que el usuario escribe en la entrada estándar y agregarlo a una cadena (sin sobrescribir su contenido), por lo que pasamos esa cadena como argumento. El argumento de la cadena necesita ser mutable para que el método pueda cambiar el contenido de la cadena.

El símbolo & indica que este argumento es una referencia (Sí!, como en C/C++), lo cual brinda una forma de permitir que varias partes de tu código accedan a una misma pieza de datos sin necesidad de copiar esos datos en memoria múltiples veces.

Nota: Las referencias son una característica compleja, y una de las principales ventajas de Rust es lo seguras y fáciles de usar que son las referencias.

read_line coloca lo que el usuario ingresa en la cadena que le pasamos, pero también devuelve un valor de tipo Result. Result es una enumeración, que es un tipo que puede estar en uno de varios estados posibles (cada estado posible, una variante). El propósito de estos tipos Result es codificar información sobre el manejo de errores.

Las variantes de Result son Ok y Err. La variante Ok indica que la operación fue exitosa y dentro de Ok se encuentra el valor generado exitosamente. La variante Err significa que la operación falló y Err contiene información sobre cómo o por qué falló la operación.

Los valores del tipo Result, tienen métodos definidos en ellos. Una instancia de Result tiene un método expect. Si esta instancia de Result es un valor Err, expect hará que el programa se bloquee y mostrará el mensaje que pasaste como argumento a expect.

Ejecute el programa utilizando el comando cargo run.

Referencias

  • The Rust Programming Language. 2nd Edition by Steve Klabnik and Carol Nichols, with contributions from the Rust Community. 2023

Did you find this article valuable?

Support Jesse Padilla by becoming a sponsor. Any amount is appreciated!