我想写一个函数,它接受一个字符串并返回最后至少3位数的字符串

时间:2017-05-18 08:00:36

标签: c# unit-testing

如果传入的字符串末尾已有3位数字,则返回不变。如果传入的字符串末尾没有3位数字,则需要在末尾的任何数字前插入零以具有3位数字。

我已经完成了编码,我已经在private static string stringCleaner(string inputString)中添加了一些逻辑来实现,但它给出了这个错误:

  

测试:' A12'预计:' A012'例外:索引超出了数组的范围。

     

测试:' A12345'预计:' A12345'例外:索引超出了数组的范围。

     

测试:' A1B3'预计:' A1B003'例外:索引超出了数组的范围。

     

测试:''预计:' 000'例外:对象引用未设置为对象的实例。

     

测试:''预计:' 000'实际:' 000'结果:通过

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConvertToCamelCaseCS
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<string[]> testValues = new List<string[]>()
                {
                    new string[]{"A12","A012"},
                    new string[]{"A12345","A12345"},
                    new string[]{"A1B3","A1B003"},
                    new string[]{null, "000"},
                    new string[]{"", "000"}
                };
                foreach (string[] testValue in testValues)
                {
                    testStringCleaner(testValue[0], testValue[1]);
                }
                Console.ReadLine();
            }


            private static void testStringCleaner(string inputString, string expectedString)
            {
                try
                {
                    String actualString = stringCleaner(inputString);
                    String passOrFail = (actualString == expectedString) ? "Pass" : "Fail";


                    Console.WriteLine("Test:'{0}' Expected:'{1}' Actual:'{2}' Result:{3}", inputString, expectedString, actualString, passOrFail);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Test:'{0}' Expected:'{1}' Exception:{2}", inputString, expectedString, ex.Message);
                }
            }



            private static string stringCleaner(string inputString)
            {
                string result = inputString;
                int lengthOfString = result.Length;
                int changeIndex = 0;

                if (lengthOfString == 0)
                {
                     result = "000";
                }
                else
                {
                    for (int i = lengthOfString; i >= lengthOfString - 2; i--)
                    {
                        char StrTOChar = (char)result[i];
                        int CharToInt = (int)StrTOChar;
                        if (CharToInt >= 65 && CharToInt <= 122)
                        {
                            changeIndex = i;
                            break;
                        }
                    }

                    if (lengthOfString == changeIndex + 3)
                    {
                        return result;
                    }
                    else
                    {
                        if (changeIndex == lengthOfString)
                        {
                           return result = result + "000";
                        }
                        else if (changeIndex + 1 == lengthOfString)
                        {
                            return result = result.Substring(0, changeIndex) + "00" + result.Substring(changeIndex + 1, lengthOfString);
                        }
                        else if(changeIndex+2==lengthOfString)
                        {
                            return result = result.Substring(0, changeIndex) + "0" + result.Substring(changeIndex + 1, lengthOfString);
                        }

                    }
                }
                return result;
            }
        }
    }

3 个答案:

答案 0 :(得分:0)

让我们实施:

private static string stringCleaner(string value) {
  // let's not hardcode magic values: 3, "000" etc. but a have a constant 
  const int digits_at_least = 3;

  // special case: null or empty string
  if (string.IsNullOrEmpty(value))
    return new string('0', digits_at_least);

  int digits = 0;

  // let's count digits starting from the end
  //   && digits < digits_at_least - do not loop if we have enough digits
  //   (value[i] >= '0' && value[i] <= '9') - we want 0..9 digits only, 
  //      not unicode digits (e.g. Persian ones) - char.IsDigit
  for (int i = value.Length - 1; i >= 0 && digits < digits_at_least; --i)
    if (value[i] >= '0' && value[i] <= '9')
      digits += 1;
    else
      break;

  if (digits >= digits_at_least) // we have enough digits, return as it is
    return value;
  else
    return value.Substring(0, value.Length - digits) + 
           new string('0', digits_at_least - digits) + // inserting zeros
           value.Substring(value.Length - digits);
}

试验:

  using System.Linq;

  ... 

  var testValues = new string[][] {
     new string[]{"A12","A012"},
     new string[]{"A12345","A12345"},
     new string[]{"A1B3","A1B003"},
     new string[]{null, "000"},
     new string[]{"", "000"}
  };

  // Failed tests
  var failed = testValues
    .Where(test => test[1] != stringCleaner(test[0]))
    .Select(test => 
       $"stringCleaner ({test[0]}) == {stringCleaner(test[0])} expected {test[1]}");

  string failedReport = string.Join(Environment.NewLine, failed);

  // All failed tests
  Console.WriteLine(failedReport);

  // All tests and their results
  var allTests = testValues
    .Select(test => new {
      argument = test[0],
      expected = test[1],
      actual = stringCleaner(test[0]),
    })
    .Select(test => $"{(test.expected == test.actual ? "passed" : $"failed: f({test.argument}) = {test.actual} expected {test.expected}")}");

  string allReport = string.Join(Environment.NewLine, allTests);

  Console.WriteLine(allReport); 

结果(没有failedReport并且所有测试都通过了):

passed
passed
passed
passed
passed

答案 1 :(得分:0)

从这个有点令人困惑的问题和代码中我可以看出来的事情过于复杂。

我会使用substring来提取最后3个字符,然后从后面检查该字符串是否是使用Char.IsDigit的数字。根据您遇到非数字的时间,您可以使用简单的字符串连接添加一定量的零。

或许尝试从头开始重写代码,因为您可能更了解如何执行此操作。

答案 2 :(得分:0)

char StrTOChar = (char)result[i];

你的问题就在这一行。 (行:60) 你用的是从result.Length开始的i。并且,结果[result.Length]超出了数组的范围。您必须使用它低于数组的长度。