题目截图来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/string-to-integer-atoi/
这是来源于leetcode的一道题 “字符串转换整数(atoi)”,我们使用Rust来实现。
本次实战目的:
字符串字节向量引用的使用,类型转换,数字的边界处理,字符串取片段,。
简单分析:
题目讲的比较清晰。直接讲一下思路:
将字符串转换为utf8的字节类型,那么数字、符号等会转换为对应的ascii码,则通过对于单字节的数字、符号进行遍历比对。
至于转换为整数至少有两种方法,其一可以使用字符串截取片段来获取一段完整数字,通过 i32::from_str 转换,并可以处理溢出的异常。
其二可以使用checked_mul 和 checked_add 对每一个获取到的数字进行计算,这里类似上一期的整数翻转功能。
本次练习使用第一种方法。
直接上代码,随后进行解析:
fn my_atoi(s: String) -> i32 {
// 获取字节数组引用
let bytes = s.as_bytes();
// 字符串截取的起始和结束
let (mut start, mut idx) = (0, 0);
// 是否为负数
let mut negative = false;
// 是否遇到数字,是否遇到符号
let (mut num, mut symbol) = (false, false);
//定义各字符的ascii码遍历
let (zero, plus, sub, nine, space) = (b'0', b'+', b'-', b'9', b' ');
while idx < bytes.len() {
let ascii = bytes[idx];
//当遇到符号或者数字后,存在其他字符,则停止。
if (num || symbol) && (ascii == space || ascii == plus || ascii == sub) {
break;
}
if ascii == space || ascii == plus || ascii == sub {
start += 1;
if ascii == plus || ascii == sub {
symbol = true;
}
if ascii == sub {
negative = true;
}
}
if ascii >= zero && ascii <= nine {
num = true;
}
if ascii != space && ascii != plus && ascii != sub && (ascii < zero || ascii > nine) {
break;
}
idx += 1;
}
// 截取开始和结束相等的情况 一定是0
if start == idx {
return 0;
}
use std::str::FromStr;
//截取字符串,转换失败时会返回ParseIntError
if let Ok(v) = i32::from_str(&s[start..idx]) {
if negative {
return v.checked_mul(-1).unwrap_or(std::i32::MIN);
}
return v;
}
if negative {
return std::i32::MIN;
}
return std::i32::MAX;
}
as_bytes() 获取String内的Vec<u8>向量的引用。
可以通过 b'0' 定义u8类型的字节码,但是不能使用双引号的 b"0" ,是因为它是 &[u8; 1] 类型,不适合用在这里。
注意:使用 i32::from_str() 需要引入std::str::FromStr,参数需要传入&str类型。如此获取的字符串发生转换异常时则一定是溢出的情况。