为什么Rust有String和str?String和之间有什么区别str?什么时候使用String而不是str反之亦然?其中一个被弃用了吗?
我想编写一个程序,分两步编写一个文件.在程序运行之前,该文件可能不存在.文件名是固定的.
问题是OpenOptions.new().write()可能会失败.在这种情况下,我想调用自定义函数trycreate().我们的想法是创建文件而不是打开它并返回一个句柄.由于文件名是固定的,trycreate()没有参数,我不能设置返回值的生命周期.
我该如何解决这个问题?
use std::io::Write;
use std::fs::OpenOptions;
use std::path::Path;
fn trycreate() -> &OpenOptions {
let f = OpenOptions::new().write(true).open("foo.txt");
let mut f = match f {
Ok(file) => file,
Err(_) => panic!("ERR"),
};
f
}
fn main() {
{
let f = OpenOptions::new().write(true).open(b"foo.txt");
let mut f = match f {
Ok(file) => file,
Err(_) => trycreate("foo.txt"),
};
let buf = b"test1\n";
let _ret = f.write(buf).unwrap();
}
println!("50%");
{
let f = OpenOptions::new().append(true).open("foo.txt");
let mut f …Run Code Online (Sandbox Code Playgroud) 我想创建一个&'static str由重复的字符序列组成的长片,例如abcabcabc...
在Rust中有没有办法通过表达式来实现这一点,例如long_str = 1000 * "abc"在Python中,或者我是否必须在Python中生成它并将其复制/粘贴到Rust代码中?
我只花了一个星期阅读Rust Book,现在我正在开发我的第一个程序,它将文件路径返回到系统壁纸:
pub fn get_wallpaper() -> &str {
let output = Command::new("gsettings");
// irrelevant code
if let Ok(message) = String::from_utf8(output.stdout) {
return message;
} else {
return "";
}
}
Run Code Online (Sandbox Code Playgroud)
我收到错误expected lifetime parameter on &str,我知道Rust想要一个输入&str,它将作为输出返回,因为&str我在函数内部创建的任何内容都将在函数结束后立即清理.
我知道我可以通过返回一个String而不是一个来回避这个问题&str,并且对类似问题的许多答案已经说了很多.但我似乎也可以这样做:
fn main() {
println!("message: {}", hello_string(""));
}
fn hello_string(x: &str) -> &str {
return "hello world";
}
Run Code Online (Sandbox Code Playgroud)
得到&str我的功能.有人可以向我解释为什么这很糟糕,为什么我不应该这样做?或者也许它在某些情况下并不坏并且没问题?
我写了一个函数来提示输入并返回结果.在此版本中,返回的字符串包含用户的尾随换行符.我想将该换行符(以及该换行符)删除后返回输入:
fn read_with_prompt(prompt: &str) -> io::Result<String> {
let stdout = io::stdout();
let reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
reader.read_line(&mut input)?;
// TODO: Remove trailing newline if present
Ok(input)
}
Run Code Online (Sandbox Code Playgroud)
仅删除单个尾随换行符的原因是此函数还将用于提示输入密码(适当使用termios以停止回显),如果某人的密码具有尾随空格,则应保留该空格.
在关于如何在字符串末尾实际删除单个换行符之后,我最终使用了trim_right_matches.然而,返回一个&str.我试图用它Cow来处理这个但是错误仍然说input变量不够长.
fn read_with_prompt<'a>(prompt: &str) -> io::Result<Cow<'a, str>> {
let stdout = io::stdout();
let reader = io::stdin();
let mut input = String::new();
print!("{}", prompt);
stdout.lock().flush().unwrap();
reader.read_line(&mut input)?;
let mut trimmed = false;
Ok(Cow::Borrowed(input.trim_right_matches(|c| {
if !trimmed …Run Code Online (Sandbox Code Playgroud) 正在用 Rust 编写一些代码,尝试使用(否则相当不错的) crate 来定义 CLI clap,但遇到了一个相当关键的问题。App接受 an的方法Into<&'help str>,我一直无法找到实现此特征的方法。
事实上,据我了解,这是绝对无法实现的:
struct JustWorkDamnIt {
string: String
}
impl From<JustWorkDamnIt> for &str {
fn from(arg: JustWorkDamnIt) -> Self {
return arg.string.as_str()
}
}
Run Code Online (Sandbox Code Playgroud)
...产生:
error[E0515]: cannot return value referencing local data `arg.string`
--> src/cmd/interactive.rs:25:16
|
25 | return arg.string.as_str()
| ----------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `arg.string` is borrowed here
Run Code Online (Sandbox Code Playgroud)
然而有趣的是,返回一个文字编译得很好(我认为这就是为什么clap不介意使用这个特性)。大概这是因为文字被编译到内存的某个静态区域,因此不属于该函数:
error[E0515]: cannot return value referencing …Run Code Online (Sandbox Code Playgroud) 考虑这个应该返回给定文件扩展名的函数Path.
pub fn get_extension<'a>(path: &'a Path) -> Option<&'a str> {
let path_str = path.as_str().unwrap();
let ext_pos = regex!(".[a-z0-9]+$").find(path_str);
match ext_pos {
Some((start, _)) => {
return Some(path_str.as_slice().slice_from(start))
},
None => return None
}
}
Run Code Online (Sandbox Code Playgroud)
错误消息如下:
`path_str` does not live long enough
Run Code Online (Sandbox Code Playgroud)

错误信息很清楚,很遗憾我无法自己解决这个问题.我在理论上理解它,但对我来说还有一些模糊的东西.
据我所知,编译器想告诉我,path_str活动时间不够长,因为返回值标记为生命周期'a.
但这就是它停止的地方:
据我所知,对path(输入参数)的引用应该与str对Option(包含在输出参数中)的引用完全一样长
因为我们回来了,Some(path_str.as_slice().slice_from(start))我认为在实践中,这意味着只path_str需要生活path.
我不明白的是到底为什么不path_str不活足够长的时间,我怎么能解决这个问题?是什么让它很快死去?
UPDATE
正如在评论中指出的那样以及IRC中删除superflous as_slice()使代码编译.有谁知道那是为什么?还有人指出存在一种直接获得扩展的方法.但是,我实际上更感兴趣的是学习问题背后的故事.
我遇到了这个问题format!,据我所知,在一个没有锚定到任何东西的模式中创建一个临时值。
let x = 42;
let category = match x {
0...9 => "Between 0 and 9",
number @ 10 => format!("It's a {}!", number).as_str(),
_ if x < 0 => "Negative",
_ => "Something else",
};
println!("{}", category);
Run Code Online (Sandbox Code Playgroud)
在这段代码中, 的类型category是 a &str,它通过返回一个像 的文字来满足"Between 0 and 9"。如果我想使用 将匹配的值格式化为切片as_str(),则会出现错误:
let x = 42;
let category = match x {
0...9 => "Between 0 and 9",
number @ 10 => format!("It's a {}!", …Run Code Online (Sandbox Code Playgroud) 我正在尝试操作从函数参数派生的字符串,然后返回该操作的结果:
fn main() {
let a: [u8; 3] = [0, 1, 2];
for i in a.iter() {
println!("{}", choose("abc", *i));
}
}
fn choose(s: &str, pad: u8) -> String {
let c = match pad {
0 => ["000000000000000", s].join("")[s.len()..],
1 => [s, "000000000000000"].join("")[..16],
_ => ["00", s, "0000000000000"].join("")[..16],
};
c.to_string()
}
Run Code Online (Sandbox Code Playgroud)
在构建时,我收到此错误:
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> src\main.rs:9:9
|
9 | let c = match pad {
| ^ `str` does not have a …Run Code Online (Sandbox Code Playgroud) 我正在尝试解析文件并Vec<Vec<&str>>从函数返回。但在推送到向量时,我在文件读取循环内遇到借用值错误。
use std::io::{self, BufReader, prelude::*};
use std::fs::File;
fn read() -> Vec<Vec<&'static str>> {
let file = File::open("~/test").expect("failed to read file");
let reader = BufReader::new(file);
let mut main_vector: Vec<Vec<&str>> = Vec::new();
for line in reader.lines() {
match line {
Ok(v) => {
let mut sub_vector: Vec<&str> = Vec::new();
for element in v.split_whitespace().collect::<Vec<&str>>() {
sub_vector.push(element);
}
main_vector.push(sub_vector);
},
Err(e) => panic!("failed to parse: {:?}", e),
}
}
//return main_vector;
}
Run Code Online (Sandbox Code Playgroud)
这是编译器错误:
error[E0597]: `v` does not live long enough
--> src/main.rs:67:32 …Run Code Online (Sandbox Code Playgroud)