字符串 需求代码片段
拼接字符串(任何实现了 Display
) format!("{x}{y}")
追加字符串(任何实现了 Display
到 任何实现了 Write
) write!(x, "{y}")
按分隔符模式分割 s.split(pattern)
...with &str
s.split("abc")
...with char
s.split('/')
...with closure
s.split(char::is_numeric)
按空格切割 s.split_whitespace()
用换行符分割 s.lines()
按正则表达式分割 Regex::new(r"\s")?.split("one two three")
如果 x
或 y
之后不打算用到,考虑使用 write!
或 std::ops::Add
需要 regex crate
I/O 需求代码片段
创建一个新文件 File::create(PATH)?
通过OpenOptions 创建 OpenOptions::new().create(true).write(true).truncate(true).open(PATH)?
宏 需求代码片段
宏 可变参数 macro_rules! var_args { ($($args:expr),*) => {{ }} }
使用参数,如多次调用 f
$( f($args); )*
Esoterics 需求代码片段
干净的闭包捕获 wants_closure({ let c = outer.clone(); move || use_clone(c) })
在 try
闭包中的修复推断 iter.try_for_each(|x| { Ok::<(), Error>(()) })?;
如果 T
实现了 Copy,则可迭代和编辑 &mut [T]
Cell::from_mut(mut_slice).as_slice_of_cells()
获取带有长度的子切片 &original_slice[offset..][..length]
敏锐的确保特征 T
是对象安全的 const _: Option<&dyn T> = None;
例子 Send*
!Send
Sync*
大多数类型是 ...Arc<T>1,2
, Mutex<T>
MutexGuard<T>
,RwLockReadGuard<T>
!Sync
Cell<T>2
,RefCell<T>
Rc<T>
,&dyn Trait
,*const T
,*mut T
* 一个 T: Send
的实例可以被移动到另一个线程,而一个 T: Sync
意味着 &t
可以被移动到移动到另一个线程
如果 T
是 Sync
如果 T
是 Send
如果你需要去 send 一个裸指针,创建一个新类型 struct Ptr(*const u8)
和 unsafe impl Send for Ptr {}
,仅需确保你可以 send 它
获取迭代器
基本用法
假设有一个类型 C
的集合c :
c.into_iter()
— 将集合c 转换为一个Iterator i 和consumes c 。需要实现了 C
的IntoIterator 。条目的类型取决于 C
是什么。获取迭代器的"标准化"方法
c.iter()
— 一些集合提供的优雅方法,返回借用的迭代器,不会消耗 c
c.iter_mut()
— 同上,但是可变借用的迭代器允许更改集合
The Iterator
一旦你有一个 i
:
i.next()
— 返回下一个元素c提供的 Some(x)
,或者如果已经完成了则返回None
For 循环
for x in c {}
— 语法糖,调用c.into_iter()
并且循环i直到为 None
* 如果它看起来好像没有消耗 c
,那是因为类型是 Copy
,如 如果你调用 (&c).into_iter()
,它将在 &c
上调用 into_iter()
(这将消耗引用并将其转换为迭代器),但c仍保持不变。
实现迭代器
基本用法
假设你有一个 `struct Collection {}`
struct IntoIter {}
— 创建一个结构来保存你的迭代状态(如 索引)以进行值的迭代
impl Iterator for IntoIter {}
— 实现 Iterator::next()
,这样它就可以生成元素
Collection<T>
IntoIter<T>
⌾Iterator
Item = T;
共享的和可变迭代器
struct Iter<T> {}
— 为共享迭代器去创建持有 &Collection<T>
的结构
struct IterMut<T> {}
— 同上,为了可变迭代器去创建持有 &mut Collection<T>
的结构
impl Iterator for Iter {}
— 实现共享迭代器
impl Iterator for IterMut {}
— 实现可变迭代器
另外你可能会希望添加一些便捷的方法
Collection::iter(&self) -> Iter
Collection::iter_mut(&mut self) -> IterMut
Iter<T>
⌾Iterator
Item = &T;
IterMut<T>
⌾Iterator
Item = &mut T;
使用循环的写法
impl IntoIterator for Collection {}
— 现在for x in c {}
是有用的
impl IntoIterator for &Collection {}
— 现在for x in &c {}
是有用的
impl IntoIterator for &mut Collection {}
— 现在for x in &mut c {}
是有用的
Collection<T>
⌾IntoIterator
Item = T;
To = IntoIter<T>
Iterate over T
&Collection<T>
⌾IntoIterator
Item = &T;
To = Iter<T>
Iterate over &T
&mut Collectn<T>
⌾IntoIterator
Item = &mut T;
To = IterMut<T>
Iterate over &mut T
需要转换成的→ u8 … i128
f32 / f64
String
u8 … i128
u8::try_from(x)?
x as f32
x.to_string()
f32 / f64
x as u8
x as f32
x.to_string()
String
x.parse::<u8>()?
x.parse::<f32>()?
x
如果打印是正确的话 from()
会直接输出,如 u32::from(my_u8)
截断(11.9_f32 as u8 gives 11
),充满(1024_f32 as u8 gives 255
)
可能会有不合适的数字(u64::MAX as f32
)或产生 Inf
(u128::MAX as f32
)
已经存在的类型 x
要转换成 String
String
x
CString
x.into_string()?
OsString
x.to_str()?.to_string()
PathBuf
x.to_str()?.to_string()
Vec<u8>
String::from_utf8(x)?
&str
x.to_string()
&CStr
x.to_str()?.to_string()
&OsStr
x.to_str()?.to_string()
&Path
x.to_str()?.to_string()
&[u8]
String::from_utf8_lossy(x).to_string()
已存在的类型 x
要转换成 CString
String
CString::new(x)?
CString
x
OsString
CString::new(x.to_str()?)?
PathBuf
CString::new(x.to_str()?)?
Vec<u8>
CString::new(x)?
&str
CString::new(x)?
&CStr
x.to_owned()
&OsStr
CString::new(x.to_os_string().into_string()?)?
&Path
CString::new(x.to_str()?)?
&[u8]
CString::new(Vec::from(x))?
*mut c_char
unsafe { CString::from_raw(x) }
已存在的类型 x
要转换成 OsString
String
OsString::from(x)
CString
OsString::from(x.to_str()?)
OsString
x
PathBuf
x.into_os_string()
Vec<u8>
?
&str
OsString::from(x)
&CStr
OsString::from(x.to_str()?)
&OsStr
OsString::from(x)
&Path
x.as_os_str().to_owned()
&[u8]
?
已存在的类型 x
要转换成 PathBuf
String
PathBuf::from(x)
CString
PathBuf::from(x.to_str()?)
OsString
PathBuf::from(x)
PathBuf
x
Vec<u8>
?
&str
PathBuf::from(x)
&CStr
PathBuf::from(x.to_str()?)
&OsStr
PathBuf::from(x)
&Path
PathBuf::from(x)
&[u8]
?
已存在的类型 x
要转换成 PathBuf
String
PathBuf::from(x)
CString
PathBuf::from(x.to_str()?)
OsString
PathBuf::from(x)
PathBuf
x
Vec<u8>
?
&str
PathBuf::from(x)
&CStr
PathBuf::from(x.to_str()?)
&OsStr
PathBuf::from(x)
&Path
PathBuf::from(x)
&[u8]
?
已存在的类型 x
要转换成 Vec
String
x.into_bytes()
CString
x.into_bytes()
OsString
?
PathBuf
?
Vec<u8>
x
&str
Vec::from(x.as_bytes())
&CStr
Vec::from(x.to_bytes_with_nul())
&OsStr
?
&Path
?
&[u8]
x.to_vec()
已存在的类型 x
要转换成 &str
String
x.as_str()
CString
x.to_str()?
OsString
x.to_str()?
PathBuf
x.to_str()?
Vec<u8>
std::str::from_utf8(&x)?
&str
x
&CStr
x.to_str()?
&OsStr
x.to_str()?
&Path
x.to_str()?
&[u8]
std::str::from_utf8(x)?
已存在的类型 x
要转换成 &CStr
String
CString::new(x)?.as_c_str()
CString
x.as_c_str()
OsString
x.to_str()?
PathBuf
?,4
Vec<u8>
CStr::from_bytes_with_nul(&x)?
&str
?,4
&CStr
x
&OsStr
?
&Path
?
&[u8]
?
已存在的类型 x
要转换成 PathBuf
String
PathBuf::from(x)
CString
PathBuf::from(x.to_str()?)
OsString
PathBuf::from(x)
PathBuf
x
Vec<u8>
?
&str
PathBuf::from(x)
&CStr
PathBuf::from(x.to_str()?)
&OsStr
PathBuf::from(x)
&Path
PathBuf::from(x)
&[u8]
CStr::from_bytes_with_nul(x)?
*const c_char
unsafe { CStr::from_ptr(x) }
已存在的类型 x
要转换成 &OsStr
String
OsStr::new(&x)
CString
?
OsString
x.as_os_str()
PathBuf
x.as_os_str()
Vec<u8>
?
&str
OsStr::new(x)
&CStr
?
&OsStr
x
&Path
x.as_os_str()
&[u8]
?
已存在的类型 x
要转换成 &Path
String
Path::new(x)
CString
Path::new(x.to_str()?)
OsString
Path::new(x.to_str()?)
PathBuf
Path::new(x.to_str()?)
Vec<u8>
?
&str
Path::new(x)
&CStr
Path::new(x.to_str()?)
&OsStr
Path::new(x)
&Path
x
&[u8]
?
已存在的类型 x
要转换成 &[u8]
String
x.as_bytes()
CString
x.as_bytes()
OsString
?
PathBuf
?
Vec<u8>
&x
&str
x.as_bytes()
&CStr
x.to_bytes_with_nul()
&OsStr
x.as_bytes()
&Path
?
&[u8]
x
已存在的类型 x
要转换成 Other ( *const c_char
)
CString
x.as_ptr()
( *const c_char
)
* 如果类型能被推断出来则可使用简写 x.into()
* 如果类型能被推断出来则可使用简写 x.as_ref()
如果调用了unsafe ,你应该或必须确保原始数据带有字符串类型的有效表示(如 一个 UTF-8
的字符串)
仅在一些平台( std::os::<your_os>::ffi::OsStrExt
)存在辅助方法去获取底层 OsStr
的原始表示。从那里使用表格的其它部分,如下
use std::os::unix::ffi::OsStrExt;
let bytes: &[u8] = my_os_str.as_bytes();
CString::new(bytes)?
c_char
必须来自之前的 CString
,如果来自FFI,请参阅 &CStr
x
因为缺少终止符 0x0
,没有已知的简写,可能最好的方式是通过 CString
必须确保向量实际上以 0x0
结尾
Rust使用这些APIs将类型转换为字符串化输出,统称为格式宏
宏 输出 备注
format!(fmt)
String
"to String" 的转换器
print!(fmt)
Console 写到标准输出
println!(fmt)
Console 写到标准输出,换行
eprint!(fmt)
Console 写到标准错误输出
eprintln!(fmt)
Console 写到标准错误输出,换行
write!(dst, fmt)
Buffer 还有 use std::io::Write;
writeln!(dst, fmt)
Buffer 还有 use std::io::Write;
,换行
方法 备注
x.to_string()
生成 String
,实现任何的 Display
类型
* 这 fmt
是字符串文字,例如 "hello {}"
,指定输出和其他参数
* 在友好的 format!
中,类型通过 trait Display "{}"
或 Debug "{:?}"
转换,非详尽列表如下
类型 实现
String
Debug, Display
CString
Debug
OsString
Debug
PathBuf
Debug
Vec<u8>
Debug
&str
Debug, Display
&CStr
Debug
&OsStr
Debug
&Path
Debug
&[u8]
Debug
bool
Debug, Display
char
Debug, Display
u8 … i128
Debug, Display
f32, f64
Debug, Display
!
Debug, Display
()
Debug
* 简而言之,几乎所有东西都是Debug,更多特殊类型可能需要特殊处理或转换到 Display
格式宏中的每个参数指示符要么是空的 {},{argument},要么遵循基本语法
{ [argument] ':' [[fill] align] [sign] ['#'] [width [$]] ['.' precision [$]] [type] }
元素 含义
argument
数字( 0, 1, ...
),变量或名字,如 print!("{x}")
fill
如果指定了宽度,用(如 0
)来填充空白的字符
align
如果指定了宽度,则左(<)、中(^)或右(>)
sign
可以是 +
,标志总是被打印
#
代替格式化,如 美化的 Debug
格式器 ?
或前缀十六进制使用 0x
width
最小的宽度(≥0),填充(默认为空格)如果以 0
开头,则补零
precision
数字的小数位(≥0),或者形容非数字的最大宽度
$
解释宽度(width)或精度(precision)作为参数标识符,而不是允许动态格式化
type
Debug
格式化、十六进制(x)、二进制(b)、八进制(o)、指针(p)、exp(e)
格式化示例 解释
{}
使用 Display
打印下一个参数
{x}
同上,但在范围内使用变量 x
{:?}
使用 Debug
打印下一个参数
{2:#?}
使用 Debug
格式化,较好的打印第三个参数
{val:^2$}
将命名参数 val
居中,宽度由第三个参数指定
{:<10.3}
左对齐宽度为 10,精度为 3
{val:#x}
将参数 val
格式化为十六进制,带前缀 0x
(替代格式 x
)
完整示例 解释
println!("{}", x)
使用 Display
在标准输出打印并且追加一个新行
println!("{x}")
同上,但在范围内使用变量 x
format!("{a:.3} {b:?}")
用三位数字转换 PI
,增加空格,b
使用 Debug
,返回 String