news 2026/1/27 2:42:00

【Rust】字符串(String 与 str) 详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Rust】字符串(String 与 str) 详解

Rust 提供两种主要字符串类型:String(可变,拥有所有权)和&str(不可变,借用)。

1.字符串基础

创建字符串

// 多种创建方式lets1=String::new();// 空字符串lets2="初始内容".to_string();// &str 转 Stringlets3=String::from("Hello");// from 方法lets4="字面量".to_owned();// to_owned(克隆)// 字符串字面量(&'static str)letliteral:&str="我是字面量";

更新字符串

letmuts=String::new();// 追加字符s.push('H');// "H"s.push_str("ello");// "Hello"// 拼接lets1=String::from("Hello, ");lets2=String::from("World!");lets3=s1+&s2;// s1被消耗,s3 = "Hello, World!"// 格式拼接lets4=format!("{}{}","Hi, ","Rust!");// "Hi, Rust!"

2.字符串操作

访问内容

lets=String::from("你好,世界");// 按字节访问(UTF-8编码)forbyteins.bytes(){println!("{}",byte);// UTF-8字节序列}// 按字符访问(Unicode标量值)forchins.chars(){println!("{}",ch);// '你', '好', ',', '世', '界'}// 字符迭代器方法letchar_count=s.chars().count();// 字符数:5letbyte_len=s.len();// 字节数:15(中文3字节/字符)

切片操作

lets=String::from("Hello, World!");// 创建字符串切片lethello=&s[0..5];// "Hello"letworld=&s[7..12];// "World"// 小心!必须按字符边界切片// let bad = &s[0..1]; // 对多字节字符会panic!// 安全切片方法ifs.is_char_boundary(3){letslice=&s[0..3];// 安全切片}

3.字符串方法

查询与检查

lets=String::from("Hello Rust");// 长度信息letbyte_len=s.len();// 字节长度letis_empty=s.is_empty();// 是否为空// 包含检查lethas_hello=s.contains("Hello");// trueletstarts=s.starts_with("He");// trueletends=s.ends_with("Rust");// true// 查找letfind_idx=s.find("Rust");// Some(6)letrfind_idx=s.rfind('l');// Some(3)(从右向左)

修改操作

letmuts=String::from("Hello World");// 替换lets1=s.replace("World","Rust");// 新字符串:"Hello Rust"s.replace_range(6..11,"Rust");// 原地替换:"Hello Rust"// 删除s.remove(5);// 移除索引5的字符(',')s.pop();// 移除最后一个字符s.truncate(5);// 截断到前5个字符s.clear();// 清空字符串// 插入s.insert(5,',');// 在索引5插入字符s.insert_str(0,"Prefix ");// 插入字符串

4.字符串转换

类型转换

// String ↔ &strletstring=String::from("hello");letstr_slice:&str=&string;// 自动解引用letowned:String=str_slice.to_string();// 数字转字符串letnum_str=42.to_string();// "42"letfloat_str=format!("{:.2}",3.14159);// "3.14"// 字符串转数字letnum:i32="42".parse().unwrap();// 42letnum_result:Result<i32,_>="42".parse();// Ok(42)

字符编码

// UTF-8 编码/解码lets="🦀 Rust";// 包含emoji// 获取UTF-8字节letbytes=s.as_bytes();// &[u8]// 从字节创建(需要有效UTF-8)letfrom_bytes=String::from_utf8(bytes.to_vec());// 处理无效UTF-8letlossy=String::from_utf8_lossy(b"Hello\xFFWorld");// "Hello�World"(替换无效字节)

5.字符串格式化

format! 宏

// 基本格式化lets=format!("{} + {} = {}",1,2,3);// "1 + 2 = 3"// 控制格式letpi=format!("PI: {:.3}",3.14159);// "PI: 3.142"lethex=format!("0x{:X}",255);// "0xFF"letbin=format!("{:b}",10);// "1010"// 位置参数lets=format!("{1} {0}","World","Hello");// "Hello World"// 命名参数lets=format!("{name} is {age}",name="Alice",age=30);

其他格式化宏

print!("Hello");// 打印不换行println!("World");// 打印换行eprint!("Error");// 标准错误打印eprintln!("Error with newline");lets=format!("Debug: {:?}",vec![1,2,3]);// 调试格式lets=format!("Pretty: {:#?}",vec![1,2,3]);// 美化调试

6.字符串性能优化

预分配容量

// 避免重复分配letmuts=String::with_capacity(100);// 预分配100字节s.push_str("Hello");s.push_str(" World");println!("长度: {}, 容量: {}",s.len(),s.capacity());// 长度: 11, 容量: 100(无需重新分配)

字符串重用

// 复用String缓冲区letmuts=String::new();foriin0..10{s.clear();// 清空内容,保留容量s.push_str(&format!("Item {}",i));// 处理s...}

使用Cow(写时复制)

usestd::borrow::Cow;fnprocess(input:&str)->Cow<str>{ifinput.contains("bad"){Cow::Owned(input.replace("bad","good"))// 需要时克隆}else{Cow::Borrowed(input)// 直接借用}}letresult=process("hello");// Cow::Borrowed("hello")letresult2=process("bad word");// Cow::Owned("good word")

7.常用字符串模式

字符串分割

lets="apple,banana,orange";// 按分隔符分割letfruits:Vec<&str>=s.split(',').collect();// ["apple", "banana", "orange"]// 保留分隔符letparts:Vec<&str>=s.split_inclusive(',').collect();// ["apple,", "banana,", "orange"]// 多分隔符lets2="apple, banana; orange";letfruits2:Vec<&str>=s2.split([',',';',' ']).collect();// 行分割lettext="line1\nline2\r\nline3";letlines:Vec<&str>=text.lines().collect();

字符串修剪

lets=" Hello Rust! \n";lettrimmed=s.trim();// "Hello Rust!"(移除两端空白)letleft_trimmed=s.trim_start();// "Hello Rust! \n"letright_trimmed=s.trim_end();// " Hello Rust!"// 自定义修剪字符lets2="***Hello***";lettrimmed2=s2.trim_matches('*');// "Hello"

大小写转换

lets="Hello Rust";letupper=s.to_uppercase();// "HELLO RUST"letlower=s.to_lowercase();// "hello rust"// 首字母大写fncapitalize(s:&str)->String{letmutchars=s.chars();matchchars.next(){None=>String::new(),Some(first)=>first.to_uppercase().chain(chars).collect(),}}letcap=capitalize("hello");// "Hello"

8.字符串与集合

字符串向量

// 字符串集合letwords=vec!["hello","world","rust"].into_iter().map(|s|s.to_string()).collect::<Vec<String>>();// 连接字符串letsentence=words.join(" ");// "hello world rust"// 拼接多个字符串letconcatenated=["foo","bar","baz"].concat();// "foobarbaz"

字符处理

lets="Hello 世界";// 字符统计letchar_count=s.chars().count();// 7letgrapheme_count=s.chars().count();// 注意:可能不是字形簇数// 字符位置ifletSome(pos)=s.char_indices().find(|(_,ch)|*ch=='世').map(|(i,_)|i){println!("'世'在位置 {}",pos);// 输出位置}

9.字符串与I/O

文件读写

usestd::fs;usestd::io::{self,Write,BufRead};// 读取文件为字符串letcontent=fs::read_to_string("file.txt")?;// 写入字符串到文件fs::write("output.txt","Hello World")?;// 逐行读取letfile=fs::File::open("file.txt")?;letreader=io::BufReader::new(file);forlineinreader.lines(){letline=line?;println!("{}",line);}

用户输入

usestd::io;letmutinput=String::new();println!("请输入:");io::stdin().read_line(&mutinput)// 读取一行.expect("读取失败");lettrimmed=input.trim();// 移除换行符println!("你输入了: {}",trimmed);

10.字符串最佳实践

选择指南

  1. 函数参数:优先使用&str而非&String
  2. 返回类型:需要所有权时用String,否则考虑Cow<str>
  3. 性能敏感:预分配容量,避免重复分配
  4. 国际文本:使用chars()而非字节索引

常见错误避免

// ❌ 错误:多字节字符切片// let s = "你好";// let slice = &s[0..1]; // panic!// ✅ 正确:使用字符迭代lets="你好";ifletSome(first_char)=s.chars().next(){println!("首字符: {}",first_char);}// ❌ 避免:不必要的String分配fnbad_greeting(name:&String)->String{format!("Hello, {}",name)// 可以接受&str}// ✅ 改进:使用&str参数fngood_greeting(name:&str)->String{format!("Hello, {}",name)}

String vs &str 总结

特性String&str
所有权拥有数据借用数据
可变性可变不可变
内存位置栈、堆或静态内存
大小动态编译时已知
性能有分配开销无分配开销

核心原则

  • 需要修改或拥有字符串时使用String
  • 只读引用时使用&str
  • 函数参数优先接受&str以兼容两者
  • 使用to_string()into()进行必要转换

Rust的字符串设计确保了内存安全和UTF-8编码正确性,虽然增加了复杂性,但提供了强大的安全保证。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/25 0:43:53

燧原科技邃思芯片适配:国产AI加速器运行anything-llm实测

燧原科技邃思芯片适配&#xff1a;国产AI加速器运行anything-llm实测 在企业对数据安全与推理效率的要求日益严苛的今天&#xff0c;如何在不依赖公有云服务的前提下&#xff0c;实现大语言模型&#xff08;LLM&#xff09;的高效、稳定、本地化部署&#xff0c;已成为智能系统…

作者头像 李华
网站建设 2026/1/22 9:53:35

MISRA C++规则检查常见问题:快速理解汇总

MISRA C 规则检查避坑指南&#xff1a;一线工程师的实战解析在汽车电子、工业控制和航空航天这些容错率极低的领域&#xff0c;软件缺陷可能直接引发灾难性后果。因此&#xff0c;“写正确的代码”早已不是一种追求&#xff0c;而是一项硬性要求。正是在这样的背景下&#xff0…

作者头像 李华
网站建设 2026/1/19 13:22:38

Open-AutoGLM 沉思浏览器上线倒计时:仅限100个内测名额,立即申请

第一章&#xff1a;Open-AutoGLM 沉思浏览器上线倒计时&#xff1a;仅限100个内测名额&#xff0c;立即申请 备受期待的 Open-AutoGLM 沉思浏览器即将正式上线&#xff0c;目前进入最后阶段的封闭测试。该浏览器基于开源大语言模型驱动&#xff0c;专为开发者与高级用户提供智…

作者头像 李华
网站建设 2026/1/26 15:00:54

计算机毕业设计springboot美容美发店管理系统 基于 SpringBoot 的美容院智能运营平台 SpringBoot 驱动的理发店一站式业务管控系统

计算机毕业设计springboot美容美发店管理系统su1ybxr5 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。当“颜值经济”撞上“小店数字化”&#xff0c;美容美发门店每天要在同一套…

作者头像 李华
网站建设 2026/1/11 18:32:12

你不能错过的提示工程架构师提示缓存机制设计秘籍大公开

你不能错过的提示工程架构师提示缓存机制设计秘籍大公开 引入与连接&#xff1a;当"重复"成为AI时代的隐形成本 想象这样一个场景&#xff1a;作为某科技公司的提示工程架构师&#xff0c;你精心设计的客户服务AI系统每天处理着上万次用户咨询。突然&#xff0c;财务…

作者头像 李华