2012-06-24 148 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); 

这涵盖了所有情况!