Strings en Rust
El manejo de texto es uno de los primeros puntos en los que Rust se siente distinto a otros lenguajes, sobre todo porque tiene dos tipos de cadena de texto. En cuanto entiendes por qué, deja de ser confuso.
&str vs String
Sección titulada «&str vs String»&str(string slice, una porción de cadena): texto que ya existe en algún sitio, normalmente escrito directamente en tu código. Tiene un tamaño fijo y no puede crecer.String: un texto propio que puede crecer. Puedes añadirle cosas, y vive en el heap (el montículo de memoria).
fn main() { let literal: &str = "hola"; // un string slice let owned: String = String::from("hola"); // un String propio
println!("{literal} / {owned}");}Una regla práctica sencilla: si solo vas a imprimir un texto fijo, "así" (un &str) te sirve. Si necesitas construir, ampliar o modificar texto mientras el programa se ejecuta, usa String.
Hacer crecer un String
Sección titulada «Hacer crecer un String»fn main() { let mut greeting = String::from("¡Hola"); greeting.push_str(", mundo"); // añade un &str greeting.push('!'); // añade un solo char
println!("{greeting}");}Salida:
¡Hola, mundo!Combinar cadenas
Sección titulada «Combinar cadenas»Puedes unir cadenas con +, o usar format! (que suele ser la opción más clara):
fn main() { let first = String::from("¡Hola, "); let second = String::from("mundo!");
let combined = first + &second; // fíjate en el & delante de second println!("{combined}");
// format! suele leerse mejor: let name = "Ferris"; let greeting = format!("¡Hola, {name}!"); println!("{greeting}");}Métodos de cadena útiles
Sección titulada «Métodos de cadena útiles»Unos cuantos que usarás todo el tiempo. En este ejemplo dejamos el texto en inglés a propósito: la longitud se mide en bytes, y las letras con tilde ocupan más de un byte, así que el resultado cambiaría.
fn main() { let text = " Hello, Rust! ";
println!("{}", text.trim()); // "Hello, Rust!" (sin espacios alrededor) println!("{}", text.to_uppercase()); // " HELLO, RUST! " println!("{}", text.to_lowercase()); // " hello, rust! " println!("{}", text.contains("Rust")); // true println!("{}", text.trim().len()); // 12 (longitud en bytes) println!("{}", text.trim().replace("Rust", "World")); // "Hello, World!"}Recorrer una cadena
Sección titulada «Recorrer una cadena»Para ir carácter por carácter, usa .chars():
fn main() { for c in "abc".chars() { println!("{c}"); }}Práctica
Sección titulada «Práctica»1. Limpia una entrada desordenada
Sección titulada «1. Limpia una entrada desordenada»Alguien escribió " rUsT is FUN " en un formulario. Conviértelo en rust is great: quita los espacios de más, pásalo todo a minúsculas y reemplaza fun por great. Luego imprime el resultado y su longitud. Pista: los métodos de cadena se pueden encadenar, uno detrás de otro: text.trim().to_lowercase()....
Dejamos este texto en inglés a propósito: el programa imprime la longitud en bytes, y con letras acentuadas el número cambiaría.
Ver solución
fn main() { let input = " rUsT is FUN ";
// primero trim, luego minúsculas, luego reemplazar "fun" (ya en minúsculas) let clean = input.trim().to_lowercase().replace("fun", "great");
println!("{clean}"); println!("{} bytes", clean.len());}Salida:
rust is great13 bytesEl orden importa: si llamaras a .replace("fun", "great") antes de .to_lowercase(), no se reemplazaría nada, porque el texto todavía dice FUN.
2. Crea una dirección de correo
Sección titulada «2. Crea una dirección de correo»Con first = "Ada" y last = "Lovelace", construye el String [email protected] e imprímelo. Luego imprime si contiene una @. Pista: format! acepta expresiones como first.to_lowercase() como argumentos para sus huecos {}.
Ver solución
fn main() { let first = "Ada"; let last = "Lovelace";
let email = format!("{}.{}@example.com", first.to_lowercase(), last.to_lowercase());
println!("{email}"); println!("parece válido: {}", email.contains('@'));}Salida:
parece válido: trueResumen
Sección titulada «Resumen»&stres texto prestado y fijo;Stringes propio y puede crecer.- Haz crecer un
Stringcon.push_str()(para texto) o.push()(para un solo carácter). - Al combinar cadenas, prefiere
format!antes que+: es más claro y no mueve nada. - Métodos habituales:
.trim(),.to_uppercase(),.contains(),.replace(),.chars().
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. ¿Qué tipo de cadena es propio y puede crecer mientras se ejecuta el programa?
2. ¿Por qué esta página prefiere format! antes que + para combinar más de una o dos cadenas?
3. ¿Por qué no puedes acceder a una cadena de Rust con un índice como text[0]?
4. ¿Qué método añade un solo carácter a un String, como en greeting.push('!')?
Puntuación: 0 / 4
Para leer más
Sección titulada «Para leer más»- Storing UTF-8 Encoded Text with Strings: The Rust Book (en inglés): el capítulo oficial sobre
String, incluido por qué no puedes acceder por posición. - String Slices: The Rust Book (en inglés): qué es en realidad un
&str, una vez que hayas aprendido el borrowing (préstamo). - Strings: Rust by Example (en inglés): ejemplos ejecutables de
Stringy&str, además de caracteres de escape y raw strings (cadenas sin escapes). String: documentación de la biblioteca estándar (en inglés): todos los métodos de unStringpropio, cada uno con un pequeño ejemplo.str: documentación de la biblioteca estándar (en inglés): métodos comotrim,contains,replaceysplit, que funcionan con cualquier texto.