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 = "h3";
let s = a.to_string();
也可以直接在字符串文字上实现to_string
方法:
let s = "h3".to_string();
下面通过一个例子来理解这一点:
fn main()
{
let data="h3";
let s=data.to_string();
print!("{} ",s);
let str="tutorial".to_string();
print!("{}",str);
}
执行上面示例代码,得到以下结果 -
h3 tutorial
创建string
的第二种方法是使用string::from
函数,它相当于string::new()
函数。下面通过一个简单的例子来理解这一点:
fn main()
{
let str = string::from("h3 tutorial");
print!("{}",str);
}
执行上面示例代码,得到以下结果 -
h3 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("h3 ");
let s2 = string::from("tutorial!!");
let s3 = s1+&s2;
再来看看一个简单的代码:
fn main()
{
let s1 = string::from("h3");
let s2 = string::from(" tutorial!!");
let s3 = s1+&s2;
print!("{}",s3);
}
执行上面示例代码,得到以下结果 -
h3 tutorial!!
在上面的例子中,s3
包含两个字符串串联的结果,即"h3 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("h3");
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