我有以下代码来创建长度为n+1的字符串,其中n作为命令行参数传递:
let args: Vec<String> = env::args().collect();
let min_no_of_bytes = &args[2].parse::<u64>();
let no_of_times_to_repeat = min_no_of_bytes as usize;
let mut inputtext='0'.to_string().repeat(no_of_times_to_repeat);
但是我在编译过程中得到以下错误:
error[E0606]: casting `&Result<u64, ParseIntError>` as `usize` is invalid
--> src/main.rs:33:17
|
33 | let temp = min_no_of_bytes as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: cast through a raw pointer first
请建议。谢谢。
原代码中有几个问题没有处理。
args
不保证有第二个参数,因此&args[2]
可能会panic&args[2]
处的字符串不保证是可解析的数字,因此parse
返回Result
,这可能携带错误。
在Rust中通常不鼓励直接访问数组。这当然是可能的,但它可能会引起恐慌,而且速度很慢。因此,如果要访问数组,通常使用迭代器或.get()
函数。
处理所有错误
首先,我建议在我们使它变得更漂亮之前处理所有的错误。如果您避免直接访问数组和unwrap
:
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let arg = match args.get(2) {
Some(val) => val,
None => {
println!("Not enough arguments provided!");
return;
}
};
let min_no_of_bytes = match arg.parse::<u64>() {
Ok(val) => val,
Err(e) => {
println!("Unable to parse number from argument: {}", e);
return;
}
};
let no_of_times_to_repeat = min_no_of_bytes as usize;
let inputtext = '0'.to_string().repeat(no_of_times_to_repeat);
println!("{}", inputtext);
}
使用:cargo run -- bla 3
运行此程序打印000
。
设置正确的错误处理
如果你意识到我们现在有println!(...error)
和return
紧挨着彼此。相反,我们可以直接从main返回一个错误来组合这两个操作。Rust会自动打印错误。
为了接受任何错误类型,可以使用Result<(), Box<dyn Error>>
类型或像anyway这样的包装类型来完成。
我将在这里提供anyhow
解决方案,因为我认为通常使用包装器库而不是直接使用Box<dyn Error>
会更好。
use anyhow::{anyhow, Result};
use std::env;
fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();
let arg = args
.get(2)
.ok_or(anyhow!("Not enough arguments provided!"))?;
let min_no_of_bytes = arg.parse::<u64>()?;
let no_of_times_to_repeat = min_no_of_bytes as usize;
let inputtext = '0'.to_string().repeat(no_of_times_to_repeat);
println!("{}", inputtext);
Ok(())
}
注意这里的?
操作符,这是一种快速表示"如果这是Err
值,则从函数返回它,否则将值展开"的方式。基本上是安全的、错误传播的.unwrap()
版本。
使用合适的命令行解析库
我不会在这里深入讨论细节,但是如果您的项目代码略多于10行,您很快就会发现手动编写参数解析非常乏味。
有几个库使这个过程非常容易。在写这篇文章的时候,我推荐的是clap:
use clap::Parser;
/// A program that does things
#[derive(Parser, Debug)]
#[clap(version, about)]
struct Args {
/// Minimum number of bytes
#[clap(short)]
min_no_of_bytes: u64,
}
fn main() {
let args = Args::parse();
let no_of_times_to_repeat = args.min_no_of_bytes as usize;
let inputtext = '0'.to_string().repeat(no_of_times_to_repeat);
println!("{}", inputtext);
}
这需要你的Cargo.toml
中的clap = { version = "3.1", features = ["derive"] }
。
使用cargo run -- -m 3
运行它会得到000
。
很酷的副作用是您可以免费获得帮助消息:
cargo run -- -h
my-program 0.1.0
A program that does things
USAGE:
my-program.exe -m <MIN_NO_OF_BYTES>
OPTIONS:
-h, --help Print help information
-m <MIN_NO_OF_BYTES> Minimum number of bytes
-V, --version Print version information
以下操作有效:
let args: Vec<String> = env::args().collect();
let min_no_of_bytes = *(&args[2].parse::<usize>().unwrap());
let mut inputtext='0'.to_string().repeat(no_of_times_to_repeat);