【问题标题】:Parse textbox and convert a group to percentage of another group解析文本框并将一个组转换为另一个组的百分比
【发布时间】:2015-07-29 14:34:37
【问题描述】:

我要做的是使用正则表达式将文本框解析为 3 个组。它是一个数学表达式,分为 3 组。该表达式最初为字符串格式,但将转换为整数以执行计算,然后再转换回字符串。第 1 组包含整数。第 2 组 包含操作数,第 3 组包含整数。

这是一个计算器应用程序,因此在单击按钮(百分比按钮)时,我想将第 3 组转换为第 1 组的百分比。

这是我尝试过的,但它不起作用。我错过了什么?

文本框中的表达式如下:

2 + 3 
2 * 3 
2 / 3 
2 - 3 

我想将每个表达式中的“3”转换为 2 的 3%。 然后显示变化:

2 + 0.06 
2 * 0.06 
2 / 0.06 
2 - 0.06 

String Expression = richTextBox1.Text;
Regex regEx = new Regex(@"([\+-]?\d+\.*\d*[eE][\+-]?\d+|[\-\+]?\d+\.*\d*)([\/\*\+\-])(-?\d+\.*\d*[eE][\+-]?\d+|-?\d+\.*\d*)");

Match m = regEx.Match(Expression);

while (m.Success)
{
    double result = Convert.ToDouble(m.Groups[3].Value);
    result = Convert.ToDouble(m.Groups[1].Value) / 100;
    if ((result < 0) || (m.Index == 0)) 
        Expression = regEx.Replace(Expression, result.ToString(), 1);
    else 
        Expression = regEx.Replace(Expression, "+" + result, 1);
    m = regEx.Match(Expression);
}

【问题讨论】:

  • 你能发布一个你试图解析的文本的例子吗?
  • 哪个部分不工作?您在计算中没有使用第 2 组或第 3 组,您只在计算中使用了第 1 组。为什么不直接要求用户输入第 1 组输入?
  • 不确定您要做什么,但您的正则表达式无法正确匹配 int's/floats。这可能会更好(没有空格)@"^([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)([/*+-])([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)$"
  • 文本框中的表达式如下所示: 2 + 3 或 2 * 3 或 2 / 3 或 2 - 3 我想将每个表达式中的“3”转换为 2 的 3%。然后显示变化:2 + 0.06 或 2 * 0.06 或 2 / 0.06 或 2 - 0.06
  • 我永远不敢编写自己的公式解析器。尽管如此,如果我愿意,我不会使用正则表达式。取而代之的是I would (and did) use a finished one

标签: c# regex parsing


【解决方案1】:

我认为编写公式解析器不在这个问题的范围内。我只能说明当前方法的问题所在。

首先,您没有考虑值之间的空格。 其次,您将整个表达式替换为其中的一部分。 第三,您对结果使用了多个分配,但我们只对第 3 组感兴趣。

这里是“固定”代码:替换回调方法...

public static string Repl(Match m)
{
    double result = Convert.ToDouble(m.Groups[3].Value);
    result = Convert.ToDouble(m.Groups[3].Value) / 100 * 2;
    if (result < 0 || m.Index == 0)
       return m.Value.Replace(m.Groups[3].Value, result.ToString());
    else 
       return m.Value.Replace(m.Groups[3].Value, "+" + result.ToString());
}

这就是我们所说的:

String Expression = "2 * 3";
Regex regEx = new Regex(@"([+-]?\d+\.*\d*[eE][+-]?\d+|[-+]?\d+\.*\d*)\s*([/*+-])\s*(-?\d+\.*\d*[eE][+-]?\d+|-?\d+\.*\d*)");
Expression = regEx.Replace(Expression,Repl);
Console.WriteLine(Expression);

当然,您可以将此回调方法转换为 lambda 表达式。

IDEONE demo

【讨论】:

    【解决方案2】:

    如果您只是转换表达式中的第二个数字,这个问题的范围似乎并不太难。我会使用Regex.Split() 的模式:

    "([-+/*])"
    

    这会将表达式分成三部分:

    • 第一个数字
    • 操作员
    • 第二个数字

    然后只需将第二个数字转换为 2 的 3% 并将 String.Join() 重新组合在一起。

    代码示例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    public class Program
    {
        public static void Main()
        {
            List<string> expressions = new List<string>
            {
                "2 + 3", 
                "2 * 3", 
                "2 / 3", 
                "2 - 3" 
            };
    
            Console.WriteLine("Before: ");
            expressions.ForEach(Console.WriteLine);
            Console.WriteLine();
    
            for (int i = 0; i < expressions.Count; i++)
            {
                string[] pieces = Regex.Split(expressions[i], "([-+/*])")
                    .Select((p, j) => j == 2 ? (2 * 0.03).ToString() : p.Trim())
                    .ToArray();
                expressions[i] = String.Join(" ", pieces);
            }
    
            Console.WriteLine("After: ");
            expressions.ForEach(Console.WriteLine);
            Console.WriteLine();
        }
    }
    

    结果:

    Before: 
    2 + 3
    2 * 3
    2 / 3
    2 - 3
    
    After: 
    2 + 0.06
    2 * 0.06
    2 / 0.06
    2 - 0.06
    

    Fiddle Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      • 2017-05-26
      相关资源
      最近更新 更多