解析所有可能类型的不同架构维度输入

jth*_*h41 9 c# regex linq string string-parsing

我正在为我们公司的产品编写一个库,它将采用我们的用户已经熟悉的任何类型的体系结构维度作为从字符串转换为double的函数的输入.以下是我们希望有效的输入类型列表.

Input| 意义| Output(英寸由双人代表)


12.5' | 12英尺和6英寸|150.0

11" | 11英寸|11.0

3/16"| 英寸的3个十六分之一|0.1875


在英尺和英寸以及英寸和十六分之间可以使用或不使用空格

11' 11"| 11英尺和11英寸|143.0

11'11"| 11英尺和11英寸|143.0


在英尺和英寸之间或英寸和十六分之间或两者之间可以使用或不使用破折号

12'-11"| 12英尺和11英寸|155.0

12' 11 3/16"| 12英尺和11英寸和3个十六分之二|155.1875

12' 11-1/2"| 12英尺和11英寸和8个十六分之二|155.5


在英尺和英寸以及英寸和十六分之间可以使用任意数量的空间

12' 11 1/2"| 12英尺和11英寸和8个十六分之二|155.5


还提供了另一种更简单的格式

121103| 12英尺和11英寸和3个十六分之二|155.1875


每种格式都可以使用否定词

-121103| 12英尺和11英寸和3个十六分之二|-155.1875

-11'11"| 11英尺和11英寸|-143.0

我们目前正在使用一组极其复杂的分支逻辑来尝试确定输入尝试模拟的格式......并且它并不适用于所有情况.

是否有一些可能的LINQ和正则表达式和巫术的组合,我们可以用来确定如何解析字符串?

另请注意,我们确实希望避免在表单上给出一个简单的组合框来选择输入格式类型.

Try*_*hen 5

此函数适用于您的输入值示例。

public static Double Conv(String inp)
{
    String expr= "((?<feet>\\d+)(?<inch>\\d{2})(?<sixt>\\d{2}))|((?<feet>[\\d.]+)')?[\\s-]*((?<inch>\\d+)?[\\s-]*((?<numer>\\d+)/(?<denom>\\d+))?\")?";
    Match m = new Regex(expr).Match(inp);
    Double feet = m.Groups["feet"].Success ? Convert.ToDouble(m.Groups["feet"].Value) : 0;
    Int32  inch = m.Groups["inch"].Success ? Convert.ToInt32(m.Groups["inch"].Value) : 0;
    Int32  sixt = m.Groups["sixt"].Success ? Convert.ToInt32(m.Groups["sixt"].Value) : 0;
    Int32 numer = m.Groups["numer"].Success ? Convert.ToInt32(m.Groups["numer"].Value) : 0;
    Int32 denom = m.Groups["denom"].Success ? Convert.ToInt32(m.Groups["denom"].Value) : 1;
    return feet*12+inch+sixt/16.0+numer/Convert.ToDouble(denom);
}    
Run Code Online (Sandbox Code Playgroud)

请注意,除了您提供的有效输入之外,我没有做出任何努力来测试其他输入。例如,您可能希望至少在某些捕获组中检查是否成功,或者可能将验证作为单独的步骤进行。这段代码是在考虑解析的情况下编写的。

编辑:

这是一个更强大的版本:

public static Double Conv(String inp)
{
    String expr= "^\\s*(?<minus>-)?\\s*(((?<feet>\\d+)(?<inch>\\d{2})(?<sixt>\\d{2}))|((?<feet>[\\d.]+)')?[\\s-]*((?<inch>\\d+)?[\\s-]*((?<numer>\\d+)/(?<denom>\\d+))?\")?)\\s*$";
    Match m = new Regex(expr).Match(inp);
    if(!m.Success || inp.Trim()=="")
    {
        // maybe throw exception or set/return some failure indicator
        return 0; // here using return value zero as failure indicator
    }
    Int32 sign  = m.Groups["minus"].Success ? -1 : 1;
    Double feet = m.Groups["feet"].Success ? Convert.ToDouble(m.Groups["feet"].Value) : 0;
    Int32  inch = m.Groups["inch"].Success ? Convert.ToInt32(m.Groups["inch"].Value) : 0;
    Int32  sixt = m.Groups["sixt"].Success ? Convert.ToInt32(m.Groups["sixt"].Value) : 0;
    Int32 numer = m.Groups["numer"].Success ? Convert.ToInt32(m.Groups["numer"].Value) : 0;
    Int32 denom = m.Groups["denom"].Success ? Convert.ToInt32(m.Groups["denom"].Value) : 1;
    return sign*(feet*12+inch+sixt/16.0+numer/Convert.ToDouble(denom));
}
Run Code Online (Sandbox Code Playgroud)

对于空字符串和带有示例允许之外的额外字符的字符串,它会失败。五位或更多位被视为更简单的格式。

更改是开始和结束锚点以及允许的前导和尾随空白,以及 if 语句中对空/仅空白字符串的特殊情况检查。

免责声明:这显然还没有针对所有可能的非法输入进行测试,而且我也不是 ac# 程序员:-)