修复 System.FormatException
Fixing a System.FormatException
我正在编写一个代码,它将查看名为 a 的文本文件中的一个组,如果该代码中的一行包含短语 "Savings Found",它将写出该行,如果有 30%或更多储蓄,它会在前面放置一个星号,如果它包含 30% 或更多并且有 500 美元或更多储蓄,它会放置两个星号。下面我有一个示例数据,一个控制台需要是什么样子的示例,以及我到目前为止的代码:
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);
}
样本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: 1.00. Actual Savings: 7.18. Savings found: 7.18 (11.55 %). Savings were previously found.
我遇到的问题是出现 FormatException 错误,我想我知道问题出在哪里。问题是 subString 的值是 257.18 以及之后的所有值。我不想要它之后的一切我只想要数字。我该怎么做才能摆脱多余的垃圾以便它可以编译?
这个问题类似于之前问的一个问题,但是在那个答案中我得到了一个 ArgumentIndexOutOfBounds 异常,试图修复它,但在实际修复问题上没有走多远,因此这个问题背后的原因。
我假设你想要 "Savings found:" 之后的数字和小数值
正则表达式应该有帮助。可能有比这更好的方法,但这应该可行。
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: 1.00. Actual Savings: 7.18. Savings found: 7.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);
}
您可以为此使用正则表达式:
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);
}
}
看来您能够重现错误。那太棒了!可重现的问题通常很容易修复。
假设您没有其他工具,如 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
添加一个手表,看看它是
你可以想一想为什么“$257.18”无法被解析,并找出对策。使用之前的代码,您甚至不知道导致问题的输入。
可能的对策:
- 删除美元:
.Replace("$","")
- 稍后开始子字符串:
subStr.Substring(1, ...)
savingsString = savingsString.Trim('$');
如果不能确定是开头还是结尾
从你的程序代码来看,你好像知道所有需要的方法,只是不知道如何调试。
继续使用这种方法,您将能够解决代码中的所有问题,甚至是未来的问题。
并且:我不推荐 Regex。它们不可读,没有人愿意维护它们。
我正在编写一个代码,它将查看名为 a 的文本文件中的一个组,如果该代码中的一行包含短语 "Savings Found",它将写出该行,如果有 30%或更多储蓄,它会在前面放置一个星号,如果它包含 30% 或更多并且有 500 美元或更多储蓄,它会放置两个星号。下面我有一个示例数据,一个控制台需要是什么样子的示例,以及我到目前为止的代码:
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);
}
样本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: 1.00. Actual Savings: 7.18. Savings found: 7.18 (11.55 %). Savings were previously found.
我遇到的问题是出现 FormatException 错误,我想我知道问题出在哪里。问题是 subString 的值是 257.18 以及之后的所有值。我不想要它之后的一切我只想要数字。我该怎么做才能摆脱多余的垃圾以便它可以编译?
这个问题类似于之前问的一个问题,但是在那个答案中我得到了一个 ArgumentIndexOutOfBounds 异常,试图修复它,但在实际修复问题上没有走多远,因此这个问题背后的原因。
我假设你想要 "Savings found:" 之后的数字和小数值 正则表达式应该有帮助。可能有比这更好的方法,但这应该可行。
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: 1.00. Actual Savings: 7.18. Savings found: 7.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);
}
您可以为此使用正则表达式:
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);
}
}
看来您能够重现错误。那太棒了!可重现的问题通常很容易修复。
假设您没有其他工具,如 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
添加一个手表,看看它是
你可以想一想为什么“$257.18”无法被解析,并找出对策。使用之前的代码,您甚至不知道导致问题的输入。
可能的对策:
- 删除美元:
.Replace("$","")
- 稍后开始子字符串:
subStr.Substring(1, ...)
savingsString = savingsString.Trim('$');
如果不能确定是开头还是结尾
从你的程序代码来看,你好像知道所有需要的方法,只是不知道如何调试。
继续使用这种方法,您将能够解决代码中的所有问题,甚至是未来的问题。
并且:我不推荐 Regex。它们不可读,没有人愿意维护它们。