C# I/O 助手类

来源:互联网 发布:常州市软件行业协会 编辑:程序博客网 时间:2024/05/16 09:20

在使用 C# 语言解 ACM 题的时候,如果能够有一个 ReadInt32 方法直接从标准输入读取整数比较方便的。下面就是一个 I/O 助手类 IOHelper:

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
namespace Skyiv
{
  using System;
  using System.IO;
  using System.Text;
 
  sealed class IOHelper : IDisposable
  {
    static readonly Encoding Encoding = Encoding.ASCII; // or UTF8 ?
    static readonly byte[] EOLS = Encoding.GetBytes(Environment.NewLine);
    static readonly byte[] BLANKS = { 9, 10, 13, 32 }; // tab,lf,cr,space
    static readonly byte EOF = 0; // assume '\0' not in input file
     
    byte[] buf = new byte[32]; // for Write(int n)
    byte[] buffer = new byte[64 * 1024];
    int current = 0;
    int count = 0;
    BinaryReader reader;
    BinaryWriter writer;
     
    public IOHelper()
      this(Console.OpenStandardInput(), Console.OpenStandardOutput())
    {}
     
    public IOHelper(Stream reader, Stream writer)
    {
      this.reader = new BinaryReader(reader);
      this.writer = new BinaryWriter(writer);
    }
     
    byte ReadByte()
    {
      if (current >= count)
      {
        count = reader.Read(buffer, current = 0, buffer.Length);
        if (count == 0) return EOF;
      }
      return buffer[current++];
    }
     
    public static byte[] GetBytes(string str)
    {
      return Encoding.GetBytes(str);
    }
     
    public int ReadInt32()
    {
      var n = 0;
      var ok = false;
      for (byte b; (b = ReadByte()) != EOF; )
      {
        if (Array.IndexOf(BLANKS, b) >= 0)
          if (ok) break;
          else continue;
        n = n * 10 + (b - '0');
        ok = true;
      }
      return n;
    }
     
    public int ReadLine(byte[] buffer)
    {
      var n = 0;
      while (n < buffer.Length)
      {
        var b = ReadByte();
        if (b == EOLS[0])
        {
          if (EOLS.Length == 2 && ReadByte() != EOLS[1])
            throw new InvalidDataException("Invalid EOL");
          break;
        }
        buffer[n++] = b;
      }
      return n;
    }
 
    public void Write(int n)
    {
      if (n == 0) { writer.Write((byte)'0'); return; }
      var i = buf.Length;
      for (; n > 0; n /= 10) buf[--i] = (byte)((n % 10) + '0');
      Write(buf, i, buf.Length - i);
    }
     
    public void Write(byte[] buffer, int index, int count)
    {
      writer.Write(buffer, index, count);
    }
     
    public void Write(string str)
    {
      var buffer = Encoding.GetBytes(str);
      writer.Write(buffer, 0, buffer.Length);
    }
     
    public void WriteSpace()
    {
      writer.Write(BLANKS, 3, 1);
    }
     
    public void WriteLine()
    {
      writer.Write(EOLS, 0, EOLS.Length);
    }
     
    public void Dispose()
    {
      if (reader != null) reader.Close();
      if (writer != null) writer.Close();
    }
  }
}

此外,IOHelper 类还提供以下方法用于处理字符串:

  • public int ReadLine(byte[] buffer)
  • public void Write(byte[] buffer, int index, int count)

类似于 C/C++ 语言,这两个方法仅仅把字符串当作字节数组处理,使用 ASCII 码。而不是象 C# 语言中字符串是使用 Unicode 进行编码。

下面是一个使用示例,题目来源请参见“I-Keyboard”这篇随笔。

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
namespace Skyiv.Ben.Acm
{
  using System;
 
  // http://www.spoj.pl/problems/IKEYB/
  sealed class Ikeyb
  {
    const int MAX = 90;
     
    static int[,] cost = new int[MAX + 1, MAX + 1];
    static int[,] price = new int[MAX + 1, MAX + 1];
    static int[,] index = new int[MAX + 1, MAX + 1];
    static int[] F = new int[MAX];
    static byte[] keys = new byte[MAX];
    static byte[] letters = new byte[MAX];
    static byte[] message1 = IOHelper.GetBytes("Keypad #");
    static byte[] message2 = IOHelper.GetBytes(": ");
     
    static IOHelper helper;
 
    static void Main()
    {
      using (helper = new IOHelper())
      {
        var runner = new Ikeyb();
        var T = helper.ReadInt32();
        for (var n = 1; n <= T; n++) runner.Run(n);
      }
    }
 
    void Run(int n)
    {
      var K = helper.ReadInt32();
      var L = helper.ReadInt32();
      helper.ReadLine(keys);
      helper.ReadLine(letters);
      for (var i = 0; i < L; i++) F[i] = helper.ReadInt32();
      Initialize(K, L);
      Compute(K, L);
      helper.Write(message1, 0, message1.Length);
      helper.Write(n);
      helper.Write(message2, 0, 1);
      helper.WriteLine();
      Output(K, L);
      helper.WriteLine();
    }
     
    void Initialize(int K, int L)
    {
      for (var i = 0; i <= K; i++)
        for (var j = 1; j <= L; j++)
          price[i, j] = int.MaxValue / 2;
      for (var i = 1; i <= L; i++)
        for (var j = i; j <= L; j++)
          cost[i, j] = cost[i, j - 1] + (j - i + 1) * F[j - 1];
    }
     
    void Compute(int K, int L)
    {
      for (var i = 1; i <= K; i++)
        for (var j = i; j <= L; j++)
          for (var n = 1; n <= j - i + 1; n++)
          {
            var sum = price[i - 1, j - n] + cost[j - n + 1, j];
            if (sum <= price[i, j])
            {
              price[i, j] = sum;
              index[i, j] = n;
            }
          }
    }
 
    void Output(int K, int L)
    {
      if (K == 0) return;
      var n = index[K--, L];
      Output(K, L - n);
      helper.Write(keys, K, 1);
      helper.Write(message2, 0, message2.Length);
      helper.Write(letters, L - n, n);
      helper.WriteLine();
    }
  }
}

如果给出以下输入:

12 5*#ABCDE1024327682147483647987654321

上述程序将产生以下输出:

Keypad #1:*: ABCD#: E

注意上述输出其实是有问题的,正确的输出应该分为 AB 和 CDE 两组。但是程序本身是没有问题的,而是输入数据有问题。因为原来的题目中限定各个字母出现的频率不能超过 100000。

0 0
原创粉丝点击