Ir al contenido

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 (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}");
}
▶ Pruébalo tú mismo

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.

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!
▶ Pruébalo tú mismo

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}");
}
▶ Pruébalo tú mismo

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!"
}
▶ Pruébalo tú mismo

Para ir carácter por carácter, usa .chars():

fn main() {
for c in "abc".chars() {
println!("{c}");
}
}
▶ Pruébalo tú mismo

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 great
13 bytes
▶ Pruébalo tú mismo

El orden importa: si llamaras a .replace("fun", "great") antes de .to_lowercase(), no se reemplazaría nada, porque el texto todavía dice FUN.

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: true
▶ Pruébalo tú mismo
  • &str es texto prestado y fijo; String es propio y puede crecer.
  • Haz crecer un String con .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 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