3 votes

Quelle est la manière idiomatique en Rust de formater une valeur en plusieurs types de chaînes de caractères ?

J'ai la latitude en degrés sous forme de f64 et je dois le convertir en un String . Au début, j'ai pensé à mettre en œuvre Display comme ceci :

struct Latitude(f64);

impl fmt::Display for Latitude {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", if self.0 > 0. { "N" } else { "S" }, self.0)
    }
}

fn main() {
    let lat: f64 = 45.;
    println!("{}", Latitude(lat));
}

Après cela, j'ai des exigences supplémentaires. J'ai besoin de convertir en une des deux représentations :

  1. N 70.152351
  2. N 70° 09' 08"

Il y a également un drapeau supplémentaire ; lorsqu'il est false j'ai besoin de quelque chose comme :

  1. - --.------
  2. - --° -' -"

La manière la plus simple de mettre cela en œuvre sera :

fn format_lat(degree: f64, use_min_sec_variant: bool, is_valid: bool) -> String;

Cependant, je ne vois pas de fonctions libres dans la bibliothèque standard de Rust.

Je devrais peut-être utiliser struct Latitude(f64) et mettre en œuvre un to_string méthode ? Ou peut-être devrais-je implémenter un autre trait ?

5voto

Shepmaster Points 1732

Vous pouvez créer des types enveloppants avec différents types de formatage et les renvoyer en tant que méthode :

struct Latitude(f64);
struct MinutesSeconds(f64);

impl Latitude {
    fn minutes_seconds(&self) -> MinutesSeconds {
        MinutesSeconds(self.0)
    }
}

impl fmt::Display for MinutesSeconds {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "latitude in a different format")
    }
}

C'est la même idée que Path::display .

En ce qui concerne le concept de validité / invalidité, il semble que vous vouliez vraiment un système de contrôle de la qualité. struct Latitude(Option<f64>) et ensuite fournir None lorsqu'il n'est pas valide.

4voto

dpc.ucore.info Points 2764

En gros, vous êtes libre de faire ce que vous voulez. Sans plus de contexte sur vos objectifs, toute méthode me semble suffisante.

Personnellement, je le ferais comme :

struct Latitude(f64);

impl Latitutde {
    pub fn format_as_x(&self, f: &mut fmt::Formatter) -> fmt::Result<(), Error> {}

    pub fn format_as_y(&self, f: &mut fmt::Formatter) -> fmt::Result<(), Error> {}
}

plus un Display trait + to_format_x() -> String fonctions de commodité.

format_as_y sont la meilleure méthode de l'OMI car ils gèrent les erreurs, peuvent prendre n'importe quel formateur et ne nécessitent pas d'allouer un fichier String pour revenir.

Au fait, prendre bool est généralement un anti-modèle : le piège booléen.

2voto

nabijaczleweli Points 33

Puede impl Latitude si vous avez besoin de passer des arguments ou impl ToString for Latitude si vous ne le faites pas :

use std::string::ToString;

struct Latitude(f64);

// If you need parameterisation on your conversion function
impl Latitude {
    // You'd probably use a better-suited name
    pub fn to_string_parameterised(&self, use_min_sec_variant: bool) -> String {
        // Conversion code
        format!("{} {}", self.0, use_min_sec_variant)
    }
}

// If you don't need parameterisation and want to play nicely with 100% of all code elsewhere
impl ToString for Latitude {
    fn to_string(&self) -> String {
        // Conversion code
        format!("{}", self.0)
    }
}

fn main() {
    let lat = Latitude(45.0);
    println!("{}", lat.to_string_parameterised(false));
    println!("{}", lat.to_string());
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X