2017-03-23 83 views
0

我想檢查字符串是否以"|<any char><any char>TD"開頭。我已經驗證該字符串只包含0..9,a-z,A-Z,空格,','和'*'。如果索引範圍無效,則獲取None而不是字符串切片

包括正則表達式箱這樣的任務是太多的開銷,而不是我想我需要這樣的東西

fn get_slice(s: &str, range: Range<usize>) -> Option<&str> { 
    unimplemented!(); 
} 

它可以用於像:

let is_good_string: bool = 
    get_slice(s, (0..5)).map_or(false, |v: &str| &v[0..1] == "|" && &v[3..5] == "TD"); 

有什麼功能,在標準庫類似於我的get_slice?是否有可能以其他方式藉助標準庫函數來解決我的任務?

+0

你會通過切割這樣的字符串來傷害自己。查看關於[切分字符串]的書(https://doc.rust-lang.org/stable/book/strings.html#slicing)。 –

+0

@ E_net4我讀過關於'str'的​​切片。你的意思是我會遇到utf-8的問題?在我的情況下,這不是問題,因爲我解析了與ASCII協同工作的舊協議。 – user1244932

+0

這聽起來像是在編寫解析器。您可能希望查看允許您編寫高效解析器的工具,而不是手動執行所有操作。 nom是流行的選擇,專門用於解析二進制文件格式。 – Shepmaster

回答

3

我同意E_net4's answer,但對於後人,字面回答你的問題是直截了當:

use std::ops::Range; 

fn get_slice(s: &str, range: Range<usize>) -> Option<&str> { 
    if s.len() > range.start && s.len() > range.end { 
     Some(&s[range]) 
    } else { 
     None 
    } 
} 

fn main() { 
    println!("{:?}", get_slice("", 0..5)); 
    println!("{:?}", get_slice("abc", 0..2)); 
    println!("{:?}", get_slice("abc", 2..5)); 
    println!("{:?}", get_slice("abc", 1..2)); 
} 

雖然我會避免使用此字符串切片,並用它只能在常規切片,由於到字符串的UTF-8性質。

+0

是否需要s.len()> range.start'檢查? 'Range'在創建期間不檢查'start <= end'? – user1244932

+0

@ user1244932使用本地編譯器創建一個起始位置大於結束位置的範圍,可以更快地回答您的問題。 – Shepmaster

5

獲得無,而不是切片如果索引範圍無效

有標準的,沒有功能的,我知道的。

我要檢查,如果字符串開頭「| <任何字符> <任何字符> TD」,

但對於這一目標,我提出了一個解決方案,它是(在我看來)更優雅比切片:

fn is_good(s: &str) -> bool { 
    if !s.starts_with('|') { 
     return false; 
    } 
    let mut td_iter = s.chars().skip(3); 
    (td_iter.next(), td_iter.next()) == (Some('T'), Some('D')) 
} 

Playground。它與任何UTF-8字符串兼容,並確保在讀取字符串/字符邊界之外的代碼點時不發生恐慌。

+0

在我的情況下,用ascii,我最好使用'str :: slice_unchecked',再加上這樣的代碼太多了,如果我爲每個「標題」檢查寫這樣的東西,我將被大量代碼掩埋。 – user1244932

+0

@ user1244932然後參數化爲'T'和'D'? – Shepmaster

+0

@ user1244932在此我強加兩條建議。其中之一就是將你的函數概括爲其他類型的頭文件(甚至可以使用宏)。另一個是*在問題中*具體*關於你的上下文*,否則答案不會考慮它。 –