Поиск…
Вступление
String
(тип строки, выделенной кучей) и &str
( заимствованная строка, которая не использует дополнительную память). Знать разницу и когда использовать каждый, важно понять, как работает Руста.
Базовая манипуляция строками
fn main() {
// Statically allocated string slice
let hello = "Hello world";
// This is equivalent to the previous one
let hello_again: &'static str = "Hello world";
// An empty String
let mut string = String::new();
// An empty String with a pre-allocated initial buffer
let mut capacity = String::with_capacity(10);
// Add a string slice to a String
string.push_str("foo");
// From a string slice to a String
// Note: Prior to Rust 1.9.0 the to_owned method was faster
// than to_string. Nowadays, they are equivalent.
let bar = "foo".to_owned();
let qux = "foo".to_string();
// The String::from method is another way to convert a
// string slice to an owned String.
let baz = String::from("foo");
// Coerce a String into &str with &
let baz: &str = &bar;
}
Примечание. Оба метода String::new
и String::with_capacity
будут создавать пустые строки. Однако последний выделяет начальный буфер, что делает его изначально медленнее, но помогает сократить последующие распределения. Если конечный размер String известен, String::with_capacity
следует использовать String::with_capacity
.
Строчная нарезка
fn main() {
let english = "Hello, World!";
println!("{}", &english[0..5]); // Prints "Hello"
println!("{}", &english[7..]); // Prints "World!"
}
Обратите внимание, что нам нужно использовать оператор &
. Он принимает ссылку и, таким образом, дает компилятору информацию о размере типа среза, который ему нужно распечатать. Без справки, два println!
вызовы будут ошибкой времени компиляции.
Предупреждение: Нарезка работает смещением байта , а не смещением символа, и будет паниковать, если границы не находятся на границе символа:
fn main() {
let icelandic = "Halló, heimur!"; // note that “ó” is two-byte long in UTF-8
println!("{}", &icelandic[0..6]); // Prints "Halló", “ó” lies on two bytes 5 and 6
println!("{}", &icelandic[8..]); // Prints "heimur!", the “h” is the 8th byte, but the 7th char
println!("{}", &icelandic[0..5]); // Panics!
}
Это также является причиной того, что строки не поддерживают простую индексацию (например, icelandic[5]
).
Разделить строку
let strings = "bananas,apples,pear".split(",");
split
возвращает итератор.
for s in strings {
println!("{}", s)
}
И может быть «собран» в Vec
с помощью Iterator::collect
.
let strings: Vec<&str> = "bananas,apples,pear".split(",").collect(); // ["bananas", "apples", "pear"]
От заемных до принадлежащих
// all variables `s` have the type `String`
let s = "hi".to_string(); // Generic way to convert into `String`. This works
// for all types that implement `Display`.
let s = "hi".to_owned(); // Clearly states the intend of obtaining an owned object
let s: String = "hi".into(); // Generic conversion, type annotation required
let s: String = From::from("hi"); // in both cases!
let s = String::from("hi"); // Calling the `from` impl explicitly -- the `From`
// trait has to be in scope!
let s = format!("hi"); // Using the formatting functionality (this has some
// overhead)
Помимо format!()
Все вышеперечисленные методы одинаково быстры.
Разрыв длинномерных литералов
Разрыв регулярных строковых литералов с символом \
let a = "foobar";
let b = "foo\
bar";
// `a` and `b` are equal.
assert_eq!(a,b);
Перерыв строк строки для разделения строк, и присоединиться к ним с concat!
макрос
let c = r"foo\bar";
let d = concat!(r"foo\", r"bar");
// `c` and `d` are equal.
assert_eq!(c, d);