在Java中,我可以向扫描器传递一个字符串,然后我可以做一些方便的事情,例如scanner.hasNext()
或scanner.nextInt()
,scanner.nextDouble()
等。
这允许一些非常干净的代码来解析包含数字行的字符串。
这是如何在C#中完成的?
如果你有一个字符串说:
"0 0 1 22 39 0 0 1 2 33 33"
在Java中,我会将其传递给扫描仪并执行
while(scanner.hasNext())
myArray[i++] = scanner.nextInt();
或类似的东西。什么是C#'这样做的方法?
答案 0 :(得分:23)
我将把它作为一个单独的答案添加,因为它与我已经给出的答案截然不同。以下是您可以开始创建自己的Scanner类的方法:
class Scanner : System.IO.StringReader
{
string currentWord;
public Scanner(string source) : base(source)
{
readNextWord();
}
private void readNextWord()
{
System.Text.StringBuilder sb = new StringBuilder();
char nextChar;
int next;
do
{
next = this.Read();
if (next < 0)
break;
nextChar = (char)next;
if (char.IsWhiteSpace(nextChar))
break;
sb.Append(nextChar);
} while (true);
while((this.Peek() >= 0) && (char.IsWhiteSpace((char)this.Peek())))
this.Read();
if (sb.Length > 0)
currentWord = sb.ToString();
else
currentWord = null;
}
public bool hasNextInt()
{
if (currentWord == null)
return false;
int dummy;
return int.TryParse(currentWord, out dummy);
}
public int nextInt()
{
try
{
return int.Parse(currentWord);
}
finally
{
readNextWord();
}
}
public bool hasNextDouble()
{
if (currentWord == null)
return false;
double dummy;
return double.TryParse(currentWord, out dummy);
}
public double nextDouble()
{
try
{
return double.Parse(currentWord);
}
finally
{
readNextWord();
}
}
public bool hasNext()
{
return currentWord != null;
}
}
答案 1 :(得分:4)
使用已经给出的部分答案,我创建了一个StringReader
,可以提取Enum
以及实现IConvertible
的任何数据类型。
<强>用法强>
using(var reader = new PacketReader("1 23 ErrorOk StringValue 15.22")
{
var index = reader.ReadNext<int>();
var count = reader.ReadNext<int>();
var result = reader.ReadNext<ErrorEnum>();
var data = reader.ReadNext<string>();
var responseTime = reader.ReadNext<double>();
}
<强>实施强>
public class PacketReader : StringReader
{
public PacketReader(string s)
: base(s)
{
}
public T ReadNext<T>() where T : IConvertible
{
var sb = new StringBuilder();
do
{
var current = Read();
if (current < 0)
break;
sb.Append((char)current);
var next = (char)Peek();
if (char.IsWhiteSpace(next))
break;
} while (true);
var value = sb.ToString();
var type = typeof(T);
if (type.IsEnum)
return (T)Enum.Parse(type, value);
return (T)((IConvertible)value).ToType(typeof(T), System.Globalization.CultureInfo.CurrentCulture);
}
}
答案 2 :(得分:3)
虽然这不是完全相同的基本概念,但您正在寻找的是这个lambda表达式:
string foo = "0 0 1 22 39 0 0 1 2 33 33";
int[] data = foo.Split(' ').Select(p => int.Parse(p)).ToArray();
这样做的第一个Split
string
,使用空格作为分隔符。然后Select
函数允许您为数组中的给定成员指定别名(在本例中我称之为“p
”),然后对该成员执行操作以给出最终结果结果。然后ToArray()
调用将这个抽象的可枚举类转换为具体的数组。
因此,最后,这会拆分string
,然后将每个元素转换为int
,并使用结果值填充int[]
。
答案 3 :(得分:3)
据我所知,框架中没有用于执行此操作的内置类。你必须自己动手。
这不会太难。一个不错的C#版本可能会实现IEnumerable,所以你可以说:
var scanner = new Scanner<int>(yourString);
foreach(int n in scanner)
; // your code
答案 4 :(得分:2)
为了尽可能接近您的语法,如果您只对一种类型感兴趣(示例中为“int”),这将起作用:
static void Main(string[] args)
{
if (args.Length == 0) { args = new string[] { "3", "43", "6" }; }
IEnumerator<int> scanner = (from arg in args select int.Parse(arg)).GetEnumerator();
while (scanner.MoveNext())
{
Console.Write("{0} ", scanner.Current);
}
}
这是一个更加疯狂的版本,允许您访问字符串的IConvertible实现支持的任何类型:
static void Main(string[] args)
{
if (args.Length == 0) { args = new string[] { "3", "43", "6" }; }
var scanner = args.Select<string, Func<Type, Object>>((string s) => {
return (Type t) =>
((IConvertible)s).ToType(t, System.Globalization.CultureInfo.InvariantCulture);
}).GetEnumerator();
while (scanner.MoveNext())
{
Console.Write("{0} ", scanner.Current(typeof(int)));
}
}
只需将其他类型传递给while循环中的“typeof”运算符即可选择类型。
这两者都需要最新版本的C#和.NET框架。
答案 5 :(得分:1)
您可以使用linq完成此操作:
string text = "0 0 1 22 39 0 0 1 2 33 33";
text.Where(i => char.IsNumber(i)).Write(); // do somthing usefull here...
答案 6 :(得分:0)
我会以两种方式中的一种方式执行此操作,具体取决于1)您是否使用支持LINQ的最新.NET框架和2)您知道值是有效整数。这是一个演示两者的函数:
int[] ParseIntArray(string input, bool validateRequired)
{
if (validateRequired)
{
string[] split = input.Split();
List<int> result = new List<int>(split.Length);
int parsed;
for (int inputIdx = 0; inputIdx < split.Length; inputIdx++)
{
if (int.TryParse(split[inputIdx], out parsed))
result.Add(parsed);
}
return result.ToArray();
}
else
return (from i in input.Split()
select int.Parse(i)).ToArray();
}
根据其他答案中的评论,我认为您需要验证。阅读完这些评论之后,我认为最接近的是int.TryParse和double.TryParse,它是hasNextInt和nextInt(或hasNextDouble和nextDouble的组合)的组合。