String
Rust 字符串
String 和 &str
&str 是一个简单的字符串。当你写let my_variable = "Hello, world!"
, 你创建了&str ,它的速度非常快。String 字符串是更复杂的字符串。它有点慢,并且功能更多。字符串是一个指针,在堆上有数据。
// Rust 的 string 被表达为:&'static str,所有的用""包裹起来的字符串,都被声明成了一个不可变,静态的字符串。
let x = "Hello";
let x:&'static str = "Hello";
fn main() {
let name = "서태지"; // This is a Korean name. No problem, because a &str is UTF-8.
let other_name = String::from("Adrian Fahrenheit Țepeș"); // Ț and ș are no problem in UTF-8.
}
您甚至可以借助
fn main() {
let name = "😂";
println!("My name is actually {}", name);
}
那么为什么我们在
fn main() {
println!("A String is always {:?} bytes. It is Sized.", std::mem::size_of::<String>()); // std::mem::size_of::<Type>() gives you the size in bytes of a type
println!("And an i8 is always {:?} bytes. It is Sized.", std::mem::size_of::<i8>());
println!("And an f64 is always {:?} bytes. It is Sized.", std::mem::size_of::<f64>());
println!("But a &str? It can be anything. '서태지' is {:?} bytes. It is not Sized.", std::mem::size_of_val("서태지")); // std::mem::size_of_val() gives you the size in bytes of a variable
println!("And 'Adrian Fahrenheit Țepeș' is {:?} bytes. It is not Sized.", std::mem::size_of_val("Adrian Fahrenheit Țepeș"));
}
这就是为什么我们需要一个 & 的原因,因为 & 会创建一个指针,而
类型互转
这里有一些:
String::from("This is the string text");
这是用于String 的方法,该方法采用文本并创建String 。"This is the string text".to_string()
,这是 &str 的方法,使它成为String 。format! 宏。这就像println !除了它创建一个String 而不是打印。因此,您可以执行以下操作:
fn main() {
let my_name = "Billybrobby";
let my_country = "USA";
let my_home = "Korea";
let together = format!(
"I am {} and I come from {} but I live in {}.",
my_name, my_country, my_home
);
}
现在我们有了一个在一起命名的字符串,但尚未打印出来。此外,我们还可以使用 .into()
来创建字符串,某些类型可以使用String::from("Some str")
是来自 &
fn main() {
let my_string = "Try to make this a String".into(); // ⚠️
}
// Rust doesn't know what type you want, because many types can be made from a &str.
error[E0282]: type annotations needed
--> src\main.rs:2:9
|
2 | let my_string = "Try to make this a String".into();
| ^^^^^^^^^ consider giving `my_string` a type
fn main() {
let my_string: String = "Try to make this a String".into();
}
我们也可以使用 &*
符号将
fn use_str(s: &str) {
println!("I am: {}", s);
}
fn main() {
let s = "Hello".to_string();
use_str(&*s);
}
首先呢,&*
是两个符号 &
和 *
的组合,按照*
操作。由于impl Deref<Target=str> for String
,这相当于一个运算符重载,所以你就能通过 *
获得一个
索引访问
有人会把
let x = "hello".to_string();
x[1]; //编译错误!
let x = "哎哟我去".to_string();
for i in x.as_bytes() {
print!("{} ", i);
}
println!("");
for i in x.chars() {
print!("{}", i);
}
x.chars().nth(2);
格式化字符串
format!
、format_arg!
、print!
、println!
、write!
;Debug
、Display
。相信你们在写print!
或者println!
这两个宏,但是其实最核心的是format!
,前两个宏只不过将format!
的结果输出到了
fn main() {
let s = format!("{1}是个有着{0:>0width$}KG重,{height:?}cm高的大胖子",
81, "wayslog", width=4, height=178);
// 我被逼的牺牲了自己了……
print!("{}", s);
}
format_string := <text> [ format <text> ] *
format := '{' [ argument ] [ ':' format_spec ] '}'
argument := integer | identifier
format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
fill := character
align := '<' | '^' | '>'
sign := '+' | '-'
width := count
precision := count | '*'
type := identifier | ''
count := parameter | integer
parameter := integer '$'
字符串切片
另一个没有所有权的数据类型是
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
这类似于引用整个let world = &s[6..11];
的情况,

对于
let s = String::from("hello");
let slice = &s[0..2];
let slice = &s[..2];
依此类推,如果
let s = String::from("hello");
let len = s.len();
let slice = &s[3..len];
let slice = &s[3..];
也可以同时舍弃这两个值来获取整个字符串的
let s = String::from("hello");
let len = s.len();
let slice = &s[0..len];
let slice = &s[..];
字符串