panicked
今天在工作中遇到一个问题,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.61s
Running `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.51s
Running `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=9
s.truncate(idx);
println!("idx:{}, s:{}", idx, s);
}
-------------------------------------------------------------------
输出结果:
idx:9, s:hello 中
好了,以上就是对自己在rust编程中遇到的问题,做一个总结与备忘,希望对有需要的人也能够有所帮助!
相关阅读
patindex(pattern,expression) 精确匹配 完全匹配返回1,不完全匹配返回0 patindex('aa','aa') 返回1patindex('aa','aabb')
晚上有时间,继续再写一点,我们来讲一下关于select表单的所有操作,在项目中还是有很多地方需要用到的。 讲select之前先讲一下index()的
java.lang.StringIndexOutOfBoundsException: String
字符串截取下标越界 出错代码 @GetMapping("/edit") //@RequiresPermissions("erp:enquirySheet:edit") public String
mybatis Parameter index out of range (1 > number o
今天遇到了一个有意思的问题,看错误信息提示,好像是有个参数没有匹配上,具体错误信息如下: ### SQL: SELECT count(*) FROM (SELECT