【问题标题】:Regex to restrict input into latitude (in decimal degrees) textbox正则表达式将输入限制为纬度(十进制度)文本框
【发布时间】:2021-01-24 17:54:28
【问题描述】:

我有一个带有文本框的 WPF 应用程序,我的用户将在其中输入十进制度的纬度值(高达 7 位精度)。当然,有效纬度范围从 -90.0000000 到 90.0000000。我正在尝试创建一个正则表达式来限制通过 PreviewTextInput 事件对文本框的输入,类似于:

    private void latitudeTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        e.Handled = !ValidateDecimalString(e.Text);
    }

    public static bool ValidateDecimalString(string decimalString)
    {
        Regex regex = new Regex("[^0-9]+");
        return !regex.IsMatch(decimalString);
    }

我当前的正则表达式只允许输入数字,但我还需要执行一些其他限制,例如:

  • 纬度可能是负数,所以我需要考虑减号(“-”),但前提是它作为第一个字符出现
  • 纬度只能包含一个小数点(“.”)

有效纬度值示例:

  • 90
  • 90.0
  • -90.0000000

我可以通过修改我的正则表达式来实现这些额外的限制吗?如果是这样,怎么做?谢谢!

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    虽然您的问题是如何使用正则表达式验证纬度,但似乎更好的方法是使用 Decimal.TryParse 之类的方法。

     public static bool ValidateLatitudeString(string decimalString)
        {
            decimal validLatitude;
            if (decimal.TryParse(decimalString, out validLatitude))
            {
                if (validLatitude >= -90.0M && validLatitude <= 90.0M)
                {
                    return true;
                }
            }
    
            return false;
        }
    

    【讨论】:

    • 我有一个像这样的现有验证规则,它会在输入数字后检查数字的范围。我试图用正则表达式完成的是简单地限制输入到文本框(因此使用 PreviewTextInput 事件)。
    • @user685869 嗯,在这种情况下,您为什么不直接使用"^-?[0-9]+([.][0-9]*)?$" 进行验证?虽然,请参阅我的答案,以获取大部分或完全正确检查数字的内容,但并没有那么不同。
    • 很公平。如果您已经在后端验证这种方式,则可能只有一个允许 numbers 的正则表达式。和 -。如果他们用 99.9 之类的东西搞砸了,那么使用后端验证来捕捉它。并不是说您不能编写一些适用于所有边缘情况的长正则表达式。
    【解决方案2】:

    这个怎么样?

    public static bool ValidateDecimalString(string decimalString)
    {
        Regex regex = new Regex("^-?([0-9]|[1-8][0-9]|90)([.][0-9]*)?$");
        return regex.IsMatch(decimalString);
    }
    

    这将允许一个可选的前导连字符减号,后跟一个从 0 到 90 的数字(但不是 999 或 01),后跟一个可选的小数部分。不过它会允许90.1;禁止这种用途:

    public static bool ValidateDecimalString(string decimalString)
    {
        Regex regex = new Regex("^-?(([0-9]|[1-8][0-9])([.][0-9]*)?|90([.]0*))$");
        return regex.IsMatch(decimalString);
    }
    

    这将允许90.0,但不允许90.1

    【讨论】:

      【解决方案3】:

      试试这样的

      public static bool ValidateDecimalString(string decimalString)
      {
          Regex regex = new Regex(@"^(-)?([0-9]+)(\.[0-9]+)?$");
          return regex.IsMatch(decimalString);
      }
      

      为了验证范围,最好使用转换后的值,例如

      public static bool ValidateLatitudeString(string decimalString)
      {
          if(ValidateDecimalString(decimalString)){
              double lat = 0;
              return double.TryParse(decimalString, out lat) && lat<=90.0 && lat>=-90;
          }
          return false;
      }
      

      所以没有正则表达式可能会更好

      public static bool ValidateLatitudeString(string decimalString)
      {
          double lat = 0;
          return double.TryParse(decimalString, out lat) && lat<=90.0 && lat>=-90;
      }
      

      【讨论】:

      • 不错的干净答案。如果你打算大量使用这个功能,你可能想把它放在一个扩展类中,DecimalStringExtender什么的,并将参数更改为this string decimalString。您还可以通过将 Regex 存储为静态成员变量 (static readonly Regex DecimalRegex = ...) 来获得一些性能提升。最后,考虑使用RegexOptions.Compiled 以获得额外的性能提升。
      • -99999999Z999999 与你的正则表达式怎么样?
      • 有效纬度范围从 -90.0000000 到 90.0000000 => ValidateDecimalString("999"); ????
      • @L.B - true :-) 正则表达式不应该测试范围,而是测试格式,以便在正则表达式使用转换和比较后更好地测试范围
      • 您的逻辑表明+89.-.0 不在十进制-90 之间。和 90. 这些应该通过表单测试,否则,表单应该是唯一的测试。
      【解决方案4】:

      另一种方式^-?[0-8]?\d(?:\.\d*)?|-?90(?:\.0+)?$Demo

      【讨论】:

        【解决方案5】:

        有很多选择。一种方式 -

         #  @"^-?(?:(?:[0-9]|[1-8][0-9])(?:\.[0-9]{1,7})?|90(?:\.0{1,7})?)$"
        
         ^ 
         -?
         (?:
              (?:
                   [0-9] 
                |  [1-8] [0-9] 
              )
              (?: \. [0-9]{1,7} )?
           |  
              90  
              (?: \. 0{1,7} )?
         )
         $
        

        匹配巨人边缘情况

         #  @"^-?(?:(?:[0-9]|[1-8](?:[0-9]|$))(?:\.(?:[0-9]{1,7}|$))?|9(?:0|$)(?:\.(?:0{1,7}|$))?)?$"
        
         ^ 
         -?
         (?:
              (?:
                   [0-9]  
                |  [1-8] (?: [0-9] | $ )
              )
              (?:
                   \. (?: [0-9]{1,7} | $ )
              )?
           |  
              9 (?: 0 | $ )
              (?:
                   \. (?: 0{1,7} | $ )
              )?
         )?
         $
        

        【讨论】:

          【解决方案6】:

          另一种方式(以双精度为例) - 不是正则表达式解决方案,但有效

                  bool IsDigitsOnlyLatitudaLongituda(string str, int deg)
                  {
              // deg with value 0 is latitude, deg with value 1 is longitude
                      bool provjera = true;
                      int brojactocki = 0;
                      if (str.Length > 0)
                      {
                          if (str[0] == '.')
                          {
                              provjera = false;
                          }
                          if (str[str.Length - 1] == '.')
                          {
                              provjera = false;
                          }
                      }
                      var brojac = 0;
                      foreach (char c in str)
                      {
                          brojac = brojac + 1;
                          if (brojac != 1)
                          {
                              if (c == '-')
                              {
                                  provjera = false;
                              }
                          }
                          if (c == '.')
                          {
                              brojactocki = brojactocki + 1;
                          }
                      }
                      if (brojactocki > 1)
                      {
                          provjera = false;
                      }
                      foreach (char c in str)
                      {
                          if ((c < '0' || c > '9') && (c != '.') && (c != '-'))
                          {
                              provjera = false;
                          }
                      }
                      double dblString;
                      if (deg == 0)
                      {
                          if (provjera == true)
                          {
                              dblString = Convert.ToDouble(str.Replace(".", ","));
                              if (dblString >= 90 || dblString <= -90)
                              {
                                  provjera = false;
                              }
                          }
                      }
                      if (deg == 1)
                      {
                          if (provjera == true)
                          {
                              dblString = Convert.ToDouble(str.Replace(".", ","));
                              if (dblString >= 180 || dblString <= -180)
                              {
                                  provjera = false;
                              }
                          }
                      }
                      return provjera;
                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-08-04
            • 1970-01-01
            • 2022-11-02
            • 1970-01-01
            • 2010-12-05
            • 2011-07-24
            • 2012-07-18
            相关资源
            最近更新 更多