柚子快報激活碼778899分享:開發(fā)語言 后端 rust字符串
柚子快報激活碼778899分享:開發(fā)語言 后端 rust字符串
0x001
字符串在rust中是一個對象特殊類型,可以理解為char的集合。
rust在核心語言中只有一種String類型,通過borrow的方式&str查看str。
string類型由rust的標準庫提供,而不是編碼為核心語言,是一種可增長、可變、擁有的、UTF-8編碼的string類型。當rustaceans指的是rust中的“string”時,通常指的是string和string slice&str類型,而不僅僅是這些類型中的一種。盡管這一部分主要是關于string的,但這兩種類型在rust的標準庫中都被大量使用,并且string和string slice都是UTF-8編碼的。
rust的標準庫還包括許多其他string類型,例如osstring、osstr、cstring和cstr??梢詾榇鎯tring提供更多的選項。這些類型指的是擁有和借用的變體,和string和str類型一樣。例如,這些字符串可以以不同的編碼存儲文本,或者以不同的方式在內存中表示。
0x002 構造
字符串創(chuàng)建一般有三個方法
fn main(){
let s = String::from("hello 世界”);
let mut s1 = String::new();
s1.push_str("hello 世界);
//s1+="hello 世界"; //與上面的語句等價,即:追加字符串在后面
let s2 = "hello 世界".to_string();
println!("{}", s);
println!("{}", s1);
println!("{}", s2);
}
輸出的結果都是一樣的:
hello 世界
hello 世界
hello 世界
以上三種方法分別調用from函數,new函數以及to_string函數。
其中,from函數和to_string函數函數功能是等價的,只是調用的對象不同而已,作用都是從一個字符串字面量直接構造出一個String來。而new函數則是憑空生產一個String,而且是空的,如果想要讓它存值,就得將它聲明為可變的(mut),之后可以用push_str函數或者+=操作符來追加字符串。
除此之外還有一個函數with_capacity:
let s = String::with_capacity(100);
它的作用與new基本相同,唯一不同的是,這個函數需要一個參數來初始化其內部的內存大小,如果你事先知道自己需要多大的內存,那么建議你使用這個函數來構造一個String而不是new。
0x003 遍歷
對字符串的遍歷,用到兩個函數:as_bytes與chars
1.遍歷字符串的所有字節(jié)
fn main(){
let s = String::from("hello 世界");
for i in s.as_bytes(){
println!("{}",i);
}
}
輸出結果:
104 101 108 108 111 32 228 184 150 231 149 140
hello分別對應前面的104 101 108 111 ,中間空格對應的是32,”世界“對應的是228 184 150 和231 149 140
2.使用chars函數遍歷字符串
fn main(){
let s =Strig::from("hello 世界");
for i in s.chars(){
println!("{}",i);
}
}
輸出結果
h e l l o 世 界
如果想要取出第幾個字符,使用函數nth:
fn main(){
let s = String::from("hello 世界");
let mut m = s.chars();
let c = m.nth(7);
if let Some(t) = c { //取出返回值中攜帶的字符
println!("{}",t);
}
}
輸出結果: 界
//更簡潔的寫法
fn main(){
let s = String::from("hello 世界");
let c = s.chars().nth(7);
if let Some(t) = c {
println!("{}", t);
}
}
還能更簡潔:
fn main(){
let s = String::from("hello 世界");
let c = s.chars().nth(7).unwrap();
println!("{}", c);
}
unwrap函數是option這個trait的一個函數,等價于:
fn main(){
let s = String::from("hello 世界");
let c = s.chars().nth(7);
let r = match c {
Some(t) => t,
None => panic!("")
};
println!("{}", r);
}
0x004 容量操作
字符串為實現內容可變,必須要預留一定的空間,為此rust提供了一些函數。
reserve():為字符串新增一些空間shrink_to_fit():將字符串的容量縮小到它所包含的內容所需要的最小值。shrink_to():將字符串的容量縮小到指定下限。如果當下容量小于下線,或者大于當前值,則什么也不做。
fn main(){
let mut s = "micro cold".to_string();
println!("original capacity = {}", s.capacity());
s.reserve(10);
println!("after reserve = {}", s.capacity());
s.shrink_to_fit();
println!("fit capacity = {}", s.capacity());
s.shrink_to(25);
println!("fit to 25 = {}", s.capacity());
}
//輸出結果
original capacity = 10
after reserve = 20
fit capacity = 10
fit to 25 = 10
0x005 增刪改查
String是可變字符串,所有提供了增加,刪除,插入等操作
類別方法 彈出與追加???????? 追加字符push;追加字符串push_str;彈出最后一個字符pop刪除清空clear;截短truncate;刪除某位置remove;匹配刪除remove_matches插入插入字符insert;插入字符串insert_str替換匹配替換replace;位置替換replace_range;匹配從左查找find;從右查找rfind;均返回第一個匹配的位置
上述方法進行測試:
fn main(){
let mut s = "micro cold".to_string();
s.push("a");
println!("push("a") -> {}", s);
s.push_str("bcd");
println!("push_str("\bcd\") -> {}", s);
s.truncate(10);
println!("truncate(3) -> {}", s);
s.remove(1);
println!("remove(1) -> {}", s);
s.insert(1, 'i');
println!("insert(1, 'i') -> {}"), s);
s.insert_str(0, "hello");
println!("insert_str(0, \"hello\" -> {}", s);
s.replace_range(0..5,"Hola");
println!("replace_range(0..5, \"Hola\" -> {}", s);
println!("s.replace(\"Hola\",\"你好\") -> {}", s.replace("Hola", "你好"));
}
//測試結果
push('a') -> micro colda
push_str("bcd") -> micro coldabcd
truncate(3) -> micro cold
remove(1) -> mcro cold
insert(1, 'i') -> micro cold
insert_str(0, "hello ") -> hello micro cold
replace_range(0..5, "Hola") -> Hola micro cold
s.replace("Hola", "你好") -> 你好 micro cold
0x006 字符串切片
字符串切片:指向String對象某個連續(xù)部分的引用。
切片的類型為:&str
使用形式:[starting_index..ending_index],其中,starting_index是切片起始位置的索引值,ending_index是切片終止位置的下一個位置的索引值。
注意:字符串字符串切片的范圍索引必須發(fā)生在有效的UTF-8字符邊界內,如果嘗試從一個多字節(jié)中創(chuàng)建字符串切片,程序會報錯并退出。
字符串字面量就是切片
let s = "Hello world";
變量s 的類型就是&str:它是一個指向二進制程序特定位置的切片。因為&str是一個不可變的引用,所有字符串字面量是不可變的。
fn main(){
let s = String::from("hello world");
let hello = &s[0..5];//如果要從索引0開始,可以不寫兩個點號之前的值 let hello =&s[..5];
let world = &s[6..11];//如果slice包含String的最后一個字節(jié),也可以舍棄尾部的數字 let world =&s[6..];
println!("{},{}",hello, world)
//也可以同時舍棄這兩個值來獲取整個字符串的slice
let s1 = &s[..];
//等價于
let len = s.len()
let s1 = &s[0..len];
}
0x007 String和str類型的轉換
字符串字面量可以轉換為String。相反,String也可以轉換成str。
通過解引用操作實現。
impl Deref for String{
fn deref(&self) -> &str{
unsafe{ str::from_utf_unchecked(&self.vec) }
}
}
利用解引用操作就可以將String轉換成str:
let s: String = String::from("Hello");
let ss: &str = &s;
連接一個str字符串:
let s = String::from("Hello");
let b = ",world!";
let f = s +b; // f == "Hello,world!"
連接兩個String對象,不能簡單的直接相加。必須先通過解引用將后一個對象轉換為&str才能進行連接:
let s = String::from("Hello");
let b = String::from(",world");
let f = s + &b; // f == "Hello,world"
//字符串連接之后,s的所有權發(fā)生了轉移,而b的內容復制到了新的字符串中。
從String到str的轉換是廉價的,相反,從str轉換String需要分配新的內存。
當定義函數的參數時,&str會比String更加通用:因為此時既可以傳遞&str對象,也可以傳遞String對象。
字符串轉整數
fn main(){
let my_string = "27".to_string();
let my_int = my_string.parse::
println!("{:?}", my_string);
println!("{:?}", my_int);
}
包含字符串
fn main(){
let a = "abcd";
println!("{:?}, a.contains("bc");
}
計算字節(jié)長度
fn main(){
let s1 = "中國-China";
println!("{:?}",s1.len()); //12
let s2 = String::from("中國-China");
println!("{:?}",s2.len()); //12
}
計算字符個數
fn main(){
let s1 = "中國-China";
println!("{:?}", s1.chars().count()); //8
let s2 = String::from("中國-China");
println!("{:?}", s2.chars().count()); //8
截取指定開始的n個的字符
fn substr(s: &str, start: usize, length: usize) -> String{
s.chars().skip(start).take(length).collect()
}
fn main(){
let s1 = "中國-China";//let s1 = String::from("中國-China");
println!(":?}",substr(s1,1,100));
println!({:?}",substr(s1,0,2));
}
獲取指定位置開始的n個字節(jié)(如果存在非法的字符邊界,則返回None)
fn main(){
let mut s String::from("中國-China");
println!("{:?}", s.get(0..=5)); //some("中國")
println!("{:?}", s.get(0..=4)); //None
}
判斷是不是以某個字符串結尾
fn main(){
let s1 = "中國-China"; // let s1 = String::from("中國-China");
assert_eq!(true, s1.ends_with("China"));
}
全部轉為大寫或小寫
fn main(){
let s1 = "中國-China"; // let s1 = String::from("中國-China");
println!("{:?}",s1.to_uppercase()); //中國-CHINA
//與to_uppercase()的不同
let mut s2 = String::from("中國-China");
s2.make_ascii_uppercase();
println!("{:?}", s2); //中國-CHINA
}
//全部轉換為小寫
fn main(){
let s1 = "中國-China"; // let s1 = String::from("中國-China");
println!("{:?}",s1.to_lowercase()); //中國-china
//與to_lowercase()的不同
let mut s2 = String::from("中國-China");
s2.make_ascii_lowercase();
println!("{:?}", s2); //中國-china
}
判斷是不是ASCII字符串
fn main(){
let s1 = "中國-China";
let s2 = "China';
assert_eq!(false, s1.is_ascii());
assert_eq!(true, s2.is_ascii());
}
判斷指定位置是不一個合法的UTF-8邊界,比如說漢字的UTF-8包含三個字節(jié),那么第一個字節(jié)的結束位置必然不是一個合法的UTF-8邊界(更準確的說,應該時這個位置是不是一個合法的字符的開始)
fn main(){
let mut s1 = String::from("中國-China");
assert_eq!(true, s1.is_char_boundary(0));
assert_eq!(true, s1.is_char_boundary(12));
assert_eq!(false, s1.is_char_boundary(2));
assert_eq!(true, s1.is_char_boundary(3));
}
字符串替換
fn main(){
let mut s = String::from("中國-China");
println!("{:?}", s.replace("中國", "China");
}
字符串切割
fn main(){
let mut s = String::from("中國-China');
let result: Vec<&str> = s.split("-").collect();
println!("{:?}", result); //["中國","China"]
}
//分離:s.split("separator")
//空白:s.split_whitespace()
//換行符:s.lines()
trim類有六個函數,trim、trim_left、trim_right、trim_matches、trim_left_matches、trim_right_matches
//trim
let s = "Hello\tword\t";
assert_eq!("Hello\tword\", s.trim());
//trim_left
let s = "Hello\tword\t";
assert_eq!("Hello\tword\", s.trim_left());
//trim_right
let s = "Hello\tword\t";
assert_eq!("Hello\tword\", s.trim_right());
//trim_matches
assert_eq!("11foolbar11".trim_matches('1'),"foolbar");
assert_eq!("123foolbar123".trim_matches(char::is_numeric), "foolbar");
let x: &[_] = &['1', '2'];
assert_eq!("12foolbar12".trim_matches(x), "foolbar");
//trim_left_matches
assert_eq!("11foolbar11".trim_letf_matches('1'),"foolbar11");
assert_eq!("123foolbar123".trim_left_matches(char::is_numeric), "foolbar123");
let x: &[_] = &['1', '2'];
assert_eq!("12foolbar12".trim_matches(x), "foolbar12");
assert_eq!("1fooX".trim_left_matches(|c| == '1' || c == 'X'), "fooX");
//trim_right_matches
assert_eq!("11foolbar11".trim_right_matches('1'),"11foolbar");
assert_eq!("123foolbar123".trim_right_matches(char::is_numeric), "123foolbar");
let x: &[_] = &['1', '2'];
assert_eq!("12foolbar12".trim_right_matches(x), "12foolbar");
柚子快報激活碼778899分享:開發(fā)語言 后端 rust字符串
參考文章
本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。