【C# for OJ/ACM做题】适用于各种OJ的2种C#输入输出辅助类(IOHelper)

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


你可能感兴趣的:(C#,输入输出,ACMICPC)