解析所有可能类型的不同建筑维度输入
我正在为我们公司的产品编写一个库,它将采用我们用户已经熟悉的任何体系结构维度作为从字符串转换为double的函数的输入。 以下是我们希望有效的输入类型列表。
Input
| 意义| Output
(英寸用双精度表示)
12.5'
| 12英尺和6英寸| 150.0
11"
| 11英寸| 11.0
3/16"
|英寸的十六分之一| 0.1875
在英尺和英寸以及英寸和十六分之间可以使用或不使用空格
143.0
11' 11"
| 11英尺和11英寸| 143.0
11'11"
| 11英尺11英寸| 143.0
在英尺和英寸之间或英寸和十六分之间或两者之间可以使用或不使用破折号
12'-11"
| 12英尺和11英寸| 155.0
155.1875
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和正则表达式和巫术的组合,我们可以用来确定如何解析字符串?
另请注意,我们确实希望避免在表单上给出一个简单的combobox来选择输入格式类型。
此函数适用于您的输入值示例。
public static Double Conv(String inp) { String expr= "((?\d+)(?\d{2})(?\d{2}))|((?[\d.]+)')?[\s-]*((?\d+)?[\s-]*((?\d+)/(?\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); }
请注意,除了您提供的有效输入之外,我没有做任何其他输入测试。 您可能希望例如在至少一些捕获组中检查成功,或者可以作为单独的步骤进行validation。 这段代码是在解析时制作的。
编辑:
这是一个更强大的版本:
public static Double Conv(String inp) { String expr= "^\s*(?-)?\s*(((?\d+)(?\d{2})(?\d{2}))|((?[\d.]+)')?[\s-]*((?\d+)?[\s-]*((?\d+)/(?\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)); }
对于空字符串,以及除了示例允许的额外字符的字符串,它都会失败。 五个或更多数字被视为更简单的格式。
更改是开始和结束锚点,允许前导和尾随空格,以及if语句中仅用于emtpy / whitespace的字符串的特殊情况检查。
免责声明:这显然没有针对每一个可能的非法输入进行测试,反正我不是ac#programmer ?
这可能会将您的复杂性从分支逻辑转移到正则表达式逻辑:
/(?(?d+)(?d{2})(?d{2}))|((?[d.]+)')?[s-]*((?d+)?[s-]*((?d+)/(?d+))?")?/
如果组特殊匹配,则您具有特殊语法,并且输出为英尺 * 12 + 英寸 + _sixt_ / 16,使用组上的ToDecimal
。 如果没有,如果输入有效,您将有一个或多个组foot , inch , numer和denom 。 对于其余部分使用ToDouble
,对其余部分使用ToDecimal,并确保在分数中检查除零。
概念validation演示代码(ruby):
[ ["12.5' "," 12 Feet and six inches "," 150.0"], ["11" "," 11 Inches "," 11.0"], ["3/16" "," 3 sixteenths of an Inch "," 0.1875"], ["11' 11" "," 11 Feet and 11 Inches "," 143.0"], ["11'11" "," 11 Feet and 11 Inches "," 143.0"], ["12'-11" "," 12 Feet and 11 Inches "," 155.0"], ["12' 11 3/16" "," 12 Feet and 11 Inches and 3 sixteenths "," 155.1875"], ["12' 11-1/2" "," 12 Feet and 11 Inches and 8 sixteenths "," 155.5"], ["12' 11 1/2" "," 12 Feet and 11 Inches and 8 sixteenths "," 155.5"], ["121103 "," 12 Feet and 11 Inches and 3 sixteenths "," 155.1875"], ["", "empty string", "0"], ].each{|i,d,o| m = /(?(?d+)(?d{2})(?d{2}))|((?[d.]+)')?[s-]*((?d+)?[s-]*((?d+)/(?d+))?")?/.match(i) #puts "#{(1..8).map{|n|"%15s"%m[n].inspect}.join}" puts "#{"%20s"%i} #{"%10s"%o} #{m[:special] ? m[:feet].to_i*12+m[:inch].to_i+m[:sixt].to_i/16.0 : m[:feet].to_f*12+m[:inch].to_i+(m[:numer].to_i.to_f/(m[:denom]||1).to_i)} " }
输出:
12.5' 150.0 150.0 11" 11.0 11.0 3/16" 0.1875 0.1875 11' 11" 143.0 143.0 11'11" 143.0 143.0 12'-11" 155.0 155.0 12' 11 3/16" 155.1875 155.1875 12' 11-1/2" 155.5 155.5 12' 11 1/2" 155.5 155.5 121103 155.1875 155.1875 0 0.0
请注意,除了您提供的有效输入之外,我没有做任何其他输入测试。 您可能希望例如检查至少一些捕获组中的非零值,或者可以将validation作为单独的步骤进行。 这段代码是在解析时制作的。
上述就是C#学习教程:解析所有可能类型的不同建筑维度输入分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1033439.html