前言
rust中的String
,是一個非常常用的crate
,它的底層涉及到了rust中的所有權(quán)概念,不過這不是本章的內(nèi)容,如果對rust所有權(quán)概念感興趣的,可以查看另一篇文章:rust所有權(quán)
本文的目的還是介紹String
的基本用法,以及有哪些常用的函數(shù)可以使用
一、基本概念
字符串,也就是由一系列字符組成的,而在計(jì)算機(jī)中存儲一個字符,用到的字節(jié)數(shù)量并不完全相同。
比如下面的代碼:
fn main() {
let s1=String::from("h");
let s2=String::from("你");
println!("{} {}",s1.len(),s2.len());
}
同樣是一個字符,只不過s1
是英文字符,s2
是中文字符,所使用的空間就不是一樣大的:
1 3
一個英文字符用1
個字節(jié)大小,而一個中文字符卻要用3
個字節(jié)大小
之所以出現(xiàn)這個現(xiàn)象,是因?yàn)?code>rust中的字符串String
為了更加的通用化,采用的是UTF-8
編碼,它可以容納世界上絕大多數(shù)的字符,比如英文、中文、日文、阿拉伯文等等
一般我們windows電腦采用的是本地化編碼,比如我是中國地區(qū),用的就是屬于中國的
GBK
或者GB2312
編碼,這個編碼只能存放中文字符,一旦遇到其它國家的字符,比如日文,就會出現(xiàn)亂碼
當(dāng)然了,有這個功能的并不只有utf-8,還有utf-16,utf-32等等
但它的好處就是,這個字符需要多大,就給他多大的空間,可以節(jié)約內(nèi)存,如果換用utf-16
,那么無論中英文都采用2個字節(jié),如果為utf-32
,無論中英文都采用4個字節(jié)
這樣做的好處是大家都一樣大,不用計(jì)算,就能取出對應(yīng)的字符,而缺點(diǎn)就是占用空間大,尤其是對于使用英文的地區(qū),就太虧了,明明一個字節(jié)就能存放他們一個字母,現(xiàn)在卻需要兩個字節(jié)、甚至四個字節(jié)!
而utf-8編碼的優(yōu)缺點(diǎn)則剛好與他們相反:節(jié)約空間,但效率較低
節(jié)約空間:英文就用一個字節(jié)表示,中文就用三個字節(jié)表示,阿拉伯文就用兩個字節(jié)表示等等,可以最大限度地節(jié)約空間
效率較低:因?yàn)椴煌址加玫貎?nèi)存大小不一,所以想要取出一個字符,就必須進(jìn)行遍歷、判斷,所以效率較低(如果為
utf-16
,每次讀取兩個字節(jié)就行了,無需判斷每個字節(jié)長什么樣,這也是為什么window底層采用utf-16
而不是utf-8
編碼,就是為了提高運(yùn)行速度)
正因?yàn)?code>utf-8編碼的這一特性,導(dǎo)致了我們無法像c語言那樣,可以直接遍歷字符串中的所有字符:
fn main() {
let s=String::from("hello 世界");
for i in s{ //錯誤,無法直接遍歷
}
}
同樣的,你也無法直接用下標(biāo)取出對應(yīng)的字符
fn main() {
let s=String::from("hello 世界");
let c=s[0]; //錯誤,不能直接用下標(biāo)取出字符
}
因?yàn)槊總€字符占用的內(nèi)存大小不一,所以它不知道你是想要取出字符,才是想要取這個位置上的字節(jié)
二、構(gòu)造
既然是學(xué)習(xí)String
,那么第一件事就是了解我們應(yīng)該怎么創(chuàng)建一個String
創(chuàng)建String
,一般有三個方法,如下:
fn main() {
let s=String::from("hello 世界");
let mut s1=String::new();
s1.push_str("hello 世界");
//s1+="hello 世界"; //與上面的語句等價(jià),即:追加字符串在后面
let s2="hello 世界".to_string();
println!("{}", s);
println!("{}", s1);
println!("{}", s2);
}
三個方法分別是調(diào)用from
函數(shù)、new
函數(shù)以及to_string
函數(shù)
其中,from
函數(shù)與to_string
函數(shù)函數(shù)功能是等價(jià)的,只是調(diào)用的對象不同而已,作用都是從一個字符串字面量直接構(gòu)造出一個String
來
而new
函數(shù)則是憑空產(chǎn)生一個String
,并且為空,如果想要讓它存值,就得將他聲明為可變的(mut
),之后可以用push_str
函數(shù)或者+=
操作符來追加字符串
最后輸出的結(jié)果都是一樣的:
hello 世界
hello 世界
hello 世界
除此之外,還有一個函數(shù)為with_capacity
:
let s=String::with_capacity(100);
它的作用與new
基本相同,唯一不同之處在于,這個函數(shù)需要一個參數(shù)來初始化其內(nèi)部的內(nèi)存大小,如果你事先知道自己需要多大的內(nèi)存,那么建議你使用這個函數(shù)來構(gòu)造一個String
而不是用new
至于原因,可以參考后文的:長度與容量
三、遍歷
接下來,我們首先要看的就是如何對字符串進(jìn)行遍歷,用到兩個函數(shù):as_bytes
與chars
首先是as_bytes
函數(shù),看名字也知道,它的意思就是:作為字節(jié)
所以它的功能就是遍歷字符串的所有字節(jié),就可以這樣寫:
fn main() {
let s=String::from("hello 世界");
for i in s.as_bytes(){
print!("{} ",i);
}
}
它的作用就是遍歷所以的字節(jié)值,打印結(jié)果如下:
104 101 108 108 111 32 228 184 150 231 149 140
其中,hello
,就分別對應(yīng)著前面的104 101 108 108 111 32
最后一個
32
,是中間的空格
而世界
兩個字,則分別對應(yīng)228 184 150
和231 149 140
由于都是一個字節(jié),所以這個as_bytes
返回的是一個字節(jié)數(shù)組,我們就可以字節(jié)通過下標(biāo)獲取第幾個字節(jié):
let cs=s.as_bytes();
let c=cs[1]; //取出第二個字節(jié)(從0算起,第二個字節(jié)的下標(biāo)為1)
或者也可以簡寫為:
let c=s.as_bytes()[1]; //取出第二個字節(jié)(從0算起,第二個字節(jié)的下標(biāo)為1)
除了as_bytes
可以返回字節(jié)數(shù)組外,還可以使用bytes
函數(shù)返回字符迭代器:
fn main() {
let s=String::from("hello 世界");
let mut b=s.bytes(); //返回字節(jié)迭代器
println!("{}",b.next().expect("err")); //打印第一個
println!("{}",b.next().expect("err")); //打印第二個
println!("{}",b.next().expect("err")); //打印第三個
println!("{}",b.next().expect("err")); //打印第四個
//...
//上面的代碼等價(jià)于下面的寫法:
for i in s.bytes(){
println!("{}",i);
}
}
顯然這個函數(shù)并不如上面的as_bytes
好用,這個就見仁見智了。
不過大多數(shù)時(shí)候,上面這種遍歷的方式并不是我們想要的,我們只想要取出其中的第幾個字符而已
這時(shí),我們就可以用到chars
函數(shù),作用就是將其作為字符看待:
fn main() {
let s=String::from("hello 世界");
for i in s.chars(){
print!("{} ",i);
}
}
這時(shí)輸出的結(jié)果就是:
h e l l o 世 界
成功將對應(yīng)的字符給取了出來
如果你想要取出第幾個字符,就可以用函數(shù)nth
:
fn main() {
let s=String::from("hello 世界");
let mut m=s.chars(); //得到迭代器
let c=m.nth(7); //得到下標(biāo)為7的Option<char>返回值
if let Some(t) = c { //取出返回值中攜帶的字符
print!("{}",t);
}
}
這里得到的結(jié)果就是界
字
更加簡潔的寫法就是:
fn main() {
let s=String::from("hello 世界");
let c=s.chars().nth(7); //得到下標(biāo)為7的Option<char>返回值
if let Some(t) =c { //取出返回值中攜帶的字符
print!("{}",t);
}
}
上面的寫法應(yīng)該還是很好理解的,就是將chars
的返回值字節(jié)調(diào)用nth
函數(shù)
當(dāng)下面這個取值的操作才是有點(diǎn)麻煩了,所以我們還能更簡潔:
fn main() {
let s=String::from("hello 世界");
let c=s.chars().nth(7).unwrap(); //取出下標(biāo)7的字符
print!("{}", c);
}
這里的unwrap
函數(shù)是Option
這個trait的一個函數(shù),等價(jià)于:
fn main() {
let s=String::from("hello 世界");
let c=s.chars().nth(7);
let r = match c {
Some(t) => t,
None => panic!("")
};
print!("{}", r);
}
如果不會這個用法的,可以參考我的其它文章,這里不再過多贅述
三、長度與容量
說到長度與容量,就不得不提及它的底層原理了。
因?yàn)?code>String本質(zhì)上是在堆上面分配的內(nèi)存,也只有在堆上分配內(nèi)存,才能滿足我們想要動態(tài)修改字符串的目的。
與之相對應(yīng)的是棧,堆與棧的概念在C/C++中聽到的應(yīng)該比較多,同時(shí)本套教程也是面對至少了解C/C++的程序員準(zhǔn)備的,所以這里不再過多解釋,如果不理解的可以自行瀏覽器搜索相關(guān)內(nèi)存進(jìn)行了解
而在你聲明一個String
后,編譯器并不知道你后面會不會再對它進(jìn)行修改,所以一般來說,它會申請一個比你預(yù)料中的要大上一些的內(nèi)存,如果你后面想要追加、插入數(shù)據(jù)。就不用重新去開辟內(nèi)存,而是直接在后面追加
長度與容量分別對應(yīng)的函數(shù)為:len()
, capacity()
比如下面這段代碼:
fn main() {
let s=String::from("hello 世界");
print!("{} {}", s.len(),s.capacity());
}
因?yàn)槭侵苯訌囊粋€字面量生成的String
,而一般這樣的行為大多數(shù)都不會再追加數(shù)據(jù)了,所以其默認(rèn)行為就是容量與長度同樣大:
12 12
但如果你用new
的方式:
fn main() {
let mut s=String::new();
s.push('c');
print!("{} {}", s.len(),s.capacity());
}
這里生成了一個String,并用push函數(shù)向里面推入一個字符,此時(shí)結(jié)果為:
1 8
此時(shí),雖然你只用了1個字節(jié),但實(shí)際上它有8個字節(jié)的容量,這樣就保證了你之后如果還想要繼續(xù)往里面推入數(shù)據(jù),就不用重新開辟內(nèi)存了
重新開辟內(nèi)容就意味著,要將這塊內(nèi)存上的數(shù)據(jù)拷貝到新內(nèi)存,并釋放掉原本的內(nèi)存,這是一個非常影響程序效率的事情
也正因如此,如果你提前知道需要多大的內(nèi)存,那就可以用函數(shù)with_capacity
來創(chuàng)建一個String
:
let mut s=String::with_capacity(1024); //提前分配好足夠大的內(nèi)存,避免后續(xù)出現(xiàn)拷貝
它的唯一一個參數(shù)就是你需要多大的內(nèi)存
四、增刪改查
對于數(shù)據(jù)的操作,無非就是增、刪、改、查這四種
所以這里我們再盡量詳盡的介紹一下這四種操作
1.增
首先是增,前面我們已經(jīng)見過兩個函數(shù)了:push_str
與push
兩個函數(shù)
fn main() {
let mut s=String::new();
s.push_str("string"); //推入一個字符串
s.push('c'); //推入一個字符
}
這兩個函數(shù)的區(qū)別就在于,前一個是用來向原字符串后面追加字符串的,而后一個則是用來追加字符的
除了調(diào)用函數(shù),我們還可以方便的使用符號來代替
fn main() {
let mut s=String::new();
s+="string"; //推入一個字符串
//上面這句,等價(jià)于:s=s+"string";
//s=s+'c'; //錯誤,對于字符類型的,只能使用push函數(shù)
//或者通過下面這種方式:先將字符轉(zhuǎn)換為String,然后前面添加&符號,代表對字符串的引用
s+=&'c'.to_string();
}
但這種操作太單一了,只能在后面推入數(shù)據(jù),很多時(shí)候我們還想要在前面、中間位置插入數(shù)據(jù)該怎么做呢?
這時(shí)候就可以使用insert
與insert_str
函數(shù)了:
fn main() {
let mut s=String::new();
s+="string"; //推入一個字符串
s.insert_str(0, "prestr "); //在0字節(jié)位置插入字符串
s.insert(0,'中'); //在0字節(jié)位置插入字符
println!("{}", s);
}
其作用同樣是一個插入字符串、一個插入字符
特別要注意的是,它的第一個參數(shù)代表要插入的位置,而這個位置是按字節(jié)算的,從0
開始
比如從前面我們就已經(jīng)知道了,一個中文漢字在utf-8編碼中需要用到3個字節(jié),那如果這時(shí)候,我在插入了一個’中‘
字后,在第1個字節(jié)位置插入一個’國‘
字,就會直接引起程序崩潰:
fn main() {
let mut s=String::new();
s+="string"; //推入一個字符串
s.insert(0,'中'); //在0字節(jié)位置插入字符
s.insert(1, '國'); //'中'字占3個字節(jié),如果這時(shí)候在1位置插入,就會引起程序崩潰
println!("{}", s);
}
這個時(shí)候,最好是對要插入的位置進(jìn)行檢測:
if s.is_char_boundary(1){
s.insert(1, '國');
}
通過函數(shù)is_char_boundary
來檢測指定想要插入的位置是不是字符的邊界,如果是字符的邊界,那就代表我們可以插入字符,否則就不能插入字符
2.刪
說完了增,下面我們再來說一說刪,主要用到的函數(shù)就是remove
與remove_matches
首先是remove
函數(shù),它的作用是刪除一個字符:
fn main() {
let mut s="哈嘍 world".to_string();
s.remove(0); //刪除第0字節(jié)開始位置的字符
println!("{}", s);
}
這里我特意在字符串中放置了中文,就是為了讓你能夠更加明悟這一點(diǎn),因?yàn)橐粋€中文字符是占用的3個字節(jié)
運(yùn)行后輸出的代碼為:
嘍 world
也就是說,它的作用是移除從0字節(jié)開始的第一個字符,因?yàn)檫@是一個中文,占用三個字節(jié),所以實(shí)際上它移除了三個字節(jié)
如果你像這樣寫,程序就會直接崩潰:
fn main() {
let mut s="哈嘍 world".to_string();
s.remove(1); //刪除第1字節(jié)開始位置的字符
println!("{}", s);
}
因?yàn)榈谝粋€字節(jié)所在的位置不是字符邊界,它在第一個中文字符占用的三個字節(jié)中間
除了刪除單個直接外,我們還可以使用remove_matches
函數(shù)來刪除子字符串,不過由于這個函數(shù)似乎還不穩(wěn)定,所以暫時(shí)還用不了:
可能再過不久就會添加進(jìn)來了,這里可以先了解一下
它的作用就是刪除所有匹配到的子字符串
如果正常運(yùn)行,那么上面的代碼結(jié)果應(yīng)該就是:
world
除了上面兩個函數(shù)外,我們還可以使用函數(shù)drain
來刪除指定范圍類的字符串:
fn main() {
let mut s="hello 哈嘍 world".to_string();
s.drain(0..5);
println!("{}", s);
}
打印結(jié)果為: 哈嘍 world
注意這個函數(shù)的返回值,就是被刪除的子字符串,如果你想要保留,可以用下面這個辦法:
fn main() {
let mut s="hello 哈嘍 world".to_string();
let m:String=s.drain(0..5).collect(); //將刪除的字符串轉(zhuǎn)換為String并返回
println!("{}", m); //得到被刪除的子字符串
}
除了上面用來刪除字符的函數(shù),我們還可以用另外一個函數(shù)replace_range
來代替:
fn main() {
let mut s="哈嘍 world 哈嘍".to_string();
s.replace_range(0..6, "");
println!("{}", s);
}
它的第一個參數(shù)是一個范圍,可以用上面代碼中的語法書寫(同樣要注意邊界問題)
然后第二個參數(shù)就要要取代的內(nèi)容,我們可以直接將其設(shè)置為空字符串即可,這樣就完成了刪除操作
除了這些,我們還可以直接清空里面的內(nèi)容,調(diào)用clear
函數(shù)即可:
fn main() {
let mut s="哈嘍 world 哈嘍".to_string();
s.clear(); //清空
println!("{}", s);
}
3.改
接下來要介紹的就是String中的改操作,使用到的函數(shù)就是replace
系列方法
比如下面的代碼:
fn main() {
let s="哈嘍 world 哈嘍".to_string();
let ret=s.replace("world","世界");
println!("{}",ret);
}
它的作用就是搜尋字符串中所有能匹配到第一個參數(shù)的子字符串,并將其替換為第二個參數(shù),最后將替換完成的結(jié)果返回
注意,它不會修改原字符串的內(nèi)容,而是重新開辟的一塊內(nèi)存來存放結(jié)果
這時(shí)候,輸出的結(jié)果為:
哈嘍 世界 哈嘍
如果想要直接修改原字符串,那就可以使用replace_range
函數(shù):
fn main() {
let mut s="哈嘍 world 哈嘍".to_string();
s.replace_range(7..12, "世界");
println!("{}",s);
}
使用這個函數(shù)唯一要注意的地方就在于,它的第一個參數(shù)為一個范圍,如果字符串中存在中文,就一定要注意這個范圍是指代的字節(jié)數(shù)組的范圍,一定要在字符的邊界上面,否則程序會字節(jié)崩潰
比如這里之所以是從7開始,是因?yàn)橐粋€漢字占用三個字節(jié),這里有兩個函數(shù)外加一個空格,所以就是從7開始的,而world這個單詞占用5個字節(jié),7+5=12,所以范圍為:
7..12
4.查
對于字符串,查找的操作也是非常常用的,用到的函數(shù)名稱也非常的直白,就是find
:
fn main() {
let s="哈嘍 world 哈嘍".to_string();
let i1=s.find('哈'); //查找字符
if let Some(t) = i1{
println!("查詢到的位置為:{}",t);
}else{
println!("沒有找到");
}
let i1=s.find("world"); //查找指定的字符串
if let Some(t) = i1{
println!("查詢到的位置為:{}",t);
}else{
println!("沒有找到");
}
}
這個函數(shù)既可以查早字符、也可以查早字符串,用起來還是非常方便的
它在查詢后就會得到一個結(jié)果,為Option<usize>
類型,可以用match
或者if let
語法取出里面的值
我這里為了方便,就直接用if let
語句了
其結(jié)果為:
查詢到的位置為:0
查詢到的位置為:7
但你會發(fā)現(xiàn),這個字符串中有兩個哈嘍
,第一個查詢語句查詢的哈
這個字符,就只返回了前面那個哈
字的位置
這時(shí),你就可以調(diào)用另一個rfind
函數(shù),它的作用是查找最后一次出現(xiàn)的位置,也就是從后面向前找:
fn main() {
let s="哈嘍 world 哈嘍".to_string();
let i1=s.rfind('哈'); //查找字符
if let Some(t) = i1{
println!("查詢到的位置為:{}",t);
}else{
println!("沒有找到");
}
let i1: Option<usize>=s.rfind("world"); //查找指定的字符串
if let Some(t) = i1{
println!("查詢到的位置為:{}",t);
}else{
println!("沒有找到");
}
}
這時(shí)的結(jié)果就為:
查詢到的位置為:13
查詢到的位置為:7
如果你想要獲取指定位置的子字符串,就可以用get
函數(shù):
fn main() {
let s="hello,world".to_string();
let ret=s.get(0..5).expect("error");
println!("{}", ret);
}
五、分隔
除了一般的增刪改查外,我們有時(shí)候還會有其它很多必要的操作,比如切割字符串
這時(shí)候就可以用splite
系列函數(shù)了,比如下面這段代碼:
fn main() {
let s="哈嘍world世界world你好呀".to_string();
let ret=s.split("world");
for i in ret{
println!("{}", i);
}
}
我想要取出上面代碼中的所有中文的子字符串,而各個中文子字符串都是用的world
這個單詞分隔的,那就可以用到splite
這個函數(shù)了
它的作用就是用傳入的參數(shù)將原本的字符串用這個字符串分隔開,然后返回第一個可遍歷結(jié)果的迭代器,隨后直接用for
循環(huán)就可以遍歷它得到結(jié)果
哈嘍
世界
你好呀
比較常見的一個用途就是分隔路徑,比如下面這個代碼:
fn main() {
let s="D:/a/b/c/d/file.txt".to_string();
let ret=s.split('/');
for i in ret{
println!("{}", i);
}
}
就可以很方便的得到各個部分結(jié)果(這里用的是字符參數(shù),也是可以的,上面用的是字符串作為參數(shù)):
D:
a
b
c
d
file.txt
而有時(shí)候,我們并不想要遍歷,只想取出其中某一部分,那就可以調(diào)用collect
函數(shù),可以返回一個向量:
fn main() {
let s="D:/a/b/c/d/file.txt".to_string();
let ret:Vec<_>=s.split('/').collect();
println!("{}", ret[5]);
}
這樣就可以直接通過下標(biāo)來獲取對應(yīng)位置的數(shù)據(jù)了,非常的方便
不知道向量用法,請查看我的其它文章
上面這個函數(shù)默認(rèn)是全部分隔的,但有時(shí)候我們可能只想分隔部分,那就還可以使用其它的類似函數(shù)
比如split_once
函數(shù),意思是只分隔一次:
fn main() {
let s="hello=world=yes".to_string();
let (f,b)=s.split_once('=').expect("not find");
print!("{} {}",f,b);
}
注意它的返回值為Option
,這里為了方便就直接調(diào)用expect
函數(shù)取得里面的值,如果沒找到這個分隔符號就直接報(bào)錯
它的返回值為:
hello world=yes
這個splite
還有一些非常方便的相似函數(shù)可以供我們使用,但使用方法都基本類似,下面直接用代碼演示:
按空格分割的函數(shù):split_ascii_whitespace
fn main() {
let s="a b \n c \t d".to_string();
let ret=s.split_ascii_whitespace();
for i in ret{
println!("{}", i);
}
}
結(jié)果:
a
b
c
d
這里的空格不單單指的是空格,還有 制表符 \t
以及換行符\n
等
但正如它名字所說的,只支持ASCII
碼的空格符,如果你的字符串中還包含utf-8編碼的空格符,就可以使用函數(shù)split_whitespace
:
fn main() {
let s="a b \n \u{2009} c \td".to_string();
let ret=s.split_whitespace();
for i in ret{
println!("{}", i);
}
}
簡單來說,就是split_whitespace
更加強(qiáng)大
上面介紹的分隔函數(shù),都會將分隔符號給去除掉,如果你想要保留分隔字符串,就可以使用函數(shù):split_inclusive
方法如下:
fn main() {
let mut s="hello哈world哈".to_string();
let ret=s.split_inclusive('哈');
for i in ret{
println!("{}", i);
}
}
這次用哈
字作為分隔符號,得到的結(jié)果將會保留這個分隔符:
hello哈
world哈
除此之外,我們還可以根據(jù)下標(biāo)將字符串分割為兩部分:
fn main() {
let s="hello=world".to_string();
let (f,b)=s.split_at(5);
println!("{}\n{}",f,b);
}
用到的函數(shù)就是split_at
,不過需要注意的是,只要你的字符串中涉及到中文(不是字母的文字),那就要注意這個下標(biāo)一定得是字符邊界,否則程序直接崩潰
如果有時(shí)候那你需要可變的返回值,那就可以使用split_at_mut
,方法類似,不再贅述
而spite_off
函數(shù)的作用與split_at
基本類似,不同之處在于,它會截?cái)嘣址?,并返回后半段的字符?/p>
fn main() {
let mut s="hello=world".to_string();
let b=s.split_off(5);
print!("{}\n{}",s,b);
}
上面兩段代碼的結(jié)果相同:
hello
=world
最后還有一個函數(shù)可以用來得到指定字符結(jié)尾的子字符串:
fn main() {
let mut s="hello,world,test,哈哈哈,".to_string();
let ret=s.split_terminator(',');
for i in ret{
println!("{}", i);
}
}
上面的代碼就可以得到所有以,
結(jié)尾的子字符串,但如果只是這樣用話,也許還不如直接用splite
函數(shù)了
所以它還有更高級的用法,如下:
fn main() {
let s="hello,world;test-哈哈哈=".to_string();
let ret=s.split_terminator([',',';','-','=']);
for i in ret{
println!("{}", i);
}
}
它可以指定一系列作為結(jié)尾的字符或字符串!
甚至如果你了解閉包的話,還可以用閉包!
fn main() {
let s="hello,world;test-哈哈哈=".to_string();
let ret=s.split_terminator(|c| if c==',' || c==';' || c=='-' || c== '=' {true} else {false});
for i in ret{
println!("{}", i);
}
}
都可以得到結(jié)果:
hello
world
test
哈哈哈
六、轉(zhuǎn)換
作為字符串,一個非常常見的場景就是將字符串轉(zhuǎn)換為數(shù)字,這時(shí)候就可以調(diào)用parse
函數(shù)
fn main() {
let s=" 100\t\n".to_string();
let num:i32=s.trim().parse().expect("解析錯誤");
print!("{}",num);
}
這里用這個字符串作為解析的目的,就是提醒你在解析時(shí),一定要先調(diào)用trim
函數(shù),去除掉多余空白字符,否則解析必然會出錯
因?yàn)樗姆祷刂禐?code>Result類型,所以需要調(diào)用expect
取出轉(zhuǎn)化后得到的值,如果轉(zhuǎn)換失敗,則直接報(bào)錯
另一個注意的點(diǎn)是,如果你想要解析字符串到指定類型,你就必須表明想要解析的數(shù)據(jù)類型
比如這里的 let num:i32
,就是告訴這個函數(shù)我想要解析為i32
類型
七、判斷
作為字符串,判斷也是一個非常常用的功能
比如判斷是否與某個字符串相等,就可以直接用==
進(jìn)行判斷即可:
fn main() {
let s="hello".to_string();
if s=="hello" {
println!("s 為hello ")
}else{
println!("s 不為hello ")
}
}
除此之外,我們還可以判斷字符串是否以某個子字符串開始或者結(jié)尾:
fn main() {
let s="hello".to_string();
if s.starts_with("hel"){
println!("s 是以hel作為開頭的");
}
if s.ends_with("llo"){
println!("s 是以llo作為結(jié)尾的");
}
}
尤其是ends_with
函數(shù),常用來判斷一個文件的后綴是不是指定的格式,比如.txt
文本文件等文章來源:http://www.zghlxwxcb.cn/news/detail-436908.html
然后還有判斷是否包含某個子字符串,也很常用:文章來源地址http://www.zghlxwxcb.cn/news/detail-436908.html
fn main() {
let s="hello 哈嘍 world".to_string();
if s.contains("哈嘍"){
println!("s 包含哈嘍兩個字");
}
}
到了這里,關(guān)于rust 字符串(String)詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!