web-dev-qa-db-fra.com

Comment convertir un caractère en entier pour que "1" devienne 1?

J'essaie de trouver la somme de tous les chiffres d'un nombre donné, comme 134 donne 8.

Mon plan consiste à parcourir le nombre en le convertissant en string à l'aide de .to_string(), puis à utiliser .chars() pour effectuer une itération sur le nombre. Ensuite, je veux convertir chaque char de l'itération en un integer et l'ajouter à une variable. Je veux obtenir la valeur finale de cette variable.

J'ai essayé d'utiliser le code ci-dessous pour convertir une char en une integer ( Playground ):

fn main() {
    let x = "123";
    for y in x.chars() {
        let z = y.parse::<i32>().unwrap();
        println!("{}", z + 1);
    }
}

Mais il en résulte cette erreur:

error: no method named `parse` found for type `char` in the current scope
 --> <anon>:4:19
  |
4 |         let z = y.parse::<i32>().unwrap();
  |                   ^^^^^

Comment puis-je convertir une char en un entier?

Le code ci-dessous fait exactement ce que je veux faire ( Playground ):

fn main() {
     let mut sum = 0;
     let x = 123;
     let x = x.to_string();
     for y in x.chars() {
        // converting `y` to string and then to integer
        let z = (y.to_string()).parse::<i32>().unwrap();
        // incrementing `sum` by `z`
        sum += z;
    }
    println!("{}", sum);
}

mais je dois d’abord convertir char en chaîne, puis en entier pour incrémenter sum de z. Existe-t-il un moyen de convertir directement char en entier?

7
ritiek

La méthode dont vous avez besoin est char::to_digit . Il convertit char en un nombre qu'il représente dans la base donnée. 

Vous pouvez également utiliser Iterator::sum pour calculer facilement la somme d’une séquence:

fn main() {
    const RADIX: u32 = 10;
    let x = "134";
    println!("{}", x.chars().map(|c| c.to_digit(RADIX).unwrap()).sum::<u32>());
}
9
Pavel Strakhov
my_char as u32 - '0' as u32

Maintenant, il reste encore beaucoup à apprendre sur cette réponse. 

Cela fonctionne parce que les codages ASCII (et donc UTF-8) ont les chiffres arabes 0 à 9 classés par ordre croissant. Vous pouvez obtenir les valeurs scalaires et les soustraire.

Cependant, que doit-il faire pour les valeurs en dehors cette plage? Que se passe-t-il si vous fournissez 'p'? Il retourne 64. Qu'en est-il de '.'? Cela va paniquer. Et '♥' retournera 9781. 

Les chaînes ne sont pas que des sacs d'octets. Ils sont encodés en UTF-8 et vous ne pouvez pas simplement ignorer ce fait. Chaque char peut contenir n'importe quelle valeur scalaire Unicode.

C'est pourquoi les chaînes ne sont pas la bonne abstraction du problème.

Du point de vue de l'efficacité, l'attribution d'une chaîne semble inefficace. Rosetta Code a un exemple d'utilisation d'un itérateur qui ne fait que des opérations numériques:

struct DigitIter(usize, usize);

impl Iterator for DigitIter {
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {
        if self.0 == 0 {
            None
        } else {
            let ret = self.0 % self.1;
            self.0 /= self.1;
            Some(ret)
        }
    }
}

fn main() {
    println!("{}", DigitIter(1234, 10).sum::<usize>());
}
1
Shepmaster

Une autre méthode consiste à parcourir les caractères de votre chaîne, à les convertir et à les ajouter à l'aide de fold.

fn sum_of_string(s: &str) -> u32 {
  s.chars().fold(0, |acc, c| c.to_digit(10).unwrap_or(0) + acc)
}

fn main() {
    let x = "123";
    println!("{}", sum_of_string(x));
}
0
manonthemat