好像还没见过有人总结出来在各种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; } } }