修复System.FormatException

时间:2015-06-03 18:36:18

标签: c# debugging formatexception

我正在编写一个代码,它将查看名为a的文本文件中的一个组,如果该代码中的一行包含短语“Savings Found”,它将写出该行,如果有30%或更多的节省它会在前面放一个星号,如果它含有30%或更多并且节省了500美元或更多,它将放置两个星号。下面我有一个示例数据,一个控制台需要的示例,以及我到目前为止的代码:

git diff upstream/master

示例数据/示例

    string find = "Savings found:";
    foreach (var line in a.Where(w => w.Contains(find)))
       {
          var subStr = line.Substring(line.IndexOf(find) + find.Length);
          var startIndex = subStr.IndexOf('(');
          var endIndex = subStr.IndexOf(')');

          var savings = double.Parse(subStr.Substring(0, startIndex - 1).Trim());
          var percent = double.Parse(subStr.Substring(startIndex + 1, endIndex - startIndex - 2).Trim());

          Console.WriteLine("{0}{1}{2}", (percent >= 30) ? "*" : string.Empty,

          (percent >= 30 && savings >= 500) ? "*" : string.Empty,
                                                        line);
         }

我遇到的问题是我收到FormatException错误,我想我知道问题是什么。问题是subString的值是257.18以及之后的所有内容。我不想要一切之后我只想要这个号码。我该怎么做才能摆脱那些额外的垃圾,以便它可以编译?

这个问题类似于前面提到的问题,但是在那个答案中我得到了一个ArgumentIndexOutOfBounds异常,试图解决它,但是在实际修复问题方面做得并不多,因此这个问题背后的原因。

3 个答案:

答案 0 :(得分:0)

您可以使用正则表达式:

foreach(string line in a)
{
    Match m = Regex.Match(line, @"Savings\s+found:\s*\$(?<savings>\d+\.\d+)\s*\(\s*(?<percent>\d+\.\d+)\s*%");
    if (m.Success)
    {
        decimal savings = decimal.Parse(m.Groups["savings"].Value, CultureInfo.InvariantCulture);
        decimal percent = decimal.Parse(m.Groups["percent"].Value, CultureInfo.InvariantCulture);
        string prefix = string.Empty;
        if (percent >= 30)
        {
            if (savings >= 500)
                prefix = "**";
            else
                prefix = "*";
        }
        Console.WriteLine(prefix + line);
    }
}

答案 1 :(得分:0)

您似乎可以重现错误。太棒了!可重现的问题通常很容易解决。

假设您没有其他工具,如OzCode或ReSharper,这将是调试和修复它的方式:

一旦知道发生错误的行,就要使语句更简单。也就是说,将其分解为更小的部分。在你的情况下

var savings = double.Parse(subStr.Substring(0, startIndex - 1).Trim());

做太多事情,所以你真的不知道问题是什么。将其拆分为:

var savingsString = subStr.Substring(0, startIndex - 1).Trim();
var savings = double.Parse(savingsString);

因为这样,在调试过程中,您可以将监视添加到savingsString并查看它 Watch windows in VS

你可以考虑为什么&#34; $ 257.18&#34;无法解析并找到对策。使用之前的代码,您甚至不知道导致问题的输入。

潜在的对策:

  • 删除美元:.Replace("$","")
  • 稍后启动子字符串:subStr.Substring(1, ...)
  • savingsString = savingsString.Trim('$');如果你不能确定它是在开头还是结尾

从您的程序代码中,您似乎知道所有必需的方法,您只是不知道如何调试。

继续这种方法,您将能够解决代码的所有问题,甚至是未来的问题。

并且:我不能推荐正则表达式。它们是不可读的,没有人愿意维护它们。

答案 2 :(得分:-1)

我假设你想要“找到储蓄”后的数字和小数值: 正则表达式应该有所帮助。这可能是比这更好的方法,但这应该有效。

 string find = "Savings found:";
    foreach (var line in a.Where(w => w.Contains(find)))
       {
          //line = 5/21/2015 11:55:56 PM | Batch 6|386/767|50.33 %|CH2M-R|Processed NXRMN5...Checking refundable and non-refundable fares. Traditional Booking. Inside ticketing window. Minimum Savings Required: $131.00. Actual Savings: $257.18. Savings found: $257.18 (11.55 %). Savings were previously found."
          Regex regex = new Regex(@"Savings found:\s\$[0-9]*.[0-9]{2}\s*\([0-9]*.[0-9]{2} %\)");
          Match match = regex.Match(line);
          var savingsFoundSection = match.Value;

          MatchCollection matches = Regex.Matches(savingsFoundSection, @"[0-9]*\.[0-9]{2}");
          String savingsString = matches[0].Value;
          String percentString = matches[1].Value;
          //savingString = "257.18"
          //precentString = "11.55"

          var savings = double.Parse(savingsString);
          var percent = double.Parse(percentString);

          Console.WriteLine("{0}{1}{2}", (percent >= 30) ? "*" : string.Empty,

          (percent >= 30 && savings >= 500) ? "*" : string.Empty,
                                                        line);
         }