字符串 需求代码片段
拼接字符串(任何实现了 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>
!SyncCell<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 … i128f32 / f64String
u8 … i128u8::try_from(x)?x as f32x.to_string()
f32 / f64x as u8x as f32x.to_string()
Stringx.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
Stringx
CStringx.into_string()?
OsStringx.to_str()?.to_string()
PathBufx.to_str()?.to_string()
Vec<u8>String::from_utf8(x)?
&strx.to_string()
&CStrx.to_str()?.to_string()
&OsStrx.to_str()?.to_string()
&Pathx.to_str()?.to_string()
&[u8]String::from_utf8_lossy(x).to_string()
已存在的类型 x 要转换成 CString
StringCString::new(x)?
CStringx
OsStringCString::new(x.to_str()?)?
PathBufCString::new(x.to_str()?)?
Vec<u8>CString::new(x)?
&strCString::new(x)?
&CStrx.to_owned()
&OsStrCString::new(x.to_os_string().into_string()?)?
&PathCString::new(x.to_str()?)?
&[u8]CString::new(Vec::from(x))?
*mut c_charunsafe { CString::from_raw(x) }
已存在的类型 x 要转换成 OsString
StringOsString::from(x)
CStringOsString::from(x.to_str()?)
OsStringx
PathBufx.into_os_string()
Vec<u8>?
&strOsString::from(x)
&CStrOsString::from(x.to_str()?)
&OsStrOsString::from(x)
&Pathx.as_os_str().to_owned()
&[u8]?
已存在的类型 x 要转换成 PathBuf
StringPathBuf::from(x)
CStringPathBuf::from(x.to_str()?)
OsStringPathBuf::from(x)
PathBufx
Vec<u8>?
&strPathBuf::from(x)
&CStrPathBuf::from(x.to_str()?)
&OsStrPathBuf::from(x)
&PathPathBuf::from(x)
&[u8]?
已存在的类型 x 要转换成 PathBuf
StringPathBuf::from(x)
CStringPathBuf::from(x.to_str()?)
OsStringPathBuf::from(x)
PathBufx
Vec<u8>?
&strPathBuf::from(x)
&CStrPathBuf::from(x.to_str()?)
&OsStrPathBuf::from(x)
&PathPathBuf::from(x)
&[u8]?
已存在的类型 x 要转换成 Vec
Stringx.into_bytes()
CStringx.into_bytes()
OsString?
PathBuf?
Vec<u8>x
&strVec::from(x.as_bytes())
&CStrVec::from(x.to_bytes_with_nul())
&OsStr?
&Path?
&[u8]x.to_vec()
已存在的类型 x 要转换成 &str
Stringx.as_str()
CStringx.to_str()?
OsStringx.to_str()?
PathBufx.to_str()?
Vec<u8>std::str::from_utf8(&x)?
&strx
&CStrx.to_str()?
&OsStrx.to_str()?
&Pathx.to_str()?
&[u8]std::str::from_utf8(x)?
已存在的类型 x 要转换成 &CStr
StringCString::new(x)?.as_c_str()
CStringx.as_c_str()
OsStringx.to_str()?
PathBuf?,4
Vec<u8>CStr::from_bytes_with_nul(&x)?
&str?,4
&CStrx
&OsStr?
&Path?
&[u8]?
已存在的类型 x 要转换成 PathBuf
StringPathBuf::from(x)
CStringPathBuf::from(x.to_str()?)
OsStringPathBuf::from(x)
PathBufx
Vec<u8>?
&strPathBuf::from(x)
&CStrPathBuf::from(x.to_str()?)
&OsStrPathBuf::from(x)
&PathPathBuf::from(x)
&[u8]CStr::from_bytes_with_nul(x)?
*const c_charunsafe { CStr::from_ptr(x) }
已存在的类型 x 要转换成 &OsStr
StringOsStr::new(&x)
CString?
OsStringx.as_os_str()
PathBufx.as_os_str()
Vec<u8>?
&strOsStr::new(x)
&CStr?
&OsStrx
&Pathx.as_os_str()
&[u8]?
已存在的类型 x 要转换成 &Path
StringPath::new(x)
CStringPath::new(x.to_str()?)
OsStringPath::new(x.to_str()?)
PathBufPath::new(x.to_str()?)
Vec<u8>?
&strPath::new(x)
&CStrPath::new(x.to_str()?)
&OsStrPath::new(x)
&Pathx
&[u8]?
已存在的类型 x 要转换成 &[u8]
Stringx.as_bytes()
CStringx.as_bytes()
OsString?
PathBuf?
Vec<u8>&x
&strx.as_bytes()
&CStrx.to_bytes_with_nul()
&OsStrx.as_bytes()
&Path?
&[u8]x
已存在的类型 x 要转换成 Other ( *const c_char )
CStringx.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 "{:?}" 转换,非详尽列表如下
类型 实现
StringDebug, Display
CStringDebug
OsStringDebug
PathBufDebug
Vec<u8>Debug
&strDebug, Display
&CStrDebug
&OsStrDebug
&PathDebug
&[u8]Debug
boolDebug, Display
charDebug, Display
u8 … i128Debug, Display
f32, f64Debug, 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)作为参数标识符,而不是允许动态格式化
typeDebug 格式化、十六进制(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