Rust字串


Rust包含兩種型別的字串:&strString

String

  • 字串被編碼為UTF-8序列。
  • 在堆記憶體上分配一個字串。
  • 字串的大小可以增長。
  • 它不是以空(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_strpush附加到字串
    push_str():可以使用push_str()函式增加String的大小。它將內容附加在字串的末尾。 假設s1s2是兩個字串,想要將字串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()函式的第一個引數是selfadd()獲取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.

字串中的索引

StringUTF-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]索引表示從索引從字串中的13位置獲取子字串。

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