Struct alloc::string::String 1.0.0[−][src]
pub struct String { /* fields omitted */ }
Expand description
一个 UTF-8 编码的可增长字符串。
String
类型是最常见的字符串类型,拥有对该字符串内容的所有权。它与其借用的对应物,原始的 str
有着密切的关系。
Examples
您可以使用 String::from
从一个 字符串字面量 创建一个 String
:
let hello = String::from("Hello, world!");
Run您可以使用 push
方法将 char
追加到 String
上,并使用 push_str
方法追加 &str
:
let mut hello = String::from("Hello, ");
hello.push('w');
hello.push_str("orld!");
Run如果具有 UTF-8 字节的 vector,则可以使用 from_utf8
方法从中创建一个 String
:
// vector 中的一些字节
let sparkle_heart = vec![240, 159, 146, 150];
// 我们知道这些字节是有效的,因此我们将使用 `unwrap()`。
let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
assert_eq!("💖", sparkle_heart);
RunUTF-8
String
s 始终是有效的 UTF-8。这有一些含义,首先是如果您需要非 UTF-8 字符串,请考虑使用 OsString
。它是相似的,但是没有 UTF-8 约束。第二个含义是您不能索引到 String
:
let s = "hello";
println!("The first letter of s is {}", s[0]); // ERROR!!!
Run索引旨在进行恒定时间操作,但是 UTF-8 编码不允许我们执行此操作。此外,尚不清楚索引应返回哪种类型:字节,代码点或字形簇。
bytes
和 chars
方法分别返回前两个的迭代器。
Deref
String
实现了 Deref<Target = str>
,因此继承了 str
的所有方法。另外,这意味着您可以使用与号 (&
) 将 String
传递给采用 &str
的函数:
fn takes_str(s: &str) { }
let s = String::from("Hello");
takes_str(&s);
Run这将从 String
创建一个 &str
,并将其传入。这种转换非常便宜,因此通常,函数会接受 &str
作为参数,除非出于某些特定原因它们需要 String
。
在某些情况下,Rust 没有足够的信息来进行此转换,称为 Deref
强制多态。在以下示例中,字符串切片 &'a str
实现 TraitExample
trait,函数 example_func
接受实现 trait 的所有内容。
在这种情况下,Rust 将需要进行两次隐式转换,而 Rust 没有办法进行转换。
因此,以下示例将无法编译。
trait TraitExample {}
impl<'a> TraitExample for &'a str {}
fn example_func<A: TraitExample>(example_arg: A) {}
let example_string = String::from("example_string");
example_func(&example_string);
Run有两种选择可以代替。第一种是使用方法 as_str()
显式提取包含该字符串的字符串切片,从而将 example_func(&example_string);
行更改为 example_func(example_string.as_str());
。
第二种方法将 example_func(&example_string);
更改为 example_func(&*example_string);
。
在这种情况下,我们将 String
解引用到 str
,然后将 str
引用回 &str
。
第二种方法更惯用,但是两种方法都可以显式地进行转换,而不是依赖于隐式转换。
Representation
String
由三个部分组成:指向某些字节的指针,长度和容量。指针指向 String
用于存储其数据的内部缓冲区。长度是当前存储在缓冲区中的字节数,容量是缓冲区的大小 (以字节为单位)。
这样,长度将始终小于或等于容量。
此缓冲区始终存储在堆中。
您可以使用 as_ptr
,len
和 capacity
方法查看它们:
use std::mem;
let story = String::from("Once upon a time...");
// 防止自动丢弃字符串的数据
let mut story = mem::ManuallyDrop::new(story);
let ptr = story.as_mut_ptr();
let len = story.len();
let capacity = story.capacity();
// story 有十九个字节
assert_eq!(19, len);
// 我们可以用 ptr,len 和 capacity 重新构建一个 String。
// 这都是不安全的,因为我们有责任确保组件有效:
let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ;
assert_eq!(String::from("Once upon a time..."), s);
Run如果 String
具有足够的容量,则向其添加元素将不会重新分配。例如,考虑以下程序:
let mut s = String::new();
println!("{}", s.capacity());
for _ in 0..5 {
s.push_str("hello");
println!("{}", s.capacity());
}
Run这将输出以下内容:
0
5
10
20
20
40
最初,我们根本没有分配任何内存,但是当我们追加到字符串后,它会适当地增加其容量。如果我们改为使用 with_capacity
方法来初始分配正确的容量,请执行以下操作:
let mut s = String::with_capacity(25);
println!("{}", s.capacity());
for _ in 0..5 {
s.push_str("hello");
println!("{}", s.capacity());
}
Run我们最终得到了不同的输出:
25
25
25
25
25
25
在这里,不需要在循环内分配更多的内存。
Implementations
创建一个新的空 String
。
由于 String
为空,因此不会分配任何初始缓冲区。虽然这意味着该初始操作非常便宜,但在以后添加数据时可能会导致过多的分配。
如果您对 String
可以容纳多少数据有所了解,请考虑使用 with_capacity
方法来防止过多的重新分配。
Examples
基本用法:
let s = String::new();
Run创建一个具有特定容量的新的空 String
。
String
有一个内部缓冲区来保存其数据。
容量是该缓冲区的长度,可以使用 capacity
方法进行查询。
此方法将创建一个空的 String
,但是它带有一个初始缓冲区,该缓冲区可以容纳 capacity
字节。
当您可能将一堆数据追加到 String
时,这很有用,从而减少了它需要进行的重新分配的次数。
如果给定的容量为 0
,则不会进行分配,并且此方法与 new
方法相同。
Examples
基本用法:
let mut s = String::with_capacity(10);
// 字符串不包含任何字符,即使它可以容纳更多字符
assert_eq!(s.len(), 0);
// 这些都无需重新分配即可完成...
let cap = s.capacity();
for _ in 0..10 {
s.push('a');
}
assert_eq!(s.capacity(), cap);
// ... 但这可能会使字符串重新分配
s.push('a');
Run将字节的 vector 转换为 String
。
字符串 (String
) 由字节 (u8
) 组成,字节 (Vec<u8>
) 的 vector 由字节组成,因此此函数在两者之间进行转换。
并非所有的字节片都是有效的 String
,但是: String
要求它是有效的 UTF-8。
from_utf8()
检查以确保字节是有效的 UTF-8,然后进行转换。
如果您确定字节切片是有效的 UTF-8,并且不想增加有效性检查的开销,则此函数有一个不安全的版本 from_utf8_unchecked
,它具有相同的行为,但是会跳过检查。
为了提高效率,此方法将注意不要复制 vector。
如果需要 &str
而不是 String
,请考虑使用 str::from_utf8
。
与此方法的相反的是 into_bytes
。
Errors
如果切片不是 UTF-8,则返回 Err
,并说明为什么提供的字节不是 UTF-8。还包括您移入的 vector。
Examples
基本用法:
// vector 中的一些字节
let sparkle_heart = vec![240, 159, 146, 150];
// 我们知道这些字节是有效的,因此我们将使用 `unwrap()`。
let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
assert_eq!("💖", sparkle_heart);
Run字节不正确:
// vector 中的一些无效字节
let sparkle_heart = vec![0, 159, 146, 150];
assert!(String::from_utf8(sparkle_heart).is_err());
Run请参见 FromUtf8Error
文档,以获取有关此错误的更多详细信息。
将字节切片转换为字符串,包括无效字符。
字符串由字节 (u8
) 组成,而字节 (&[u8]
) 的切片由字节组成,因此此函数在两者之间进行转换。然而,并非所有的字节片都是有效的字符串,字符串必须是有效的 UTF-8。
在此转换过程中,from_utf8_lossy()
会将所有无效的 UTF-8 序列替换为 U+FFFD REPLACEMENT CHARACTER
,如下所示:
如果您确定字节切片是有效的 UTF-8,并且不想增加转换的开销,则此函数有一个不安全的版本 from_utf8_unchecked
,它具有相同的行为,但是会跳过检查。
此函数返回 Cow<'a, str>
。如果字节切片的 UTF-8 无效,则需要插入替换字符,这将更改字符串的大小,因此需要 String
。
但是,如果它已经是有效的 UTF-8,则不需要新的分配。
这种返回类型使我们能够处理两种情况。
Examples
基本用法:
// vector 中的一些字节
let sparkle_heart = vec![240, 159, 146, 150];
let sparkle_heart = String::from_utf8_lossy(&sparkle_heart);
assert_eq!("💖", sparkle_heart);
Run字节不正确:
// 一些无效的字节
let input = b"Hello \xF0\x90\x80World";
let output = String::from_utf8_lossy(input);
assert_eq!("Hello �World", output);
Run将 UTF-16 编码的 vector v
解码为 String
,如果 v
包含任何无效数据,则返回 Err
。
Examples
基本用法:
// 𝄞music
let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
0x0073, 0x0069, 0x0063];
assert_eq!(String::from("𝄞music"),
String::from_utf16(v).unwrap());
// 𝄞mu<invalid>ic
let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
0xD800, 0x0069, 0x0063];
assert!(String::from_utf16(v).is_err());
Run将 UTF-16 编码的切片 v
解码为 String
,将无效数据替换为 替换字符 (U+FFFD
)。
与 from_utf8_lossy
返回 Cow<'a, str>
不同,from_utf16_lossy
返回 String
,因为 UTF-16 到 UTF-8 的转换需要分配内存。
Examples
基本用法:
// 𝄞mus<invalid>ic<invalid>
let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
0x0073, 0xDD1E, 0x0069, 0x0063,
0xD834];
assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
String::from_utf16_lossy(v));
Run将 String
分解为其原始组件。
返回指向底层数据的裸指针,字符串的长度 (以字节为单位) 和数据的已分配容量 (以字节为单位)。
这些参数与 from_raw_parts
的参数顺序相同。
调用此函数后,调用者将负责先前由 String
管理的内存。
唯一的方法是使用 from_raw_parts
函数将裸指针,长度和容量转换回 String
,从而允许析构函数执行清除操作。
Examples
#![feature(vec_into_raw_parts)]
let s = String::from("hello");
let (ptr, len, cap) = s.into_raw_parts();
let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };
assert_eq!(rebuilt, "hello");
Run根据长度,容量和指针创建一个新的 String
。
Safety
这是非常不安全的,因为没有检查的不变量的数量:
buf
处的内存必须事先由标准库使用的同一分配器分配,且所需的对齐方式正好为 1。length
需要小于或等于capacity
。capacity
需要是正确的值。buf
的前length
字节必须为有效的 UTF-8。
违反这些可能会导致一些问题,比如破坏分配器的内部数据结构。
buf
的所有权有效地转移到 String
,然后 String
可以随意释放,重新分配或更改指针所指向的内存的内容。
调用此函数后,请确保没有其他任何东西使用该指针。
Examples
基本用法:
use std::mem;
unsafe {
let s = String::from("hello");
// 防止自动丢弃字符串的数据
let mut s = mem::ManuallyDrop::new(s);
let ptr = s.as_mut_ptr();
let len = s.len();
let capacity = s.capacity();
let s = String::from_raw_parts(ptr, len, capacity);
assert_eq!(String::from("hello"), s);
}
Run将字节的 vector 转换为 String
,而无需检查字符串是否包含有效的 UTF-8。
有关更多详细信息,请参见安全版本 from_utf8
。
Safety
此函数不安全,因为它不检查传递给它的字节是否为有效的 UTF-8。
如果违反了此约束,则 String
的未来用户可能会导致内存不安全问题,因为标准库的其余部分都假定 String
是有效的 UTF-8。
Examples
基本用法:
// vector 中的一些字节
let sparkle_heart = vec![240, 159, 146, 150];
let sparkle_heart = unsafe {
String::from_utf8_unchecked(sparkle_heart)
};
assert_eq!("💖", sparkle_heart);
Run🔬 This is a nightly-only experimental API. (string_extend_from_within
)
string_extend_from_within
)将 src
范围内的元素复制到字符串的末尾。
Panics
如果起始点或结束点不在 char
边界上,或超出边界,就会出现 panic。
Examples
#![feature(string_extend_from_within)]
let mut string = String::from("abcde");
string.extend_from_within(2..);
assert_eq!(string, "abcdecde");
string.extend_from_within(..2);
assert_eq!(string, "abcdecdeab");
string.extend_from_within(4..8);
assert_eq!(string, "abcdecdeabecde");
Run确保此 String
的容量至少比其长度大 additional
字节。
如果选择,容量可能会增加 additional
字节以上,以防止频繁重新分配。
如果您不希望这种 “at least” 行为,请参见 reserve_exact
方法。
Panics
如果新容量溢出 usize
,就会出现 panics。
Examples
基本用法:
let mut s = String::new();
s.reserve(10);
assert!(s.capacity() >= 10);
Run这实际上可能不会增加容量:
let mut s = String::with_capacity(10);
s.push('a');
s.push('b');
// s 现在的长度为 2,容量为 10
assert_eq!(2, s.len());
assert_eq!(10, s.capacity());
// 由于我们已经有 8 个额外的容量,因此称此为...
s.reserve(8);
// ... 实际上并没有增加。
assert_eq!(10, s.capacity());
Run确保此 String
的容量比其长度大 additional
字节。
除非您绝对比分配器更了解,否则请考虑使用 reserve
方法。
Panics
如果新容量溢出 usize
,就会出现 panics。
Examples
基本用法:
let mut s = String::new();
s.reserve_exact(10);
assert!(s.capacity() >= 10);
Run这实际上可能不会增加容量:
let mut s = String::with_capacity(10);
s.push('a');
s.push('b');
// s 现在的长度为 2,容量为 10
assert_eq!(2, s.len());
assert_eq!(10, s.capacity());
// 由于我们已经有 8 个额外的容量,因此称此为...
s.reserve_exact(8);
// ... 实际上并没有增加。
assert_eq!(10, s.capacity());
Run尝试为给 String
至少插入 additional
个元素保留容量。
该集合可以保留更多空间,以避免频繁的重新分配。
调用 reserve
后,容量将大于或等于 self.len() + additional
。
如果容量已经足够,则不执行任何操作。
Errors
如果容量溢出,或者分配器报告失败,则返回错误。
Examples
use std::collections::TryReserveError;
fn process_data(data: &str) -> Result<String, TryReserveError> {
let mut output = String::new();
// 预先保留内存,如果不能,则退出
output.try_reserve(data.len())?;
// 现在我们知道在我们复杂的工作中这不能 OOM
output.push_str(data);
Ok(output)
}
Run尝试保留最小容量,以便在给定的 String
中精确插入 additional
个元素。
调用 reserve_exact
后,容量将大于或等于 self.len() + additional
。
如果容量已经足够,则不执行任何操作。
请注意,分配器可能会给集合提供比其请求更多的空间。
因此,不能依靠容量来精确地最小化。
如果希望将来插入,则首选 try_reserve
。
Errors
如果容量溢出,或者分配器报告失败,则返回错误。
Examples
use std::collections::TryReserveError;
fn process_data(data: &str) -> Result<String, TryReserveError> {
let mut output = String::new();
// 预先保留内存,如果不能,则退出
output.try_reserve_exact(data.len())?;
// 现在我们知道在我们复杂的工作中这不能 OOM
output.push_str(data);
Ok(output)
}
Run删除 String
中所有模式 pat
的匹配项。
Examples
#![feature(string_remove_matches)]
let mut s = String::from("Trees are not green, the sky is not blue.");
s.remove_matches("not ");
assert_eq!("Trees are green, the sky is blue.", s);
Run匹配项将被检测并迭代删除,因此在样式重叠的情况下,仅第一个样式将被删除:
#![feature(string_remove_matches)]
let mut s = String::from("banana");
s.remove_matches("ana");
assert_eq!("bna", s);
Run仅保留谓词指定的字符。
换句话说,删除所有字符 c
,以使 f(c)
返回 false
。
此方法在原地运行,以原始顺序恰好一次访问每个字符,并保留保留字符的顺序。
Examples
let mut s = String::from("f_o_ob_ar");
s.retain(|c| c != '_');
assert_eq!(s, "foobar");
Run由于按原始顺序仅对元素进行过一次访问,因此可以使用外部状态来确定要保留哪些元素。
let mut s = String::from("abcde");
let keep = [false, true, true, false, true];
let mut iter = keep.iter();
s.retain(|_| *iter.next().unwrap());
assert_eq!(s, "bce");
Run返回此 String
的内容的可变引用。
Safety
这个函数是不安全的,因为返回的 &mut Vec
允许写入无效的 UTF-8 字节。
如果违反此约束,则在丢弃 &mut Vec
之后使用原始 String
可能会违反内存安全,因为标准库的其余部分假定 String
是有效的 UTF-8。
Examples
基本用法:
let mut s = String::from("hello");
unsafe {
let vec = s.as_mut_vec();
assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]);
vec.reverse();
}
assert_eq!(s, "olleh");
Run在给定的字节索引处将字符串拆分为两个。
返回新分配的 String
。
self
包含字节 [0, at)
,返回的 String
包含字节 [at, len)
。
at
必须位于 UTF-8 代码点的边界上。
请注意,self
的容量不会改变。
Panics
如果 at
不在 UTF-8
代码点边界上,或者它超出字符串的最后一个代码点,就会出现 panics。
Examples
let mut hello = String::from("Hello, World!");
let world = hello.split_off(7);
assert_eq!(hello, "Hello, ");
assert_eq!(world, "World!");
Run创建一个 draining 迭代器,该迭代器将删除 String
中的指定范围并产生已删除的 chars
。
Note: 即使迭代器直到最后才被消耗,元素范围也会被删除。
Panics
如果起始点或结束点不在 char
边界上,或超出边界,就会出现 panic。
Examples
基本用法:
let mut s = String::from("α is alpha, β is beta");
let beta_offset = s.find('β').unwrap_or(s.len());
// 删除范围直到字符串中的 β
let t: String = s.drain(..beta_offset).collect();
assert_eq!(t, "α is alpha, ");
assert_eq!(s, "β is beta");
// 全范围清除字符串
s.drain(..);
assert_eq!(s, "");
Run1.27.0[src]pub fn replace_range<R>(&mut self, range: R, replace_with: &str) where
R: RangeBounds<usize>,
pub fn replace_range<R>(&mut self, range: R, replace_with: &str) where
R: RangeBounds<usize>,
删除字符串中的指定范围,并将其替换为给定的字符串。 给定的字符串不必与范围相同。
Panics
如果起始点或结束点不在 char
边界上,或超出边界,就会出现 panic。
Examples
基本用法:
let mut s = String::from("α is alpha, β is beta");
let beta_offset = s.find('β').unwrap_or(s.len());
// 替换范围直到字符串中的 β
s.replace_range(..beta_offset, "Α is capital alpha; ");
assert_eq!(s, "Α is capital alpha; β is beta");
RunMethods from Deref<Target = str>
用另一个字符串替换模式的前 N 个匹配项。
replacen
创建一个新的 String
,并将此字符串切片中的数据复制到其中。
这样做时,它将尝试查找某个模式的匹配项。
如果找到任何内容,则最多 count
次将它们替换为替换字符串切片。
Examples
基本用法:
let s = "foo foo 123 foo";
assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
Run当模式不匹配时:
let s = "this is old";
assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
Run以新的 String
返回等效于此字符串切片的小写字母。
‘Lowercase’ 是根据 Unicode 派生核心属性 Lowercase
的术语定义的。
由于更改大小写时某些字符可以扩展为多个字符,因此此函数返回 String
而不是就地修改参数。
Examples
基本用法:
let s = "HELLO";
assert_eq!("hello", s.to_lowercase());
Run一个棘手的示例,使用 sigma:
let sigma = "Σ";
assert_eq!("σ", sigma.to_lowercase());
// 但在单词结尾时,它是 ς,而不是 σ:
let odysseus = "ὈΔΥΣΣΕΎΣ";
assert_eq!("ὀδυσσεύς", odysseus.to_lowercase());
Run不区分大小写的语言不会更改:
let new_year = "农历新年";
assert_eq!(new_year, new_year.to_lowercase());
Run返回此字符串切片的大写等效项,作为新的 String
。
‘Uppercase’ 是根据 Unicode 派生核心属性 Uppercase
的术语定义的。
由于更改大小写时某些字符可以扩展为多个字符,因此此函数返回 String
而不是就地修改参数。
Examples
基本用法:
let s = "hello";
assert_eq!("HELLO", s.to_uppercase());
Run不区分大小写的脚本不会更改:
let new_year = "农历新年";
assert_eq!(new_year, new_year.to_uppercase());
Run一个字符可以变成多个:
let s = "tschüß";
assert_eq!("TSCHÜSS", s.to_uppercase());
Run返回此字符串的副本,其中每个字符都映射为其等效的 ASCII 大写字母。
ASCII 字母 ‘a’ 到 ‘z’ 映射到 ‘A’ 到 ‘Z’,但是非 ASCII 字母不变。
要就地将值大写,请使用 make_ascii_uppercase
。
要除非 ASCII 字符外还使用大写 ASCII 字符,请使用 to_uppercase
。
Examples
let s = "Grüße, Jürgen ❤";
assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
Run返回此字符串的副本,其中每个字符都映射为其等效的 ASCII 小写字母。
ASCII 字母 ‘A’ 到 ‘Z’ 映射到 ‘a’ 到 ‘z’,但是非 ASCII 字母不变。
要就地小写该值,请使用 make_ascii_lowercase
。
要除非 ASCII 字符外还使用小写 ASCII 字符,请使用 to_lowercase
。
Examples
let s = "Grüße, Jürgen ❤";
assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
RunTrait Implementations
实现 +
运算符以连接两个字符串。
这会消费左侧的 String
,并重新使用其缓冲区 (如有必要,请增加缓冲区)。
这样做是为了避免分配新的 String
并在每个操作上复制整个内容,当通过重复连接构建 n 字节的字符串时,这将导致 O(n^ 2) 运行时间。
右侧的字符串仅是借用的。它的内容被复制到返回的 String
中。
Examples
将两个 String
连接起来,第一个按值取值,第二个借用:
let a = String::from("hello");
let b = String::from(" world");
let c = a + &b;
// `a` 已移动,不能再在此处使用。
Run如果要继续使用第一个 String
,则可以对其进行克隆并追加到克隆中:
let a = String::from("hello");
let b = String::from(" world");
let c = a.clone() + &b;
// `a` 在这里仍然有效。
Run可以通过将第一个切片转换为 String
来完成 &str
切片的连接:
let a = "hello";
let b = " world";
let c = a.to_string() + b;
Run从拥有的值中借用。 Read more
用一个元素扩展一个集合。
用一个元素扩展一个集合。
如果存在,则此方法返回 self
和 other
值之间的顺序。 Read more
一个方便的 impl,委派给 &str
的 impl。
Examples
assert_eq!(String::from("Hello world").find("world"), Some(6));
Run此模式的关联搜索者
检查模式是否与 haystack 中的任何位置匹配
检查模式是否在 haystack 的前面匹配
如果匹配,则从 haystack 的正面删除模式。
检查模式是否与 haystack 的后面匹配