2015-05-08 198 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