我对C#比较陌生,并且有一个用户输入字符串(我希望是有效的)。
此字符串将组成信息的多个部分和子部分。
例如:
1-7 will //represent values 1 2 3 4 5 6 7
3:.25:7 //will be the numbers contained between 3 and 7 in increments of .25
// (3 3.25 3.5 3.75 4 ... 6.75 7)
1,4,5 //will represent values 1 4 5我希望能够遍历与此类似的单个字符串,并得到与用分号(;)分隔的数据一样多的数组。
主要目标是解析类似下面这样的东西:
1-7;3:.25:10;1,5,9;4-7由于上面有4个“数据集”,我应该创建4个包含这些值的新数组。如果我有n个“数据集”,我应该创建n个新的数组。
稍后,我将使用所有组合以嵌套的方式遍历数组。
此外,如果可能(不是必需的),能够进行如下表示形式的某种混合:
1-7,9,16:2:20;我希望我在这里试图实现的东西在我的示例中是有意义的。
谢谢!
发布于 2009-04-01 22:03:40
好吧,可能会有一个聪明的RegEx的答案,我会用我最喜欢的string.Split()函数试一试。
作为第一步,您可以将输入字符串拆分为';‘
string[] datasets = inputString.Split(';');至于你的最后一点,看起来逗号',‘的作用大同小异,你可以把它和Split(';', ',')合并,或者用分隔开
string[] parts = datasets[i].Split(',');然后,部件是以下三种情况之一:单个数字、范围或阶梯范围。
您可以使用string.IndexOf()和/或
string[] rangeParts = parts[j].Split('-');
string[] steppedParts = parts[j].Split(':');结果的长度应分别为2和3。
然后使用TryParse()检查生成的字符串,由于使用了标点符号,因此您最好修复区域性:
bool valid = double.TryParse(parts[k],
System.Globalization.NumberStyles.AllowDecimalPoint,
System.Globalization.CultureInfo.InvariantCulture, out value);这些都是零件,需要一些组装。
发布于 2009-04-01 22:11:05
我建议使用正则表达式。首先,我会使用下面的表达式将其分成几个部分。
^((?<section>[^;]+)(;|$))+然后将每个部分拆分为子部分。
^((?<subsection>[^,]+)(,|$))+现在匹配三种可能的子节类型。
(?<value>^[0-9]+$)|
(?<range>^[0-9]+-[0-9]+$)|
(?<rangewithstep>^[0-9]+:\.[0-9]+:[0-9]+$)最后,您必须分析范围类型子部分。
^(?<start>[0-9]+)-(?<end>[0-9]+)$
^(?<start>[0-9]+):(?<step>\.[0-9]+):(?<end>[0-9]+)$现在是将提取的字符串解析为数字并将其添加到数组中的问题。
我把所有的东西放在一个小的控制台应用程序中,它可以做这件事。它远非完美--没有错误处理,什么都没有,只是解析一个演示输入。我合并了前面提到的一些表达式,以获得更紧凑的代码,可能还会更好。
using System;
using System.Text.RegularExpressions;
using System.Globalization;
namespace RangeParser
{
class Program
{
static void Main(string[] args)
{
String input = "1-7,9,16:2:20;1-7; 3:.75 : 10;1,5,9;4-7";
Match sections = (new Regex(@"^((?<section>[^;]+)(;|$))+")).Match(input.Replace(" ", ""));
foreach (Capture section in sections.Groups["section"].Captures)
{
Console.Write("Section ");
Match subsections = (new Regex(@"^((?<subsection>[^,]+)(,|$))+")).Match(section.Value);
foreach (Capture subsection in subsections.Groups["subsection"].Captures)
{
Match subsectionparts = (new Regex(@"^(?<start>[0-9]*\.?[0-9]+)(((:(?<step>[0-9]*\.?[0-9]+):)|-)(?<end>[0-9]*\.?[0-9]+))?$")).Match(subsection.Value);
if (subsectionparts.Groups["start"].Length > 0)
{
Decimal start = Decimal.Parse(subsectionparts.Groups["start"].Value, CultureInfo.InvariantCulture);
Decimal end = start;
Decimal step = 1;
if (subsectionparts.Groups["end"].Length > 0)
{
end = Decimal.Parse(subsectionparts.Groups["end"].Value, CultureInfo.InvariantCulture);
if (subsectionparts.Groups["step"].Length > 0)
{
step = Decimal.Parse(subsectionparts.Groups["step"].Value, CultureInfo.InvariantCulture);
}
}
Decimal current = start;
while (current <= end)
{
Console.Write(String.Format("{0} ", current));
current += step;
}
}
}
Console.WriteLine();
}
Console.ReadLine();
}
}
}更新
修改为允许类似“1.5:0.2:3.6”的内容。
更新
为什么使用十进制而不是单精度或双精度?
输入中的数字是十进制数字,不能精确地用single或double表示,因为它们使用基数2表示。例如,0.1由单个值0.100000001490116119384765625表示。
Single x = 0.0F;
for (int i = 0; i < 8; i++)
{
x += 0.1F;
}
Console.WriteLine(x);此程序将在仅8次迭代后打印0.8000001。在1000次迭代之后,错误增长到0.00095,显示99.99905而不是100.0,并且在一百万次迭代之后,结果是100,958.3而不是100,000。
对于decimal没有这样的错误,因为decimal使用以10为基数的表示法,并且能够准确地表示像0.1这样的十进制数。
发布于 2009-04-01 22:21:15
下面是一些C#代码,它们可以完成您想要的操作:
var results = ParseExpression("1-7;3:.25:10;1,5,9;4-7");
private static List<List<float>> ParseExpression(string expression)
{
// "x-y" is the same as "x:1:y" so simplify the expression...
expression = expression.Replace("-", ":1:");
var results = new List<List<float>>();
foreach (var part in expression.Split(';'))
results.Add(ParseSubExpression(part));
return results;
}
private static List<float> ParseSubExpression(string part)
{
var results = new List<float>();
// If this is a set of numbers...
if (part.IndexOf(',') != -1)
// Then add each member of the set...
foreach (string a in part.Split(','))
results.AddRange(ParseSubExpression(a));
// If this is a range that needs to be computed...
else if (part.IndexOf(":") != -1)
{
// Parse out the range parameters...
var parts = part.Split(':');
var start = float.Parse(parts[0]);
var increment = float.Parse(parts[1]);
var end = float.Parse(parts[2]);
// Evaluate the range...
for (var i = start; i <= end; i += increment)
results.Add(i);
}
else
results.Add(float.Parse(part));
return results;
}https://stackoverflow.com/questions/707508
复制相似问题