Biketire
Biketire

Reputation: 2069

How can I convert a usize to a single char?

For an exercise I'm doing for Exercism (the minesweeper task), I need to convert an usize to a char in order to insert it into a std::string::String.

To describe the problem in minimal lines of code:

let mut s = String::from("   ");
let mine_count: usize = 5; // This is returned from a method and will be a value between 1 and 8.
s.insert(0, _______); // So I get: "5  " at the underscores I do:

The way I'm currently doing this as:

 mine_count.to_string().chars().nth(0).unwrap(); // For example: '2'

Or see the full example in the Rust playground. Somehow this doesn't strike me as elegant.

I've also tried:

 mine_count as char; // Where mine_count is of type u8

However, when adding mine_count to a std::string::String, it turns up as - for example - \u{2} and not simply '2':

let mine_count: u8 = 8;
s.insert(0, mine_count as char);
println!("{:?}", s);

The output:

"\u{8}   "

Reproduced here.

Are there other ways to achieve the goal of converting an integer in the range of 1..8 to a single character (char)?

Upvotes: 5

Views: 14201

Answers (4)

Gabriel soft
Gabriel soft

Reputation: 563

Let’s do it this way:

let data = 10;
let result = char::from_digit(data as u32, 10);

println!("{}", result); // Using the println! macro from the standard library

Upvotes: -1

E_net4
E_net4

Reputation: 29972

However when adding mine_count to a std::string::String it turns up as - for example - \u{2} and not simply '2'.

This is the difference between the char containing the scalar value 2 and a char containing the actual character '2'. The first few UTF-8 values, like in ASCII text encoding, are reserved for control characters, and do not portray something visible. What made it appear as \u{2} in this context is because you printed the string with debug formatting ({:?}). If you try to print the same string with plain formatting:

let mut s = String::from("   ");
let mine_count: u8 = 8;
s.insert(0, mine_count as char);
println!("{}", s);

The output will contain something that wasn't meant to be printed, and so might either show a placeholder character or not appear at all (reproducible here).

In order to represent a single-digit number as the respective character: (1) First make sure that mine_count is within the intended limits, either by recoverable errors or hard assertions. (2) Then, transform the number by translating it to the numeric digit character domain.

assert!(mine_count > 0);
assert!(mine_count < 9);
let mine_char = (mine_count + b'0') as char;
s.insert(0, mine_char);
println!("{}", s);

Playground

Upvotes: 7

ljedrz
ljedrz

Reputation: 22163

I suggest using char::from_digit together with a cast necessary to use it (as u32):

use std::char;

fn main() {
    let mut s = String::from("   ");
    let mine_count: u8 = 8; // or i8 or usize
    s.insert(0, char::from_digit(mine_count as u32, 10).unwrap());

    println!("{:?}", s);
}

Upvotes: 12

Shepmaster
Shepmaster

Reputation: 430466

Are there other ways to achieve the goal of converting an integer in the range of 1..8 to a single character

Use a lookup table:

const LABELS: [char; 9] = ['0', '1', '2', '3', '4', '5', '6', '7', '8'];

fn main() {
    LABELS[6_usize];
}

Upvotes: 4

Related Questions