String 带范围的算术运算顺序问题
我正试图通过铁锈书和Exercism.io网站学习铁锈。 我对你有意见。代码如下:String 带范围的算术运算顺序问题,string,rust,range,String,Rust,Range,我正试图通过铁锈书和Exercism.io网站学习铁锈。 我对你有意见。代码如下: pub fn series(_digits: &str, _len: usize) -> Vec<String> { (0.._digits.len() + 1 - _len) .map(|i| _digits[i..i + _len].to_string()) .collect() } 我很惊讶,因为它看起来对我来说是一样的。为什么会失败?发生
pub fn series(_digits: &str, _len: usize) -> Vec<String> {
(0.._digits.len() + 1 - _len)
.map(|i| _digits[i..i + _len].to_string())
.collect()
}
我很惊讶,因为它看起来对我来说是一样的。为什么会失败?发生这种情况是因为在调试模式下,会溢出的算术运算会死机,而死机会导致测试失败 对于重新排列的版本(),在
系列(“12345”,6)
中,数字.len()-len+1
变为5usize-6usize+1usize
。程序甚至不能到达+1
,因为5usize-6usize
会恐慌。(usize
不能表示负数,因此从5
中减去6
会导致溢出。)
错误消息包含故障性质的强烈提示:
——测试太长标准输出----
线程“test_too_long”在“尝试使用溢出进行减法”时惊慌失措,src/lib.rs:2:9
注意:使用'RUST_BACKTRACE=1'运行回溯跟踪。
然而,digits.len()+1-len
可以工作,因为6
正好比字符串长度多一个,因此5+1-6
可以计算为零而不会溢出。但是如果您更改test\u太长
而调用series(“12345”,7)
,两个版本都会死机。这似乎是编写测试套件的人的疏忽,特别是考虑到指令没有指定预期的行为:
如果你要求从一个5位数的字符串中得到一个6位数的序列,你应该得到你所得到的一切
值得一提的是,这里有一种方法可以使
系列
为大于输入长度的任何len
返回一个空向量:(digits.len()+1)。饱和_sub(len)
类似于digits.len()+1-len
,但如果减法的结果小于0
,它只返回0
检查错误消息。它说的不仅仅是测试失败。你是对的,我没有检查,这帮助我理解了这个问题。这是“尝试使用溢出进行减法”x)不要在变量名前面加下划线(uuu
)。这表示该变量未使用,但对您的两个变量都不适用。请注意,如果您使用&[u8]
而不是字符串类型,代码将变得容易得多。您的系列
函数将变成digits.windows(len.collect()
。
#[test]
#[ignore]
fn test_too_long() {
let expected: Vec<String> = vec![];
assert_eq!(series("92017", 6), expected);
}