有编程经验的相信没少和字符串打交道,无论是C/C+,还是现在比较流行的Python,字符串都是用的非常多的类型。在Rust中字符串类型同样有举足轻重的作用,几乎编码都离不开字符串。下面将详细学习Rust中的String类型。
fn main() {
let mut name_str = String::new();
}
我们用String的new函数来创建一个空的字符串name_str,这时候字符串里面没有任何内容,你可以理解name_str就是一个字符串的对象。接下来你就可以对name_str进行字符串方法的一系列调用。
当然我们也可以在创建的同时对字符串进行初始化
fn main() {
let name_str = String::from("ftz");
println!("the name is {}",name_str);
}
也可以用to_string方法,将字符串字面值转换成字符串类型
fn main() {
let data = "ftz";
let s = data.to_string();
// 该方法也可直接用于字符串字面量:
let s = "ftz".to_string();
}
就像开头所说字符串的使用非常频繁和广泛,在Rust中实现了很多不同的用于字符串的通用 API 可供编码者选择。其中一些可能看起来多余,不过都有其用武之地!在这个例子中,String::from
和 to_string
最终做到了完全相同的事情,所以如何选择,就是风格问题了。我个人更倾向于使用String::from,这个看起来血脉更纯,更Rust
字符串创建后,一般都不是原模原样的从头用到尾,也是有需求在流程中对字符串进行更新,这里的更新就包括对源字符串的拼接,删除,格式化
fn main() {
let mut my_name = String::from("Fei");
my_name.push_str(" tz");
println!("my name is {}",my_name);
}
运行结果:
在这里也需要注意一下push_str并不获取括号内变量的所有权
fn main() {
let mut my_name = String::from("Fei");
let sec_name = " tz";
my_name.push_str(" tz");
println!("my name is {}",my_name);
println!("second name is {}",sec_name);
}
运行结果:
可以看到我们打印出来了sec_name。
fn main() {
let mut my_name = String::from("ft");
let last_name = 'z';
my_name.push(last_name);
println!("my name is {}",my_name);
println!("last name is {}",last_name);
}
运行结果:
可以看到push方法同样也不会获得括号内变量的所有权
在Rust中使用'+'号拼接字符串的用法还是让我吃惊了一把,学到现在个人感觉Rust相对于Python还是比较刻板,对于这种在Python中常见的字符串拼接用法出现在Rust中还是比较惊喜的。
fn main() {
let first_name = String::from("Fei");
let last_name = String::from(" tz");
let my_name = first_name + &last_name;
println!("my name is {}",my_name);
println!("last name is {}",last_name);
}
运行结果:
需要注意的是用'+'号去拼接字符串,在相加后first_name便丧失了所有权,后续不能再使用first_name变量了。从使用中也可以看到被加的last_name用的是引用,不会丧失所有权,后面还可以正常使用
如果想要级联多个字符串,+
的行为就显得笨重了:
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;
对于比较长且多次的拼接可以使用format!宏来实现,更加简洁直观
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
这个就类似于C语言中的snprintf函数来格式化的拼接字符串,另外利用format!宏来拼接字符串并不会获取所有要拼接字符串的所有权。
如果我们想要获取字符串中的某个字符,第一想到的是能不能像数组一样通过下标索引去访问。
fn main() {
let first_name = String::from("Fei");
println!("my name is {}",first_name[0]);
}
运行结果:
可以看到在Rust中并不支持用下标去访问字符串中的字符。如果我们想要访问字符串中的某个字符或者一段字符可以通过切片的方式
fn main() {
let first_name = String::from("Fei");
println!("my name is {}",&first_name[0..2]);
}
运行结果:
用切片去访问字符串的时候需要注意的是切片的长度必须是字符串单个字符的整数倍
fn main() {
let first_name = String::from("您好");
println!("my name is {}",&first_name[0..1]);
}
运行结果:
可以看到程序报错了,因为一个汉字在Rust中是3个字节,切片一个字节的话程序不知道怎么返回,只能3个字节并且在边界上才可以
我们可以用for循环在遍历字符串
fn main() {
let hello = String::from("您好呀");
for sig in hello.chars(){
println!("{}",sig);
}
}
运行结果:
对于字符串的遍历最好的选择是使用 chars
方法。对中文字符串调用 chars
方法会将其分开并返回单个汉字char
类型的值,接着就可以遍历其结果来访问每一个元素了,这时候就不用烦恼字符串中的单个字符所占的字节数了
假如你想获取字符串在内存中字节值,可以用bytes方法去遍历字符串的每一个字节值
fn main() {
let hello = String::from("您好呀");
for sig in hello.bytes(){
println!("{}",sig);
}
}
运行结果:
从上面可以看到在Rust中字符串的使用相比较于Python条条框框还是相当多的,刚上手就觉得字符串的处理比较繁琐,但是这也相当程度上避免了处理字符串过程中会出现的潜在的错误。还是那句话学好Rust不容易。