本文主要是介绍rust中slice panicked at 'byte index 5 is not a char boundary' 问题解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今天在工作中遇到一个问题,string调用truncate()接口panic了,报错信息大致如下:thread '0' panicked at 'assertion failed: self.is_char_boundary(new_len)', liballoc/string.rs:1121:13
我的代码如下:
示例1:
fn main() {let mut s = String::from("hello 中国");s.truncate(7); //获取前7个字节println!("s:{}", s);
}------------------------------------------------------------------------Compiling playground v0.0.1 (/playground)Finished dev [unoptimized + debuginfo] target(s) in 0.61sRunning `target/debug/playground`
thread 'main' panicked at 'assertion failed: self.is_char_boundary(new_len)', src/liballoc/string.rs:1123:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
当然原始代码不是这个,但是原理是一样的。这里的问题出现在字符串中的中文(纯英文字符不会出现panic)。原因是,一个汉字所在字节数为非1 byte,当去截取slice的中字符时,字符边界判断导致panic了。
一开始怀疑是truncate()接口的问题,但后来发现并不是truncate本身的问题,所有涉及到slice中截取中文字符都会容易导致panic,不信看下面例子:
示例2:
fn main() {let a = "abcd早";let b = &a[..5];println!("b={}", b);
}-------------------------------------------------------------------------Compiling playground v0.0.1 (/playground)Finished dev [unoptimized + debuginfo] target(s) in 0.51sRunning `target/debug/playground`
thread 'main' panicked at 'byte index 5 is not a char boundary; it is inside '早' (bytes 4..7) of `abcd早`', src/libcore/str/mod.rs:2027:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
再看如下例子:
示例3:
fn main() {let a = "abcd早";let b = &a[..3];println!("b={}", b);
}--------------------------------------------------------------
输出结果:
b=abc
示例4:
fn main() {let a = "abcd早";let b = &a[..7];println!("b={}", b);
}-------------------------------------------------------------
输出结果:
b=abcd早
示例3与示例2的区别在于,截取的字节数不同。示例3截取前3个字符均是英文,而示例4正好截取到了中文“早”字的字符边界(“早”字占4个字节)。
那么实际生产环境中很难保证我们要截取的slice中没有中文字符,任意截取不能保证正好是字符边界,那该怎么办?
网上有人提到先把slice转换为chars的vector,然后再调用truncate()之类的,但是觉得这样太消耗性能,所以我得方法是:
// 首先判断给出的index是不是字符边界,否则向后找到字符边界所在位置
fn find_char_boundary(s: &str, index: usize) -> usize {if s.len() <= index {return index;}let mut new_index = index;while !s.is_char_boundary(new_index) {new_index += 1;}new_index
}fn main() {let mut s = String::from("hello 中国");let idx = find_char_boundary(&s, 7); //实际获取到的idx=9s.truncate(idx);println!("idx:{}, s:{}", idx, s);
}-------------------------------------------------------------------
输出结果:
idx:9, s:hello 中
好了,以上就是对自己在rust编程中遇到的问题,做一个总结与备忘,希望对有需要的人也能够有所帮助!
这篇关于rust中slice panicked at 'byte index 5 is not a char boundary' 问题解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!