当前位置: 首页 > news >正文

【Rust】 6. 字符串学习笔记

一、Rust 字符串概述

Rust 字符串是 UTF-8 编码的文本序列,提供两种主要类型:

  1. &str - 字符串切片(通常作为引用出现)
  2. String - 动态可变的、拥有所有权的字符串

二、字符串字面量 (&str)

编译时已知大小,静态分配在只读内存中

let greeting: &str = "Hello, world!";
println!("字符串字面量: {}", greeting);

三、String 类型

动态分配在堆上,可增长和修改的所有权字符串

let mut s = String::from("Hello");
s.push_str(", world!");
println!("String 类型: {}", s);

四、创建 String 的多种方式

  1. 创建空字符串
let empty = String::new();
println!("空字符串: '{}'", empty);
  1. 从字面量创建
let from_literal = String::from("初始内容");
println!("从字面量创建: {}", from_literal);
  1. 使用 to_string() 方法
let to_string = "另一个字符串".to_string();
println!("to_string(): {}", to_string);
  1. 使用 format! 宏
let formatted = format!("格式化 {} {}", "字符串", 123);
println!("format! 宏: {}", formatted);

五、修改 String

let mut mutable_string = String::from("Hello");
// 添加单个字符
mutable_string.push('!');
println!("添加字符后: {}", mutable_string);// 添加字符串切片
mutable_string.push_str(" World");
println!("添加字符串后: {}", mutable_string);// 在指定位置插入
mutable_string.insert_str(6, "Rust ");
println!("插入后: {}", mutable_string);

六、字符串访问和迭代

let text = String::from("Hello");// 获取第一个字符(Option<char> 类型)
if let Some(first_char) = text.chars().nth(0) {println!("第一个字符: {}", first_char);
}// 迭代所有字符
print!("字符迭代: ");
for c in text.chars() {print!("{} ", c);
}
println!();// 字符串切片(注意:基于字节索引,非ASCII字符需要小心)
let slice = &text[0..1]; // "H"
println!("切片: {}", slice);

七、Unicode 和非 ASCII 字符处理

let unicode_text = "Здравствуйте"; // 俄语"你好"
println!("Unicode 文本: {}", unicode_text);// 字符数统计(不是字节数)
let char_count = unicode_text.chars().count();
let byte_count = unicode_text.len();
println!("字符数: {}, 字节数: {}", char_count, byte_count);// 遍历 Unicode 字符
print!("Unicode 字符: ");
for c in unicode_text.chars() {print!("{} ", c);
}
println!();

八、字符串转换和操作

let original = String::from("hello");// 转换为大写(返回新字符串)
let upper = original.to_uppercase();
println!("大写: {}", upper);// 转换为小写
let lower = upper.to_lowercase();
println!("小写: {}", lower);// 字符串替换
let replaced = original.replace("he", "she");
println!("替换后: {}", replaced);// 字符串分割
let sentence = "Rust is awesome!";
let words: Vec<&str> = sentence.split_whitespace().collect();
println!("分割单词: {:?}", words);

九、&str 和 String 的关系与转换

// &str → String(需要分配内存)
let slice: &str = "切片";
let owned: String = slice.to_string();
println!("&str 转 String: {}", owned);// String → &str(零成本转换)
fn process_text(text: &str) {println!("处理文本: {}", text);
}let string_data = String::from("一些数据");
process_text(&string_data); // 自动解引用转换

十、原始字符串和转义

// 普通转义
let escaped = "包含\"引号\"和\\反斜杠";
println!("转义字符串: {}", escaped);// 原始字符串(避免转义)
let raw = r#"原始字符串: "内容" 和 \反斜杠"#;
println!("原始字符串: {}", raw);// 多级原始字符串(处理包含 # 的文本)
let complex_raw = r###"包含 # 号的 "原始" 字符串"###;
println!("复杂原始字符串: {}", complex_raw);

十一、字符串索引的注意事项

// Rust 不允许直接索引字符串(因UTF-8变长编码)
let sample = "Rust编程";// 错误:不能直接索引
// let first_char = sample[0]; // 正确方式:使用字符迭代
if let Some(first) = sample.chars().nth(0) {println!("第一个字符: {}", first);
}// 获取字符向量(注意性能开销)
let chars: Vec<char> = sample.chars().collect();
println!("字符向量: {:?}", chars);

十二、字符串连接

// 使用 + 运算符(会获取所有权)
let s1 = String::from("Hello");
let s2 = String::from(" World");
let combined = s1 + &s2; // s1 被移动,不能再使用
println!("连接后: {}", combined);// 使用 format! 宏(推荐,不会获取所有权)
let s3 = String::from("Hello");
let s4 = String::from(" World");
let formatted_combine = format!("{}{}", s3, s4);
println!("format! 连接: {}", formatted_combine);
// s3 和 s4 仍然可用

十三、实用字符串方法

let example = String::from("   Rust Programming   ");// 去除首尾空白
let trimmed = example.trim();
println!("去除空白: '{}'", trimmed);// 检查是否包含子串
let contains = example.contains("Rust");
println!("包含 'Rust': {}", contains);// 查找子串位置
if let Some(pos) = example.find("Programming") {println!("'Programming' 位置: {}", pos);
}// 字符串长度(字节数)
println!("字节长度: {}", example.len());// 判断是否为空
println!("是否为空: {}", example.is_empty());

十四、总结:

  • &str: 静态、不可变、零成本抽象的字符串视图
  • String: 动态、可变、拥有所有权的字符串
  • UTF-8 编码确保完整的 Unicode 支持
  • 设计注重内存安全和性能
  • 丰富的API支持各种字符串操作

性能提示:频繁的字符串修改建议使用 String,只读操作使用 &str

http://www.xdnf.cn/news/1394389.html

相关文章:

  • app怎么防止被攻击被打有多少种防护方式?
  • 税务岗位能力提升培训课程推荐
  • 达梦数据库-数据缓冲区 (二)
  • 【Flask】测试平台开发,产品管理实现编辑功能-第六篇
  • 接吻数问题:从球体堆叠到高维空间的数学奥秘
  • 机器学习 - Kaggle项目实践(5)Quora Question Pairs 文本相似
  • 栈和队列OJ习题
  • 佳易王钓场计时计费系统:全方位赋能钓场智能化管理,软件操作教程
  • vue在函数内部调用onMounted
  • 2025年热门职业资格证书分析
  • Rust 登堂 之 深入Rust 类型(六)
  • Linux内存管理 - LRU机制
  • 「LangChain 学习笔记」LangChain大模型应用开发:代理 (Agent)
  • VeOmni 全模态训练框架技术详解
  • 蓝蜂蓝牙模组:破解仪器仪表开发困境
  • 《P2863 [USACO06JAN] The Cow Prom S》
  • C++模板类的详细介绍和使用指南
  • 桌面GIS软件添加第三方图层
  • 【无标题】透明显示屏设计,提升展厅视觉体验边界
  • 【0424】为用户指定(CREATE TABLE)的 table 创建 relcache entry,并将其注册到 relcache ④
  • ros2--action/动作--接口
  • 【链表 - LeetCode】146. LRU 缓存
  • LeetCode Hot 100 Python (11~20)
  • Windows 11 跳过 OOBE 的方法和步骤
  • 打工人日报#20250829
  • 亚马逊季节性产品运营策略:从传统到智能化的演进
  • 【AOSP】Android Dump 开发与调试指南
  • 麒麟系统使用-VSCode运行.net过程中一些可能问题及解决办法
  • 每周资讯 | 《恋与深空》获科隆游戏展2025“最佳移动游戏奖”;8月173个版号下发
  • 25.8.29_NSSCTF——[BJDCTF 2020]Easy_WP