2012-06-24 145 views
0

我有一個字符串,可以輸入爲{n}d {n}h {n}m {n}s,其中{n}是一個整數,表示天數,小時數,分鐘數,秒數。我如何從字符串中提取這個{n}號碼?解析字符串的整數部分

用戶不必輸入全部4-d,h,m,s。他只能輸入4d,即4天或5h 2s,即5小時2秒。

這是我的。肯定應該有更好的方法來做到這一點。此外,並不涵蓋所有情況。

int d; int m; int h; int sec; 
string [] split = textBox3.Text.Split(new Char [] {' ', ','}); 
List<string> myCollection = new List<string>(); 

foreach (string s in split) 
{ 
    d = Convert.ToInt32(s.Substring(0,s.Length-1)); 
    h = Convert.ToInt32(split[1].Substring(1)); 
    m = Convert.ToInt32(split[2].Substring(1)); 
    sec = Convert.ToInt32(split[3].Substring(1)); 
} 
dt =new TimeSpan(h,m,s); 

回答

3

如果天,小時,分鐘和秒的順序是固定的,那麼你可以使用正則表達式:

string input = textBox3.Text.Trim(); 
Match match = Regex.Match(input, 
    "^" + 
    "((?<d>[0-9]+)d)? *" + 
    "((?<h>[0-9]+)h)? *" + 
    "((?<m>[0-9]+)m)? *" + 
    "((?<s>[0-9]+)s)?" + 
    "$", 
    RegexOptions.ExplicitCapture); 

if (match.Success) 
{ 
    int d, h, m, s; 
    Int32.TryParse(match.Groups["d"].Value, out d); 
    Int32.TryParse(match.Groups["h"].Value, out h); 
    Int32.TryParse(match.Groups["m"].Value, out m); 
    Int32.TryParse(match.Groups["s"].Value, out s); 
    // ... 
} 
else 
{ 
    // Invalid input. 
} 
+0

指定'RegexOptions.ExplicitCapture'而不是使用非捕獲組,並且你很好... – Lucero

+0

@Lucero:哇,我學到了一些東西新! –

0

編寫自定義分析器 - 使用狀態機來確定字符串中每個部分的確切含義。

這個想法是遍歷字符串中的每個字符,並根據它改變狀態。所以,你將有一個Number狀態和DayMonthHourSeconds狀態,SpaceStartEnd狀態。

0

一種方法可能是使用sscanf(),這很容易做到這一點。我已在C#中使用this article實現了此函數的一個版本。

如果您需要更好地處理潛在的語法錯誤,那麼您只需實現自己的解析器。我會通過逐個檢查每個角色來做到這一點。

+0

'sscanf' in C#? – Oded

+0

對不起,我很困惑,但已經完成了我對C#的回答。 –

+0

我想沒有足夠的以C開頭的C風格語言;) – Oded

0

這裏有各種選擇。您可以嘗試使用TimeSpan.TryParse函數,但這需要不同的輸入格式。另一種方法是將字符串拆分爲空白字符並遍歷每個部分。在此過程中,您可以檢查零件是否包含d,h,s等,並將該值提取到期望的變量中。你甚至可以使用RegEx來解析字符串。這是基於迭代一個例子:

static void Main(string[] args) 
    { 
     Console.WriteLine("Enter the desired Timespan"); 
     string s = Console.ReadLine(); 

     //ToDo: Make sure that s has the desired format 

     //Get the TimeSpan, create a new list when the string does not contain a whitespace. 
     TimeSpan span = s.Contains(' ') ? extractTimeSpan(new List<string>(s.Split(' '))) : extractTimeSpan(new List<string>{s}); 

     Console.WriteLine(span.ToString()); 

     Console.ReadLine(); 
    } 

    static private TimeSpan extractTimeSpan(List<string> parts) 
    { 
     //We will add our extracted values to this timespan 
     TimeSpan extracted = new TimeSpan(); 

     foreach (string s in parts) 
     { 
      if (s.Length > 0) 
      { 
       //Extract the last character of the string 
       char last = s[s.Length - 1]; 

       //extract the value 
       int value; 
       Int32.TryParse(s.Substring(0, s.Length - 1), out value); 

       switch (last) 
       { 
        case 'd': 
         extracted = extracted.Add(new TimeSpan(value,0,0,0)); 
         break; 
        case 'h': 
         extracted = extracted.Add(new TimeSpan(value, 0, 0)); 
         break; 
        case 'm': 
         extracted = extracted.Add(new TimeSpan(0, value, 0)); 
         break; 
        case 's': 
         extracted = extracted.Add(new TimeSpan(0, 0, value)); 
         break; 
        default: 
         throw new Exception("Wrong input format"); 
       } 
      } 
      else 
      { 
       throw new Exception("Wrong input format"); 
      } 
     } 

     return extr 
0

您可以優化你的方法稍微

int d = 0; 
int m = 0; 
int h = 0; 
int s = 0; 

// Because of the "params" keyword, "new char[]" can be dropped. 
string [] parts = textBox3.Text.Split(' ', ','); 

foreach (string part in parts) 
{ 
    char type = part[part.Length - 1]; 
    int value = Convert.ToInt32(part.Substring(0, part.Length - 1)); 
    switch (type) { 
     case 'd': 
      d = value; 
      break; 
     case 'h': 
      h = value; 
      break; 
     case 'm': 
      m = value; 
      break; 
     case 's': 
      s = value; 
      break; 
    } 
} 

現在你已經完全沒有缺失的部分設置。缺少的部分仍然是0。您可以將這些值轉換爲TimeSpan

var ts = TimeSpan.FromSeconds(60 * (60 * (24 * d + h) + m) + s); 

這涵蓋了所有情況!