只是在弄亂終端界面的一些圖形時彈出此錯誤...
thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside '?' (bytes 1..4) of ??▓█', src/main.rs:38:6
我可以不使用這些字符,還是需要使用一些魔法來支持我認為的默認 ASCII 字符?
(這里是那些想知道的相關代碼。)
// Example call with the same parameters that led to this issue.
charlist(" ??▓█".to_string(), 0.66);
// Returns the n-th character in a string.
// (Where N is a float value from 0 to 1,
// 0 being the start of the string and 1 the end.)
fn charlist<'a>(chars: &'a String, amount: f64) -> &'a str {
let chl: f64 = chars.chars().count() as f64; // Length of the string
let chpos = -((amount*chl)%chl) as i32; // Scalar converted to integer position in the string
&chars[chpos as usize..chpos as usize 1] // Slice the single requested character
}
uj5u.com熱心網友回復:
您似乎有幾個誤解。因此,讓我按順序解決它們。
?,?,▓和█不是 ASCII 字符!它們是 unicode 代碼點。您可以通過以下簡單的實驗來確定這一點。
fn main() {
let slice = " ??▓█";
for c in slice.chars() {
println!("{}, {}", c, c.len_utf8());
}
}
此代碼有輸出:
, 1
?, 3
?, 3
▓, 3
█, 3
正如你所看到的,這個“四四方方”的字符每個長度為 3 個位元組!Rust 對它的所有字串都使用 utf-8 編碼。這導致了另一個誤解。
在這一行
&chars[chpos as usize..chpos as usize 1]中,您試圖獲得長度為一個位元組的切片。rust 中的字串切片以位元組為索引。但是你試圖在一個字符的中間切片(它的長度為 3 個位元組)。一般來說,utf-8 編碼中的字符長度可以是一到四個位元組。要獲取 char 的位元組長度,您可以使用 methodlen_utf8。您可以使用 method 獲取字串切片中的字符迭代器
chars。然后獲取第 n 個字符就像使用迭代器方法一樣簡單nth所以以下是正確的:
assert_eq!(" ??▓█".chars().nth(3).unwrap(), '?');
如果您還想擁有此字符的索引,則可以使用 method char_indices。
使用
f64值來表示第 n 個字符很奇怪,如果你真的想這樣做,我會鼓勵你重新考慮。但如果你這樣做,你有兩個選擇。您必須記住,由于字符具有可變長度,因此 string 的 slice 方法len不會回傳字符數,而是 slice 的位元組長度。要知道字串中有多少個字符,除了迭代它之外別無選擇。因此,例如,如果您想擁有一個中間角色,您必須首先知道有多少個。我可以想到兩種方法可以做到這一點。您可以為
Vec<char>(或類似的東西)收集字符。然后你就會知道有多少個字符,并且可以在O(1)第 n 個索引中。但是,這將導致額外的記憶體分配。你可以先數一下有多少個字符
slice.chars().len()。然后計算第 n 個的位置,并通過再次迭代字符并獲得第 n 個來獲得它(如上所示)。這不會導致任何額外的記憶體分配,但它的復雜性為O(2n),因為您必須對整個字串進行兩次迭代。
你選擇哪一個取決于你。你將不得不做出妥協。
- 這并不是一個真正的正確性問題,但更喜歡在函式的引數中使用
&strover (因為它會為您的呼叫者提供更多的靈活性)。&String如果引數中只有一個參考,而另一個參考在回傳的型別中,則不必指定生命周期。Rust 會推斷它們必須具有相同的生命周期。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/516515.html
標籤:细绳锈
