【问题标题】:How can I get integer and char separately in such a simple string?如何在如此简单的字符串中分别获取整数和字符?
【发布时间】:2011-11-30 02:33:31
【问题描述】:

我有类似的字符串:“7d”、“5m”、“95d”等。

我需要找到简单的方法来分别得到整数和字符。

我怎样才能做到这一点:

int number = GetNumber("95d"); //should return 95
char code = GetCode("95d"); // should return d

【问题讨论】:

  • 不正确的字符串值怎么办?你想以某种方式处理它吗?
  • 在我看来,这几乎像 7d,就像双精度值 7 和 5m,像十进制的 5。如果这是在正确的附近,你可能有“5.0m”吗?

标签: c# .net regex string parsing


【解决方案1】:

给你:

public class NumberSuffixParser
{
    private static readonly Regex rxPattern = new Regex( @"^(?<number>\d+(\.\d+)?)(?<suffix>\p{L}+)$" , RegexOptions.IgnoreCase|RegexOptions.ExplicitCapture ) ;

    public void Parse( string value , out decimal number , out string suffix )
    {
        if ( value == null ) throw new ArgumentNullException("value") ;
        Match match = rxPattern.Match( value ) ;
        if ( ! match.Success ) throw new ArgumentOutOfRangeException("value") ;
        number = decimal.Parse( match.Groups["number"].Value ) ;
        suffix =                match.Groups["suffix"].Value   ;
        return ;
    }

    public decimal ParseNumber( string value )
    {
        decimal number ;
        string  suffix ;
        Parse( value , out number , out suffix ) ;
        return number ;
    }

    public string ParseSuffix( string value )
    {
        decimal number ;
        string  suffix ;
        Parse( value , out number , out suffix ) ;
        return suffix ;
    }

}

下面是另一种稍微简单但相当灵活的方法。它会愉快地解析诸如“789xyz”、“1234”或“abcde”之类的东西。如果找不到整数前缀,则返回 0。后缀是整数前缀后面的任何内容:如果找不到后缀,则返回 nil ('')。

public static void Parse( string value , out int number , out string suffix )
{
  number = 0 ;
  int i = 0 ;
  for ( i = 0 ; i < value.Length && char.IsDigit( value[i] ) ; ++i )
  {
     number *= 10 ;
     number += ( value[i] - '0' ) ;
  }
  suffix = value.Substring(i) ;
  return ;
}

【讨论】:

    【解决方案2】:

    这些是表达式:

    [^\d]+ <- not digit
    \d+ <- digits
    


    编辑
        static int GetNumber(string text)
        {
            string pat = @"\d+";
            int output;
            // Instantiate the regular expression object.
            Regex r = new Regex(pat, RegexOptions.IgnoreCase);
            Match m = r.Match(text);
            if (int.TryParse(m.Value, out output))
                return output;
            else
                return int.MinValue; // something unlikely
        }
    
        static char GetChar(string text)
        {
            string pat = @"[^\d]";
            int output;
            // Instantiate the regular expression object.
            Regex r = new Regex(pat, RegexOptions.IgnoreCase);
            Match m = r.Match(text);
            return m.Value.Length == 1 ? m.Value[0] : '\0';
        }
    

    您实际上只需要创建一次 RegExp 对象,而不是在每次方法调用时。

    【讨论】:

    • 用户如何捕获这些表达式匹配的值?
    • @Anthony Pegram :两个函数都返回捕获的值。还是您的意思是在多个返回值的情况下?
    • @Eric,我的评论早于他的修订版。 ;) 检查历史以获取正确的上下文。
    • 第二个函数名为 GetChar 并返回字符串。有点混乱。
    • @pencilCake,这有帮助吗?
    【解决方案3】:
        private char GetChar(string t)
        {
            return t.Substring(t.Length - 1, 1)[0];
        }
    
        private int GetNumber(string t)
        {
            return Int32.Parse(t.Substring(0, t.Length - 1));
        }
    

    编辑:GetNumber 函数的第二个版本,使用 'TryParse' 而不是 'Parse':

        private int GetNumber(string t)
        {
            int result;
            if(Int32.TryParse(t.Substring(0, t.Length - 1), out result) == false)
            {
                 // you can handle here incorrect 't' value if you want
            }
            return result;
        }
    

    【讨论】:

    • 始终 Int32.TryParse 是最好的方法 2。
    • @zenwalker。我添加了使用 TryParse 而不是 Parse 的替代函数版本
    【解决方案4】:

    你可以试试这样的:

    static string getNumber(String str)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char chr in str)
        {
            try
            {
                int x = int.Parse(chr.ToString());
                sb.Append(chr);
            } catch (Exception ex) {
                return sb.ToString();
            }
        }
    
        return null;
    }
    
    static string getCode(String str)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char chr in str)
        {
            try
            {
                int x = int.Parse(chr.ToString());
            }
            catch (Exception ex)
            {
                sb.Append(chr);
            }
        }
    
        return sb.ToString();
    }
    
    
    
    // 95
    Console.WriteLine(getNumber("95d"));
    // a
    Console.WriteLine(getCode("95d"));
    

    【讨论】:

    • 这不是你应该做的事情。一方面,不应将异常用于控制流。
    • @AnthonyPegram,是的,感谢您指出这一点,但我只是想展示一种不同的方式。
    • 这很好,但是你明白为什么这不是一个好方法吗?有更好的方法来测试你是否正在处理一个数字,而不是尝试转换它并在它失败时捕获异常。特别令人震惊的是,当您尝试获取字符代码时,catch 块是所需的路径。研究解析或验证输入的更好方法。
    • 有了 TryParse,为什么还要进行异常处理。不好我的朋友。
    • @zenwalker,正如我之前所说,这是另一种方式,当然,即使不是建设性的评论,您也可以随意指出任何内容。但是只有接受“规则”的答案,“stackoverflow”会是什么?这个社区很棒,因为人们和乐于助人。
    【解决方案5】:

    RegEx 解决方案的简单替代方案。

    string letters = Seperate( "95d",  c => Char.IsLetter( c ) );
    string numbers = Seperate( "95d", c => Char.IsNumber( c ) );
    
    static string Seperate( string input, Func<char,bool> p )
    {
        return new String( input.ToCharArray().Where( p ).ToArray() );
    }
    

    您可以将“分离”作为字符串的扩展方法,让事情变得更简洁。

    【讨论】:

      【解决方案6】:

      正则表达式可能有点矫枉过正——您证明的示例具有非常简单、一致的格式。尝试以下功能作为起点:

      public int GetNumber(string input)
      {
         return int.Parse(input.Substring(0, input.Length - 1));
      }
      
      
      public char GetCode(string input)
      {
         return input.Last();
      }
      

      我说“作为起点”是因为您需要考虑边缘情况——您将如何处理空字符串?字符串可以以多个字母字符结尾,如果是,您将如何处理?希望这些例子能让车轮转动。

      【讨论】:

      • 如果我传给你“5m”,你的GetNumber函数会抛出。如果我将“95d”传递给您,您的函数将返回 9。您确定这是一个好的起点吗?
      【解决方案7】:
      public int GetNumber(string input)
      {
          string result = "";
      
          foreach (Char c in input)
          {
              if (Char.IsDigit(c))
                  result += c;
          }
      
          return Convert.ToInt32(result);
      }
      
      public string GetCode(string input)
      {
          string result = "";
      
          foreach (Char c in input)
          {
              if (!Char.IsDigit(c))
                  result += c;     // or return the char if you want only the first one.
          }
      
          return result;
      }
      

      没有测试,但对我来说,这似乎是实现这一目标的最佳方式。与其他答案相比,它也是提供最大灵活性的方法。

      【讨论】:

        【解决方案8】:
        string s = "95d";
        int number = Int32.Parse(s.Substring(0, s.Length - 1));
        char code = Char.Parse(s.Substring(s.Length - 1));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-20
          • 2019-01-17
          • 1970-01-01
          • 2015-02-07
          • 2012-12-11
          • 1970-01-01
          • 2014-01-10
          • 2013-05-23
          相关资源
          最近更新 更多