2017-05-08 110 views
1

我甚至不知道如何对该问题进行短语处理,因此我提前致歉。我有一个由我们的质量检查使用的表单。它需要输入序列号 - 很多(有时是数百)。我在表单中为范围中的低位和高位数字设置了两个文本框(不必这样,但这是我最好的猜测)。我知道如何做到这一点,如果它只是整数(见下面的代码),但不是唯一的格式。格式的例子可能包括日期代码(“170508/1234”)或可能包括字母字符(ABC1234)。有各种各样的格式,但在任何情况下,我想找到最后一组数字的范围(通常是最后四位数字 - 就像“170508/1234 170508/1235 ...和ABC1234 ABC1235 ...不排除1234 1235 ....)。 预先感谢您确定可能包含字母和数字字符的数字范围

private void btnSN_Click(object sender, EventArgs e) 
    { 
     int from = Convert.ToInt32(txtSnStart.Text.Trim()); 
     int to = Convert.ToInt32(txtSnEnd.Text.Trim()); 

     for (int i = from; i <= to; i++) 


     { 

      txtSN.Text += i.ToString() +" "; 
     } 

回答

0

您可以使用RexEx的这一点,下面的正则表达式表达式应该在最后:

(\d+)$ 
匹配任何数量的数字

以下是修改后的代码:

// find the group of digits at end of entered text 
var fromMatch = Regex.Match(txtSnStart.Text.Trim(), @"(\d+)$"); 
int from = Convert.ToInt32(fromMatch.Groups[1].Value); 

// strip the matched digit group from entered text to get the prefix 
string prefix = txtSnStart.Text.Trim().SubString(0, txtSnStart.Text.Trim().LastIndexOf(from.ToString())); 

var toMatch = Regex.Match(txtSnEnd.Text.Trim(), @"(\d+)$"); 
int to = Convert.ToInt32(toMatch.Groups[1].Value); 

for (int i = from; i <= to; i++) 
{ 
    // combine the prefix and range value 
    txtSN.Text += string.Format("{0}{1} ", prefix, i.ToString()); 
} 
+0

谢谢 - 几乎在那里!唯一的事情是(我并没有明确表示道歉),我需要它来保留格式。你的代码在数字范围内工作得很好,我只需要它在写入txtSN.Text时保留字符在前面 –

+0

那么,说SnStart是'abc1234'而SnEnd是'xyz1236',输出应该是什么? – sachin

+0

前缀不会像这样改变,输入将始终为abC####或xyz ####。所以,对你的问题的一个例子是SnStart = abc1234 SnEnd将是abc1236,那么输出将是abc1234 abc1236 abc1236 –

0

如果将其分解为更小的部分,则此问题变得更加容易。

一旦发现问题的一小部分可能变得更加复杂,这将变得尤为重要。

输入是前缀,开始范围的数字和结束范围的数字。鉴于此,这里是有功能的类返回这些字符串:

public class StringRangeCreator 
{ 
    public IEnumerable<string> CreateStringRange(
     string prefix, int rangeStart, int rangeEnd) 
    { 
     if (rangeStart > rangeEnd) throw new ArgumentException(
      $"{nameof(rangeStart)} cannot be greater than {nameof(rangeEnd)}"); 
     return Enumerable.Range(rangeStart, (rangeEnd-rangeStart) + 1) 
      .Select(n => prefix + n); 
    } 
} 

Enumerable.Range创造了一系列数字。 Select取得该范围并返回一组字符串,其中包含与范围中的数字级联的前缀。

以及单元测试,以确保它的工作原理:

[TestClass] 
public class DetermineRangeFromLastFourCharacters 
{ 
    [TestMethod] 
    public void ReturnsExpectedRangeOfStrings() 
    { 
     var result = new StringRangeCreator().CreateStringRange("abc", 1, 10).ToList(); 
     Assert.AreEqual(10, result.Count); 
     Assert.AreEqual("abc1", result[0]); 
     Assert.AreEqual("abc10", result[9]); 
    } 
} 

但是,如果这些号码,那么你也许你不想ABC8,ABC9,ABC10。你可能需要ABC08,ABC09,ABC10。所有相同的长度。

所以这里是修改后的类。我对预计的行为可能会有点猜测。它可以让你指定的位数可选最小数,这样你可以垫相应:

public class StringRangeCreator 
{ 
    public IEnumerable<string> CreateStringRange(
     string prefix, int rangeStart, int rangeEnd, int minimumDigits = 1) 
    { 
     if (rangeStart > rangeEnd) throw new ArgumentException(
      $"{nameof(rangeStart)} cannot be greater than {nameof(rangeEnd)}"); 
     return Enumerable.Range(rangeStart, (rangeEnd-rangeStart) + 1) 
      .Select(n => prefix + n.ToString("0").PadLeft(minimumDigits, '0')); 
    } 
} 

和其他单元测试:

[TestMethod] 
public void PadsNumbersAccordingToParameter() 
{ 
    var result = new StringRangeCreator().CreateStringRange("abc", 999, 1001, 3).ToList(); 
    Assert.AreEqual(3, result.Count); 
    Assert.AreEqual("abc999", result[0]); 
    Assert.AreEqual("abc1001", result[2]); 
} 

其他一些情况下,您可能要考虑为负数或极大范围。

既然创建结果集的问题已经分解成一个简单的输入和输出类,您可以测试,剩下的就是从表单中取出输入并将其分解到这些输入中。这可能包括确保两个字符串具有相同的前缀并确保字符串的最后部分是数字。

但是,一旦它不是一个大方法,整个事情会变得简单一些。当你意识到你希望工作的方式不同时,这也使得更容易改变。验证你的输入可以是一步,然后获得结果可以是另一个。

单元测试帮助,因为你不想调试整个事情,看看它是否工作。 Enumerable.Range没有按照我认为的方式工作,所以我不得不修复一个错误。很容易找到并修复单元测试。如果我不得不运行整个应用程序,然后在调试器中逐步完成,那将会更加困难。

+0

这些并不完全是“模型”单元测试,因为每个测试都有多个断言(每个测试检查多个事件)。 –

+0

谢谢@Scott Hannen感谢您的输入 –

相关问题