rust 循环在环绕“if”语句或函数时停止按预期工作

3zwtqj6y  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(83)

我对Rust和一般的编程都是新手。我正在尝试创建一个非常简单的猜数字游戏在命令行中.
目前,用户必须给出一个范围来猜测,但我也想给出一个默认选项。以前我有这个函数只是要求范围。
下面是尝试给出默认范围选项的情况。

fn get_range() -> Vec<i32> {
    println!("Press C for custom range or any key for default range");
    println!("Custom range");
    println!("Default range [0,10]");

    for line in stdin().lock().lines() {
        if line.unwrap().to_lowercase() == "c" {
            loop {
                let range_start: i32 = {
                    println!("\nStart of range:");
                    get_user_number().unwrap()
                };
                let range_end: i32 = {
                    println!("\nEnd of range (end is inclusive):");
                    get_user_number().unwrap()
                };

                if range_start < range_end {
                    return (range_start..=range_end).collect();
                } else {
                    println!("\nThe start of the range must be a lower number than the end!")
                }
            }
        } else {
            return (0..=10).collect();
        }
    }

    (0..=10).collect()
}

然而,由于某种原因,请求自定义范围的循环一旦在if语句中就停止正常工作,我也试图 Package 在函数中,但也不起作用。结果是它打印了Start of range,然后就停在那里了,之后什么都不工作了。
其他问题:
1.如果我删除函数(0..=10).collect()末尾的最后一条语句。我在 * for * 循环开始时从Rust分析器中得到这些错误。
1.不匹配的类型expected struct Vec<i32> found unit type ()在循环没有要迭代的元素的情况下返回一个值,或者考虑更改返回类型以解决这种可能性[E0308]
1.函数期望总是返回一个值,但循环可能运行零次[E0308]
for循环中的所有内容不都返回Vec<i32>吗?为什么类型不匹配?
1.如果我删除else选项,那么默认选项就不起作用。我不理解这一点,因为 * if * 语句只在用户键入C时发生。否则,它会跳过if并到达函数的末尾,在那里返回Vec<i32>。为什么我必须显式地放置一个 * else * 语句?
这是整个文件,如果你想要更多的上下文。请注意,get_range()函数是直接请求范围而不是提供默认选项的原始版本。
最后,对于小型项目的构建有哪些建议?我的下一个是一个简单的Neofetch类程序,它提供一些系统信息。我对命令行工具和底层的东西很感兴趣,比如内核和操作系统(但是构建内核或操作系统对我的技能来说还很遥远,希望有一天能实现:)

nlejzf6q

nlejzf6q1#

for循环中的所有内容不都返回一个Vec吗?为什么类型不匹配?
编译器研究了如果stdin().lock().lines()中没有行会发生什么。在这种情况下,for循环将永远不会执行,但for循环是一个表达式,并且根据“Programming Rust(Revised 2nd Edition)”,p.一百四十三:
循环是Rust中的表达式[这意味着它们有一个可以赋值给变量的值],但是while或for循环的值总是(),所以它们的值不是很有用。
这意味着编译器将整个for循环替换为()。类似的事情发生在这里:

let numbers: [i32;0] = [];

let x = for number in numbers {
    println!("{number}");
};

println!("{:?}", x);

--output:--
()

for循环从未执行过,但其计算结果为()。因此,如果stdin().lock().lines()中没有行,您的for循环将被跳过,它将计算为(),并且您的函数最终返回()。但是,你告诉编译器你的函数返回一个向量:

fn get_range() -> Vec<i32> {
   ...
}

()不是向量因此,不匹配的类型等。添加行:

(0..=10).collect()

在for循环之后,意味着如果跳过for循环,你的函数将不再返回(),这会使编译器关闭。
如果我删除else选项,那么默认选项就不起作用。我不明白这一点,因为if语句只在用户键入c时发生。否则,它将跳过if并到达函数的末尾,在那里返回Vec。为什么我必须显式地添加else语句?
这又和表情有关。if是一个表达式,这意味着它产生一个可以赋值给变量的值,例如:

let x = 2;

let result = if x==3 {"hello"} else {"goodbye"};

println!("{result}");

--output:--
goodbye

根据“Programming Rust(Revised 2nd Edition)”,p.一百三十八:
...如果没有else,则必须始终返回()
这意味着一个返回某些值的if expression也必须有一个返回相同类型的else分支。下面是一个与该规则相冲突的示例:

fn go(x: i32) -> i32 {
    let mut return_val =  0;

    return_val = if x==2 {4};

    return_val + 10
}

输出:

error[E0317]: `if` may be missing an `else` clause
 --> src/main.rs:7:18
  |
7 |     return_val = if x==2 {4};
  |                  ^^^^^^^^^-^
  |                  |        |
  |                  |        found here
  |                  expected integer, found `()`
  |
  = note: `if` expressions without `else` evaluate to `()`
  = help: consider adding an `else` block that evaluates to the expected type

For more information about this error, try `rustc --explain E0317`.

“Programming Rust Revised 2nd”中所述的规则实际上 * 意味着 *:
...没有else的if必须总是[求值为] ()
...因为下面的代码编译时没有错误:

fn go(x: i32) -> Vec<i32> {
    if x == 2 {
        return (30..=35).collect();
    };

    return (0..=10).collect(); //This could also be written without `return` and no semi-colon to return the collection.
}

fn main() {
    let result = go(1);
    println!("{:?}", result);

}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

显然,if expression内部的return被不同地对待。根据“Programming Rust(Revised 2nd Edition)”,p.一百四十六:
break表达式类似,return可以放弃正在进行的工作。
有趣的是,下面的代码也不会产生任何错误:

fn go(x: i32) -> Vec<i32> {

    let result = if x == 2 {
        return (30..=35).collect();
    };

    return (0..=10).collect();
}

而且,编译器推断result的类型为()。因此,要么赋值将被返回中断,并且永远不会发生,要么如果x不等于2,则if将计算为()-因为“没有else的if必须始终[计算为] ()”-并且该值将被赋值为result
让用户只按Return键来获取默认范围,或者输入两个数字来定制范围,这不是更简单吗?

println!("Enter two numbers for your range, or");
println!("simply hit Return to choose the range 1-10:");

The Rust Programming Language中有一个Guess The Number示例程序,您可能想看看。
最后,有没有什么建议,让小项目建设?
你熟悉exercism.org吗?您可以注册Rust曲目(免费),然后您将被分配一系列程序来完成。如果你有一个github帐户(免费),你可以无缝下载并提交你完成的程序。当您下载作业时,会有一套您的程序必须通过的测试--这些测试充当您作业的规范。在您提交解决方案之后,导师将检查您的程序并提出改进建议,直到您迭代地得出最终解决方案。然后你进入下一个程序。

相关问题