У меня есть функция, которая создает строку на основе значений u8 в массиве. Если u8 равен 0 или 10, я нажимаю определенный символ. В противном случае я хочу нажать на сам номер. Моя проблема в том, что когда я печатаю результат этой функции, я получаю экранированные числа. Вот код:
fn convert_result_to_string(guess_result: &[u8; SEQ_LEN]) -> String {
let mut output = String::new();
for (i, num) in guess_result.iter().enumerate() {
if *num == 0 {
output.push_str("*");
}
else if *num == 10 {
output.push_str("$");
}
else {
output.push(*num as char);
}
if i < SEQ_LEN-1 {
output.push(' ');
}
}
output
}
Позже, когда я позвоню в
let test = [0, 5, 6, 10, 7];
let o = convert_result_to_string(&test);
println!("o: {:?}", o);
Я получаю следующий результат:
o: "* \u{5} \u{6} $ \u{7}"
Почему 5, 6 и 7 сбежали?
Вы не можете просто преобразовать u8
в char
и ожидать, что результат отобразит цифру. Цифры 0–9 представлены кодовыми точками ASCII (и Unicode) 48–57. Кодовые точки ASCII 0–9 состоят из нулевого символа, пробелов и управляющих символов, которые больше не используются широко.
Эти символы экранируются, поскольку вы используете форматирование отладки ({:?}
) для отображения строки, а кодовые точки ASCII 5, 6 и 7 обычно отображаются как поля-заполнители или невидимы, в зависимости от используемого шрифта или эмулятора терминала. Таким образом, при форматировании с использованием отладочного форматирования Rust показывает вам, что вам нужно будет вставить в исходный код Rust, чтобы получить эквивалентную строку в удобочитаемой форме, которая не зависит от того, как шрифт или эмулятор терминала представляют эти символы. При этом используется escape-последовательность Юникода \u
Rust для встраивания этих непоследовательно отображаемых символов в строку.
В вашем случае вы, вероятно, ищете char::from_digit().
output.push(char::from_digit((*num).into(), 10).expect("digit must be in the range 0-9"));
Обратите внимание, что приведенный выше код вызовет панику, если значение *num
не находится в диапазоне от 0 до 9 (включительно). Подумайте о том, чтобы сделать что-то вроде этого, что также будет обрабатывать многозначные десятичные числа:
write!(output, "{num}").unwrap();
Он также намного короче и не может подвести. (реализация String
std::fmt::Write
безошибочна.)
Обратите внимание, что для этого вам потребуется use std::fmt::Write;
в вашем модуле/функции.
Я не знаю Rust, но учтите, что символ 5 (Ctrl-E) — это не то же самое, что
'5'
(цифра 5, код ASCII/Unicode 53).