简体   繁体   English

修复System.FormatException

[英]Fixing a System.FormatException

I am writing a code that will look at a group in a text file called a, and if a line in that code contains the phrase "Savings Found" it will write out that line, and if has 30% or more savings it will place an asterisk in front and if it contains 30% or more and has $500 or more savings, it will place two asterisks. 我正在编写一个代码,该代码将查看名为a的文本文件中的组,并且如果该代码中的一行包含短语“ Savings Found”,它将写出该行,如果节省30%或更多,它将放置如果前面的星号包含30%或更多并且有$ 500或更多的储蓄,它将放置两个星号。 Below I have a sample data, an example of what the console needs to look like, and the code I have thus far: 下面是一个示例数据,该示例显示了控制台的外观,以及到目前为止的代码:

    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);
         }

Sample data/example 样本数据/示例

* 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.

The problem that I am having is I am getting a FormatException error, and I think I know what the problem is. 我遇到的问题是我收到了FormatException错误,我想我知道问题出在哪里。 The problem is that the value of subString is the 257.18 and everything after that. 问题是subString的值是257.18,之后的所有值。 I don't want everything after it I just want the number. 我不想要所有内容,我只想要数字。 What can I do to get rid of that extra junk so it can compile? 我该怎么办才能消除多余的垃圾,使其可以编译?

This problem is similar to a previous question asked, however in that answer I get an ArgumentIndexOutOfBounds exception, tried to fix it, but did not go far in actually fixing the problem, hence the reasoning behind this question. 这个问题类似于先前提出的问题,但是在该答案中,我得到了ArgumentIndexOutOfBounds异常,试图解决该异常,但是在实际解决问题上并没有走多远,因此该问题背后的原因。

You can use regex for that: 您可以为此使用正则表达式:

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);
    }
}

It seems you are able to reproduce the error. 看来您能够重现该错误。 That's great! 那很棒! Reproduceable problems are typically easy to fix. 可重现的问题通常很容易解决。

Assuming you have no other tools like OzCode or ReSharper, this would be the way of debugging and fixing it: 假设您没有其他工具,例如OzCode或ReSharper,这将是调试和修复它的方法:

Once you know the line in which the error occurs, make the statement simpler. 一旦知道发生错误的行,就使语句更简单。 That is, break it down into smaller parts. 也就是说,将其分解成较小的部分。 In your case 就你而言

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

Does too many things, so you don't really know what the problem is. 做太多事情,所以您真的不知道问题出在哪里。 Split that into: 将其拆分为:

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

Because then, during debugging, you can add a watch to savingsString and see that it is 因为这样,在调试期间,您可以将手表添加到savingsString并看到它是 在VS中观看窗口

You can think about the fact why "$257.18" cannot be parsed and find counter measures to it. 您可以考虑以下事实:为什么无法解析“ $ 257.18”并找到对策。 With the code before, you didn't even know the input which caused the problem. 使用之前的代码,您甚至都不知道导致问题的输入。

Potential countermeasures: 潜在的对策:

  • remove the dollar: .Replace("$","") 删除美元: .Replace("$","")
  • start the substring later: subStr.Substring(1, ...) 稍后启动子字符串: subStr.Substring(1, ...)
  • savingsString = savingsString.Trim('$'); if you cannot be sure whether it is in the beginning or the end 如果您不确定是开头还是结尾

From your program code, it seems you know all required methods, you just don't know how to debug. 从程序代码看来,您知道所有必需的方法,只是不知道如何调试。

Continue with this approach and you'll be able to fix all problems of your code and even future problems. 继续这种方法,您将能够解决代码中的所有问题,甚至将来的问题。

And: I can't recommend Regex. 而且:我不推荐正则表达式。 They are unreadable and nobody wants to maintain them. 它们是不可读的,没有人想要维护它们。

I'm assuming you want the number and decimal values after "Savings found:" regex should help. 我假设您想在“发现节省:”正则表达式后使用数字和十进制值。 Theres probably a better way than this, but this should work. 可能有比这更好的方法,但这应该可行。

 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);
         }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM