好像还没见过有人总结出来在各种Online Judge(以下简称OJ)上使用C#时的读写辅助类吧
(用C#做题,读写标准输入输出流的麻烦大家懂的啊,读进来要自行切割后转化,输出,不一定都想去记C#那么特色的字符串格式化标记法)
下面给出2种输入输出类的实现(用来提交一些题目通过,但并没有特别系统的测试)
先说思路
1、读一整行string进来,然后Split()分割开,再按需Parse
2、根据需要的类型(整数还是小数还是别的字符串等),一个个字符读入,并且直接拼接到数中(不再搞成string再转化了)。
方案1的时间效率相对来讲很高(反正轻松虐爆Java就对了,和C的scanf的效率差估计10%吧),但是内存非常浪费,相当于输入文件整体导入到内存里还复制了2遍(string整串1遍,spilt开又是1遍),而且C#催促GC实在是没什么效果你懂的。
方案2的时间效率就比方案1差不少了,但是因为中间避免了string的使用,内存上就没有那么铺张浪费了
具体还请各位看具体题目情况选择。如果内存比较富裕,请选择方案1,如果时间有不小的富裕但内存卡得有点太小了,那请选择方案2
方案1:
(来源:某CF上C#的紫名用户,反正不是我自己+自行修改一些实现细节)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Numerics;
using E = System.Linq.Enumerable;
namespace CodeForces549H {
class Program {
protected IOHelper io;
public Program(string inputFile, string outputFile) {
io = new IOHelper(inputFile, outputFile, Encoding.Default);
//TODO:在这里实现你的代码
//使用方法:
//读入:io.NextInt()/io.NextDouble()
//输出:io.Write(其他对象)/io.Write(小数类型值,需要的精度)
io.Dispose();
}
static void Main(string[] args) {
Program myProgram = new Program(null, null);
}
}
class IOHelper : IDisposable {
public StreamReader reader;
public StreamWriter writer;
public IOHelper(string inputFile, string outputFile, Encoding encoding) {
if (inputFile == null)
reader = new StreamReader(Console.OpenStandardInput(), encoding);
else
reader = new StreamReader(inputFile, encoding);
if (outputFile == null)
writer = new StreamWriter(Console.OpenStandardOutput(), encoding);
else
writer = new StreamWriter(outputFile, false, encoding);
curLine = new string[] { };
curTokenIdx = 0;
}
string[] curLine;
int curTokenIdx;
char[] whiteSpaces = new char[] { ' ', '\t', '\r', '\n' };
public bool hasNext() {
if (curTokenIdx >= curLine.Length) {
//Read next line
string line = reader.ReadLine();
if (line != null)
curLine = line.Split(whiteSpaces, StringSplitOptions.RemoveEmptyEntries);
else
curLine = new string[] { };
curTokenIdx = 0;
}
return curTokenIdx < curLine.Length;
}
public string NextToken() {
return hasNext() ? curLine[curTokenIdx++] : null;
}
public int NextInt() {
return int.Parse(NextToken());
}
public double NextDouble() {
string tkn = NextToken();
return double.Parse(tkn, System.Globalization.CultureInfo.InvariantCulture);
}
public Decimal NextDecimal() {
string tkn = NextToken();
return Decimal.Parse(tkn, System.Globalization.CultureInfo.InvariantCulture);
}
public void Write(double val, int precision) {
writer.Write(val.ToString("F" + precision, System.Globalization.CultureInfo.InvariantCulture));
}
public void Write(Decimal val, int precision) {
writer.Write(val.ToString("F" + precision, System.Globalization.CultureInfo.InvariantCulture));
}
public void Write(object stringToWrite) {
writer.Write(stringToWrite);
}
public void WriteLine(Decimal val, int precision) {
writer.WriteLine(val.ToString("F" + precision, System.Globalization.CultureInfo.InvariantCulture));
}
public void WriteLine(double val, int precision) {
writer.WriteLine(val.ToString("F" + precision, System.Globalization.CultureInfo.InvariantCulture));
}
public void WriteLine(object stringToWrite) {
writer.WriteLine(stringToWrite);
}
public void Dispose() {
try {
if (reader != null) {
reader.Dispose();
}
if (writer != null) {
writer.Flush();
writer.Dispose();
}
} catch { };
}
public void Flush() {
if (writer != null) {
writer.Flush();
}
}
}
}
方案二:
基于夏天的风的C++输入挂修改(http://blog.csdn.net/shahdza/article/details/6317011)
不过C#的泛型和C++的模板类差别有点大,写法完全直接移植臣妾做不到啊555……如果有大神能做到请告诉我
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Numerics;
using E = System.Linq.Enumerable;
using InputDataType = System.Double;
namespace LowMemReader {
class Program {
static void Main(string[] args) {
//TODO:直接在这里写代码吧,或者你可以在这个类的构造函数里写也没关系
//使用方法:
//1、修改InputDataType为你想要的数据类型,比如System.Int32/System.Int64/System.Double等
//或者你直接把实现里的InputDataType换掉也没关系
//2、int x;
//readPosInt(x);
//返回false表示碰到了EOF,返回True表示读到了数
//readPosInt()读入非负整数
//readInt()读入整数(可正可负)
//readFloat()读入小数(可正可负)
//readString()并没有写,感觉如果延续这个一个个字符读进来并拼接的思路,更加费内存了
}
static bool readPosInt(out InputDataType x){
int c = Console.Read(); x = 0;
for (;c<'0'||c>'9';c = Console.Read())
if (c == -1) return false;
while ('0' <= c && c <= '9') {
x =x * 10 + c - '0';
c = Console.Read();
}
return true;
}
static bool readInt(out InputDataType x){
int c = Console.Read(); x = 0;
for (;c!='-'&&( c < '0' || c > '9'); c = Console.Read()) {
if (c == -1) return false;
}
int sgn = (c == '-') ? -1 : 1;
x = (c == '-') ? 0 : c - '0';
while ((c = Console.Read())>='0' && c <= '9') {
x = x * 10 + c - '0';
}
x *= sgn;
return true;
}
static bool readFloat(out InputDataType x) {
int c = Console.Read(); x = 0; double bit = 0.1;
for (; c != '-' &&c!='.'&& (c < '0' || c > '9'); c = Console.Read()) {
if (c == -1) return false;
}
int sgn = (c == '-') ? -1 : 1;
x = (c == '-') ? 0 : c - '0';
if (c != '.') {
while ((c = Console.Read()) >= '0' && c <= '9') {
x = x * 10 + c - '0';
}
}
if (c == ' ' || c == '\r' || c == '\n' || c == '\t') { x *= sgn; return true; }
while ((c = Console.Read()) >= '0' && c <= '9') {
x = x + (InputDataType)((c - '0') * bit); bit /= 10;
}
x *= sgn;
return true;
}
}
}