C# Scanner类

C#没有Java那样好用的Scanner类。于是我在需要读入一堆数字的时候,我是这么写的:

1
2
3
4
//以下代码从标准输入流中读取空格分隔的两个数 a b 
string[] tempInput = Console.ReadLine().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int a = int.Parse(tempInput[0]);
int b = int.Parse(tempInput[1]);

于是做题的时候我觉得太麻烦了,就仿照Java的Scanner功能实现了一个Scanner类。然后根据需要增加了几个奇怪的函数。

以下是我的Scanner类:
(注释采用了VS的智能感知标记,这样可以在使用这些方法时从补全框中看到方法描述等信息)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
class Scanner 
{
Queue<string> buffer;

///<summary>构造函数?它不需要构造函数,构造函数也没有参数。</summary>
public Scanner(){}

///<summary>清除输入流缓冲。如果本行被读出一部分,此方法会清除这行的其他部分。</summary>
public void Ignore()
{
buffer.Clear();
}
protected void eat(string s)
{
string[] tempInput = new Regex("(\s+)").Split(s);
buffer = new Queue<string>(tempInput);
buffer.Enqueue("");
}

///<summary>
/// 从输入流中读取下一行,如果本行已经被读出一部分,此方法将直接读出其余的所有内容。
/// 此方法执行后会清空流缓冲,所以不需要再执行<c>Ignore()</c>方法。
///</summary>
public string NextLine()
{
if (buffer.Count == 0) return Console.ReadLine();
else
{
StringBuilder temp = new StringBuilder();
foreach (string k in buffer)
{
temp.Append(k);
}
buffer.Clear();
return temp.ToString();
}
}

///<summary>
/// 该方法返回一个布尔值,表示输入流是否结束。
/// 在输入流中没有其他内容时会返回false
///</summary>
public bool HasNext()
{
if (buffer==nullbuffer.Count == 0)
{
string s = Console.ReadLine();
if (s == null) return false;
eat(s);
}
return true;
}

///<summary>
/// 该方法返回下一个字符串。由任意可能的空白符号分隔。
///</summary>
public String Next()
{
HasNext();
string t = buffer.Dequeue();
buffer.Dequeue();
return t;
}

///<summary>
/// 该方法返回输入流中接下来的一个32位整数。如果接下来的字符不能表示一个整数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public int NextInt()
{
return int.Parse(Next());
}

///<summary>
/// 该方法返回输入流中接下来的一个64位整数。如果接下来的字符不能表示一个整数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public long NextLong()
{
return long.Parse(Next());
}

///<summary>
/// 该方法返回输入流中接下来的一个浮点数。如果接下来的字符不能表示一个数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public double NextDouble()
{
return double.Parse(Next());
}

///<summary>
/// 该方法将下一行按空白字符分隔,并以字符串数组形式返回。
/// 如果输入流中一行已经被读出一部分,该方法将解析并返回剩余的部分。
///</summary>
public string[] NextArray()
{
return new Regex("\s+").Split(NextLine());
}

///<summary>
/// 该方法将下一行按空白字符分隔的整数解析成32位整型数组并返回。
/// 如果输入流中一行已经被读出一部分,该方法将解析并返回剩余的部分。如果存在字符不能表示一个数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public int[] NextIntArray()
{
string[] s=NextArray();
int[] n = new int[s.Length];
for (int i = 0; i < s.Length; i++)
{
n[i] = int.Parse(s[i]);
}
return n;
}

///<summary>
/// 该方法将下一行按空白字符分隔的整数解析成64位整型数组并返回。
/// 如果输入流中一行已经被读出一部分,该方法将解析并返回剩余的部分。如果存在字符不能表示一个数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public long[] NextLongArray()
{
string[] s = NextArray();
long[] n = new long[s.Length];
for (int i = 0; i < s.Length; i++)
{
n[i] = long.Parse(s[i]);
}
return n;
}

///<summary>
/// 该方法将下一行按空白字符分隔的数字解析成浮点数组并返回。
/// 如果输入流中一行已经被读出一部分,该方法将解析并返回剩余的部分。如果存在字符不能表示一个数,将抛出FormatException异常。
///</summary>
///<exception cref="System.FormatException">字符串不能解析为数字</exception>
public double[] NextDoubleArray()
{
string[] s = NextArray();
double[] n = new double[s.Length];
for (int i = 0; i < s.Length; i++)
{
n[i] = double.Parse(s[i]);
}
return n;
}
}

以下提供了一个snippet文件,在VS中,使用(工具->)代码段管理器导入这个文件之后,可以在代码中键入Scanner按两次Tab来插入这段代码。

https://github.com/zyzsdy/acm/blob/master/CSharp/Scanner.snippet

(请注意以上文件和上面的代码有一些微小的差异,使用上面的代码需要手动插入using System.Text.RegularExpressions;一句。)

标准的用法是类似这样:

1
2
3
4
5
static Scanner cin = new Scanner(); 
static void Main(string[] args)
{
cin.NextInt();
}