Converter String para Número em Rust

Aprenda como converter String para número em Rust usando parse(), from_str() e tratamento de erros. Exemplos completos com i32, f64 e mais.

Converter String para Número em Rust

Converter uma String (ou &str) para um tipo numérico é uma das operações mais comuns em Rust. O método parse() é a forma principal de fazer essa conversão, e funciona com qualquer tipo que implemente o trait FromStr.

Conversão básica com parse()

O jeito mais direto de converter uma string para número é usando o método parse() com anotação de tipo:

fn main() {
    // String para i32
    let numero: i32 = "42".parse().unwrap();
    println!("i32: {}", numero);

    // String para f64
    let decimal: f64 = "3.14".parse().unwrap();
    println!("f64: {}", decimal);

    // String para u64
    let grande: u64 = "18446744073709551615".parse().unwrap();
    println!("u64: {}", grande);

    // Usando turbofish syntax (alternativa à anotação de tipo)
    let valor = "100".parse::<i64>().unwrap();
    println!("i64 (turbofish): {}", valor);
}

Saída:

i32: 42
f64: 3.14
u64: 18446744073709551615
i64 (turbofish): 100

Tratamento de erros com Result

Na prática, nunca use unwrap() em código de produção. O método parse() retorna um Result que você deve tratar corretamente:

fn main() {
    // Usando match
    let entrada = "abc";
    match entrada.parse::<i32>() {
        Ok(numero) => println!("Convertido: {}", numero),
        Err(e) => println!("Erro ao converter '{}': {}", entrada, e),
    }

    // Usando if let
    let entrada = "256";
    if let Ok(numero) = entrada.parse::<u8>() {
        println!("u8: {}", numero);
    } else {
        println!("'{}' não cabe em u8 (0-255)", entrada);
    }

    // Usando unwrap_or para valor padrão
    let valor: i32 = "não_é_número".parse().unwrap_or(0);
    println!("Com padrão: {}", valor);

    // Usando unwrap_or_else para cálculo do padrão
    let valor: f64 = "inválido".parse().unwrap_or_else(|_| {
        eprintln!("Aviso: usando valor padrão 1.0");
        1.0
    });
    println!("Com padrão calculado: {}", valor);
}

Saída:

Erro ao converter 'abc': invalid digit found in string
'256' não cabe em u8 (0-255)
Com padrão: 0
Aviso: usando valor padrão 1.0
Com padrão calculado: 1.0

Usando FromStr diretamente

O trait std::str::FromStr é o que permite que parse() funcione. Você pode usá-lo diretamente e até implementá-lo para seus próprios tipos:

use std::str::FromStr;

#[derive(Debug)]
struct Ponto {
    x: f64,
    y: f64,
}

impl FromStr for Ponto {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let partes: Vec<&str> = s.split(',').collect();
        if partes.len() != 2 {
            return Err(format!("Esperado 'x,y', recebido: '{}'", s));
        }
        let x = partes[0].trim().parse::<f64>()
            .map_err(|e| format!("Erro no x: {}", e))?;
        let y = partes[1].trim().parse::<f64>()
            .map_err(|e| format!("Erro no y: {}", e))?;
        Ok(Ponto { x, y })
    }
}

fn main() {
    // FromStr direto
    let numero = i32::from_str("42").unwrap();
    println!("FromStr direto: {}", numero);

    // Tipo personalizado
    let ponto: Ponto = "3.5, 7.2".parse().unwrap();
    println!("Ponto: {:?}", ponto);

    // Tratando erro no tipo personalizado
    match "invalido".parse::<Ponto>() {
        Ok(p) => println!("Ponto: {:?}", p),
        Err(e) => println!("Erro: {}", e),
    }
}

Saída:

FromStr direto: 42
Ponto: Ponto { x: 3.5, y: 7.2 }
Erro: Esperado 'x,y', recebido: 'invalido'

Converter com espaços e caracteres extras

Strings do mundo real frequentemente têm espaços em branco ou formatação. Use trim() antes de converter:

fn main() {
    // trim() remove espaços antes e depois
    let entrada = "  42  \n";
    let numero: i32 = entrada.trim().parse().unwrap();
    println!("Trimmed: {}", numero);

    // Remover separadores de milhar
    let com_separador = "1.000.000";
    let limpo = com_separador.replace('.', "");
    let numero: i64 = limpo.parse().unwrap();
    println!("Sem separador: {}", numero);

    // Converter vários números de uma string
    let texto = "10 20 30 40 50";
    let numeros: Vec<i32> = texto
        .split_whitespace()
        .filter_map(|s| s.parse().ok())
        .collect();
    println!("Vetor: {:?}", numeros);
}

Saída:

Trimmed: 42
Sem separador: 1000000
Vetor: [10, 20, 30, 40, 50]

Tabela de referência rápida

ConversãoCódigo
&stri32"42".parse::<i32>().unwrap()
Stringf64s.parse::<f64>().unwrap()
&stru8"255".parse::<u8>().unwrap()
Com padrãos.parse::<i32>().unwrap_or(0)
FromStri32::from_str("42").unwrap()

Veja também