Rust包含兩種型別的字串:&str
和String
。
String
null
)值終止的序列。&str
&str
也稱為字串切片。&[u8]
表示,指向UTP-8序列。&str
用於檢視字串中的資料。String 和 &str 的區別
String
是一個可變參照,而&str
是對該字串的不可變參照,即可以更改String
的資料,但是不能操作&str
的資料。String
包含其資料的所有權,而&str
沒有所有權,它從另一個變數借用它。在建立向量時類似地建立String
,下面來看看範例:
建立一個空字串:
Let mut s = String::new();
在上面的宣告中,String
是使用new()
函式建立的。 現在,如果想在宣告時初始化String,可以通過使用to_string()
方法來實現。
在資料上實現to_string()
方法:
let a = "Yiibai";
let s = a.to_string();
也可以直接在字串文字上實現to_string
方法:
let s = "Yiibai".to_string();
下面通過一個例子來理解這一點:
fn main()
{
let data="Yiibai";
let s=data.to_string();
print!("{} ",s);
let str="tutorial".to_string();
print!("{}",str);
}
執行上面範例程式碼,得到以下結果 -
Yiibai tutorial
建立String
的第二種方法是使用String::from
函式,它相當於String::new()
函式。下面通過一個簡單的例子來理解這一點:
fn main()
{
let str = String::from("Yiibai tutorial");
print!("{}",str);
}
執行上面範例程式碼,得到以下結果 -
Yiibai tutorial
可以通過將更多資料推播到String
中來更改String
的大小和String
資料的內容。也可以使用格式巨集的+
運算子連線字串值。
push_str
和push
附加到字串push_str()
:可以使用push_str()
函式增加String的大小。它將內容附加在字串的末尾。 假設s1
和s2
是兩個字串,想要將字串s2
附加到字串s1
。s1.push_str(s2);
通過一個簡單的例子來理解這一點:
fn main()
{
let mut s=String::from("java is a");
s.push_str(" programming language");
print!("{}",s);
}
執行上面範例程式碼,得到以下結果 -
java is a programming language
push_str()
函式不接受引數的所有權。下面通過一個簡單的例子來理解。
fn main()
{
let mut s1 = String::from("Hello");
let s2 = "World";
s1.push_str(s2);
print!("{}",s2);
}
執行上面範例程式碼,得到以下結果 -
World
如果push_str()
函式獲取引數的所有權,則程式的最後一行將不起作用,並且不會列印s2
的值。
push()
:push()
函式用於在字串的末尾新增單個字元。假設字串是s1
和字元ch
,它將被新增到字串s1
的末尾。
s1.push(ch);
下面來看一個簡單的範例
fn main()
{
let mut s = String::from("java");
s.push('c');
print!("{}",s);
}
執行上面範例程式碼,得到以下結果-
javac
+
運算子或格式巨集連線+
運算子:+
運算子用於連線兩個字串。下面來看一個範例程式碼:let s1 = String::from("Yiibai ");
let s2 = String::from("tutorial!!");
let s3 = s1+&s2;
再來看看一個簡單的程式碼:
fn main()
{
let s1 = String::from("Yiibai");
let s2 = String::from(" tutorial!!");
let s3 = s1+&s2;
print!("{}",s3);
}
執行上面範例程式碼,得到以下結果 -
Yiibai tutorial!!
在上面的例子中,s3
包含兩個字串串聯的結果,即"Yiibai tutorial!!"
。 s1
不再有效,使用s2
的參照,即&s2
,根據使用+
運算子時呼叫的方法的簽名。+
運算子呼叫add()
方法,其宣告如下:
fn add(self,s:&str)->String
{
}
首先,s2
有&
運算子,意味著新增對s1
的參照。 根據add()
函式的簽名,可以將&str
新增到String
中,並且不能將兩個字串值一起新增。 但是根據add()
方法中指定的第二個引數,s2
的型別是&String
而不是&str
。 但是,仍然可以在add
方法中使用s2
,因為編譯器會將&string
強制轉換為&str
。 因此,當呼叫add()
方法時,Rust使用強制參照。
其次,add()
函式的第一個引數是self
,add()
獲取self
的所有權。 這意味著在語句let s3 = s1 +&s2
之後s1
不再有效;
下面通過一個簡單的例子來理解這一點:
fn main()
{
let s1 = String::from("C");
let s2 = String::from("is");
let s3 = String::from("a");
let s4 = String::from("programming");
let s5 = String::from("language.");
let s = format!("{} {} {} {} {}",s1,s2,s3,s4,s5);
print!("{}",s);
}
執行上面範例程式碼,得到以下結果:
C is a programming language.
String
以UTF-8
序列編碼。 因此,字串無法編入索引。 下面通過一個例子來理解這個概念:
fn main()
{
let s = String::from("Yiibai");
print!("{}",s[1]);
}
執行上面範例程式碼,得到類似以下的結果 -
error[E0277]: the trait bound `std::string::String: std::ops::Index<{integer}>` is not satisfied
--> jdoodle.rs:4:17
|
4 | print!("{}",s[1]);
| ^^^^ the type `std::string::String` cannot be indexed by `{integer}`
|
= help: the trait `std::ops::Index<{integer}>` is not implemented for `std::string::String`
error: aborting due to previous error
通過索引存取非常快。 但是,字串以UTF-8
序列編碼,該序列可以有多個位元組,並且在字串中查詢第n
個字元將證明是昂貴的操作。
字串中未提供索引,因為不知道索引操作的返回型別應具有位元組值,字元或字串切片。 Rust提供了一種更具體的方法來索引字串,方法是在[]
而不是單數位內提供範圍。
範例:
let s = "Hello World";
let a = &s[1..4];
在上面的場景中,s
包含字串文字,即"Hello World"
。 這裡指定[1..4]
索引表示從索引從字串中的1
到3
位置獲取子字串。
fn main() {
let s = "Hello World";
let a = &s[1..4];
print!("{}",a);
}
執行上面範例程式碼,得到以下結果 -
ell
也可以通過其他方式存取字串。使用chars()
方法迭代字串的每個元素。
下面來看一個簡單的例子:
fn main()
{
let s = "C is a programming language";
for i in s.chars()
{
print!("{}",i);
}
}
執行上面範例程式碼,得到以下結果 -
C is a programming language