2015-05-08 154 views
2

所以我试图在字符串中找到一个模式并将其转换为整数。将字符串解析为整数

首先我寻找一个字符串:

let haystack = "HTTP/1.1 200\r\n"; 
let needle = "HTTP/1."; 

let http_location = haystack.rfind(needle); 
if (http_location.is_some()) { 

现在,我已经找到了我能想到的两种方式来获得数字状态。或者:

let mut temp_str = haystack.char_at(http_location.unwrap()); 
    let status = String::from_str(temp_str); 
} 

或者:

let status = String::from_str(&haystack[http_location.unwrap()]); 
} 

不幸的是两者都被弃用(反正可能是错的)。目前正确的做法是什么?

而且,是这部分文体正确?:

let http_location = haystack.rfind(needle); 
if (http_location.is_some()) 

回答

4

解析是广泛和多样的主题。有简单的解析工具,并有高性能的解析工具和频谱之间。

fn main() { 
    let haystack = "HTTP/1.1 200\r\n"; 
    let needle = "HTTP/1."; 

    let z: Option<u8> = haystack.rfind(needle).and_then(|pt| { 
     let after_match = &haystack[(pt + needle.len())..]; 
     after_match.splitn(2, " ").next() 
    }).and_then(|val| { 
     val.parse().ok() 
    }); 

    println!("{:?}", z) 
} 

在这里,我们使用rfind就像以前那样,它可能会失败。如果结果为Some,我们使用and_then来运行关闭。第一个封闭片在针之后将字符串切片,然后将其拆分到空间上,最多2个部分。这可能会失败,所以我们使用第二个and_then来使用parse,它可以失败,Result,所以我们将其转换为Option以保留该类型。

最后,我们仍然可能失败了,因为我们解析的东西可能不是可解析的数字!

鲁斯特确实可以帮助你制定明确的地方,你可以失败,你必须处理它们。^_^

在这种情况下:

  1. 也许字符串没有 “HTTP/1。”在它
  2. 迭代器不得不在某个时候结束,所以他们可以返回None
  3. 将字符串解析为数字可能会失败。

下面是一个使用一个替代的解决方案的regex crate

extern crate regex; 

use regex::Regex; 

fn main() { 
    let haystack = "HTTP/1.1 200\r\n"; 

    let re = Regex::new(r"HTTP/1.(\d) (\d+)\r\n").unwrap(); 
    let captures = re.captures(haystack).unwrap(); 
    let version: Option<u8> = captures.at(1).and_then(|version| version.parse().ok()); 
    let status: Option<u8> = captures.at(2).and_then(|version| version.parse().ok()); 

    assert_eq!(Some(1), version); 
    assert_eq!(Some(200), status); 

    println!("Version: {:?}, Status: {:?}", version, status); 
} 

你会看到,我们有同类型的故障模式,但结构是一个有点不同。

或者,也许使用Resulttry!版本:

#[derive(Debug,Copy,Clone,PartialEq)] 
enum Error { 
    StartNotFound, 
    NotANumber, 
} 

fn parse_it(haystack: &str) -> Result<u8, Error> { 
    let needle = "HTTP/1."; 
    let pt = try!(haystack.rfind(needle).ok_or(Error::StartNotFound)); 
    let after_match = &haystack[(pt + needle.len())..]; 
    let val = after_match.splitn(2, " ").next().unwrap(); 
    val.parse().map_err(|_| Error::NotANumber) 
} 

fn main() { 
    println!("{:?}", parse_it("HTTP/1.1 200\r\n")); 
    println!("{:?}", parse_it("HTTP/1")); 
    println!("{:?}", parse_it("HTTP/1.cow")); 
} 
+0

这是锈应该在“生产”被写入的方式吗?它看起来非常简洁,似乎是作者在离开代码一段时间后很难理解的东西。无论如何,你能解释'.and_then()'的功能和语法到底是什么吗?我觉得它的官方文档假定有一些我没有的函数式编程知识。 –

+1

@andreyg美丽是在旁观者的眼中,我想!你当然可以用更多的'match'语句重写它,或者从'Option'升级到'Result',然后使用'try!'宏。我已经添加了这个和一个正则表达式的例子。我不能为整个Rust社区说话,但你一定要写出你能理解的代码! *每个人都知道,调试比编写程序要困难一倍。所以,如果你在编写代码的时候能够像你一样聪明,那么你将如何调试它?* - [Brian Kernighan](http://en.wikiquote.org/wiki/Brian_Kernighan) – Shepmaster