Dmi*_*try 4 integer-overflow unsigned-integer rust
0 .. v.len() - 1
当向量v
可能为空时,正确的循环方法是什么?
考虑以下代码,它打印向量中 2 个元素的所有选择[5, 6, 7]
:
fn main() {
let v: Vec<i32> = vec![5, 6, 7];
for i in 0 .. v.len() - 1 {
for j in i + 1 .. v.len() {
println!("{} {}", v[i], v[j]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
它打印
5 6
5 7
6 7
Run Code Online (Sandbox Code Playgroud)
正如预期的那样。
现在,如果我们有
let v: Vec<i32> = vec![];
Run Code Online (Sandbox Code Playgroud)
那么程序就会因为溢出而出现恐慌,这也是意料之中的。
问:如何在不改变程序结构和逻辑、不涉及有符号整数的情况下修复它?
以下是我不想要的解决方法的一些示例:
单独处理空v
(改变逻辑)。总的来说,我不想要任何v
空支票,例如if v.len() == 0 { 0 } else { v.len() - 1 }
更改循环顺序(更改逻辑和输出):
for j in 0 .. v.len() {
for i in 0 .. j {
Run Code Online (Sandbox Code Playgroud)
移动索引(改变逻辑):
for i in 1 .. v.len() {
for j in i .. v.len() {
// Now i is shifted by 1
Run Code Online (Sandbox Code Playgroud)
使用 i32(强制转换):
for i in 0 .. v.len() as i32 - 1 {
for j in i + 1 .. v.len() as i32 {
// cast i and j to usize
Run Code Online (Sandbox Code Playgroud)
总的来说,我希望有一种干净的方式来处理0 .. v.len() - 1
而不需要任何黑客攻击。
请注意, if i == v.len()-1
,外循环体内没有任何反应,因为i+1..v.len()
是一个空迭代器。因此,避免整数下溢的最简单方法就是删除-1
:
fn main() {
let v: Vec<i32> = vec![5, 6, 7];
for i in 0 .. v.len() {
for j in i + 1 .. v.len() {
println!("{} {}", v[i], v[j]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
产生
5 6
5 7
6 7
Run Code Online (Sandbox Code Playgroud)
如果我替换v
为Vec::new()
,您将不会得到任何输出,如预期的那样。