传送门:压行版代码
特性⚡ 极优秀的性能,再也不用担心读写卡常了!🔍 一行宏定义轻松开启缓存读写,专治毒瘤出题人!🌈 全部基础数据类型的读写支持⚙️ 简洁易用的 API,具备高度可扩展性😍 支持判断 EOF,手动刷新缓冲区,设置浮点输出精度等辅助功能📕 非常详细的文档😘 Ikaleio 信仰加成😅 长达 5KB 的代码,让你的教练骂娘🤡 一个浮点快写发了五个版本才正确实现,Ikaleio 太菜了! 用前须知仅适用于 C++11 及以上,否则得到 CE 后果自负。
如果发生运行时错误并附有 [Floating point overflow] 开头的错误消息,说明你正在尝试输出一个超出 long long 范围( ±1018\pm 10^{18}±1018 )的超大浮点数。如果你确信你要输出的数没有这么离谱,说明你正在尝试输出 infinfinf 或 nannannan,请检查你的代码。(大部分的算法竞赛题目并不会要求你输出 infinfinf、nannannan,或以科学计数法输出实数。如果你确实需要,请自行修改 write(double) 函数)
IO 交互题请不要开启缓存模式,这会导致你读不到交互库的输入造成 TLE。
代码引入快读代码之前需要先 using namespace std;。
原版123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188/* Ikaleio FastIO ver. 5.0 */#define dIO_USE_BUFFER // 本地调试时将这行注释掉,提交时取消注释struct IO {#ifdef dIO_USE_BUFFER const static int BUFSIZE = 1 << 20; char ibuf[BUFSIZE], obuf[BUFSIZE], *p1, *p2, *pp; inline int getchar() { return (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, BUFSIZE, stdin), p1 == p2) ? EOF : *p1++); } inline int putchar(char x) { return ((pp - obuf == BUFSIZE && (fwrite(obuf, 1, BUFSIZE, stdout), pp = obuf)), *pp = x, pp++), x; } inline IO &flush() { return fwrite(obuf, 1, pp - obuf, stdout), pp = obuf, fflush(stdout), *this; } IO() { p1 = p2 = ibuf, pp = obuf; } ~IO() { flush(); }#else int (*getchar)() = &::getchar; int (*putchar)(int) = &::putchar; inline IO &flush() { return fflush(stdout), *this; }#endif string _sep = " "; int k = 2; template ::value || is_same::value>::type * = nullptr> inline int read(Tp &s) { int f = 1, ch = getchar(); s = 0; while (!isdigit(ch) && ch != EOF) f = (ch == '-' ? -1 : 1), ch = getchar(); if (ch == EOF) return false; while (ch == '0') ch = getchar(); while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar(); s *= f; return true; } template ::value>::type * = nullptr> inline int read(Tp &s) { int f = 1, ch = getchar(); s = 0; while (!isdigit(ch) && ch != '.' && ch != EOF) f = (ch == '-' ? -1 : 1), ch = getchar(); if (ch == EOF) return false; while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar(); if (ch == '.') { Tp eps = 0.1; ch = getchar(); while (isdigit(ch)) s = s + (ch ^ 48) * eps, ch = getchar(), eps /= 10; } s *= f; return true; } inline int read(char &ch) { ch = getchar(); while (isspace(ch) && ch != EOF) ch = getchar(); return ch != EOF; } inline int read(char *c) { char ch = getchar(), *s = c; while (isspace(ch) && ch != EOF) ch = getchar(); while (!isspace(ch) && ch != EOF) *(c++) = ch, ch = getchar(); *c = '\0'; return s != c; } inline int read(string &s) { s.clear(); char ch = getchar(); while (isspace(ch) && ch != EOF) ch = getchar(); while (!isspace(ch) && ch != EOF) s += ch, ch = getchar(); return s.size() > 0; } template inline Tp read() { Tp x; read(x); return x; } template inline int read(Tp &x, Ts &...val) { return read(x) && read(val...); } inline int getline(char *c, const char &ed = '\n') { char ch = getchar(), *s = c; while (ch != ed && ch != EOF) *(c++) = ch, ch = getchar(); *c = '\0'; return s != c; } inline int getline(string &s, const char &ed = '\n') { s.clear(); char ch = getchar(); while (ch != ed && ch != EOF) s += ch, ch = getchar(); return s.size() > 0; } template ::value || is_same::value>::type * = nullptr> inline IO &write(Tp x) { if (x < 0) putchar('-'), x = -x; static char sta[41]; int top = 0; do sta[top++] = x % 10 ^ 48, x /= 10; while (x); while (top) putchar(sta[--top]); return *this; } inline IO &write(const string &str) { for (char ch : str) putchar(ch); return *this; } inline IO &write(const char *str) { while (*str != '\0') putchar(*(str++)); return *this; } inline IO &write(char *str) { return write((const char *)str); } inline IO &write(const char &ch) { return putchar(ch), *this; } template ::value>::type * = nullptr> inline IO &write(Tp x) { if (x > 1e18 || x < -1e18) { write("[Floating point overflow]"); throw; } if (x < 0) putchar('-'), x = -x; const static long long pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 100000000000000000, 100000000000000000}; const auto &n = pow10[k]; long long whole = x; double tmp = (x - whole) * n; long long frac = tmp; double diff = tmp - frac; if (diff > 0.5) { ++frac; if (frac >= n) frac = 0, ++whole; } else if (diff == 0.5 && ((frac == 0U) || (frac & 1U))) ++frac; write(whole); if (k == 0U) { diff = x - whole; if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) ++whole; } else { putchar('.'); static char sta[21]; int count = k, top = 0; while (frac) { sta[top++] = frac % 10 ^ 48; frac /= 10, count--; } while (count--) putchar('0'); while (top) putchar(sta[--top]); } return *this; } template inline IO &write(Tp x, Ts... val) { return write(x), write(_sep), write(val...), *this; } template inline IO &writeln(Ts... val) { return write(val...), putchar('\n'), *this; } template inline IO &writesp(Ts... val) { return write(val...), putchar(' '), *this; } inline IO &writeln(void) { return putchar('\n'), *this; } inline IO &sep(const string &s = " ") { return _sep = s, *this; } inline IO &prec(const int &K = 2) { return k = K, *this; }} io; 压行版12345678#define dIO_USE_BUFFERstruct IO{#ifdef dIO_USE_BUFFERconst static int BUFSIZE=1<<20;char ibuf[BUFSIZE],obuf[BUFSIZE],*p1,*p2,*pp;inline int getchar(){return(p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,BUFSIZE,stdin),p1==p2)?EOF:*p1++);}inline int putchar(char x){return((pp-obuf==BUFSIZE&&(fwrite(obuf,1,BUFSIZE,stdout),pp=obuf)),*pp=x,pp++),x;}inline IO&flush(){return fwrite(obuf,1,pp-obuf,stdout),pp=obuf,fflush(stdout),*this;}IO(){p1=p2=ibuf,pp=obuf;}~IO(){flush();}#elseint(*getchar)()=&::getchar;int(*putchar)(int)=&::putchar;inline IO&flush(){return fflush(stdout),*this;}#endifstring _sep=" ";int k=2;template::value||is_same::value>::type* =nullptr>inline int read(Tp&s){int f=1,ch=getchar();s=0;while(!isdigit(ch)&&ch!=EOF)f=(ch=='-'?-1:1),ch=getchar();if(ch==EOF)return false;while(ch=='0')ch=getchar();while(isdigit(ch))s=s*10+(ch^48),ch=getchar();s*=f;return true;}template::value>::type* =nullptr>inline int read(Tp&s){int f=1,ch=getchar();s=0;while(!isdigit(ch)&&ch!='.'&&ch!=EOF)f=(ch=='-'?-1:1),ch=getchar();if(ch==EOF)return false;while(isdigit(ch))s=s*10+(ch^48),ch=getchar();if(ch=='.'){Tp eps=0.1;ch=getchar();while(isdigit(ch))s=s+(ch^48)*eps,ch=getchar(),eps/=10;}s*=f;return true;}inline int read(char&ch){ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();return ch!=EOF;}inline int read(char*c){char ch=getchar(),*s=c;while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)*(c++)=ch,ch=getchar();*c='\0';return s!=c;}inline int read(string&s){s.clear();char ch=getchar();while(isspace(ch)&&ch!=EOF)ch=getchar();while(!isspace(ch)&&ch!=EOF)s+=ch,ch=getchar();return s.size()>0;}templateinline Tp read(){Tp x;read(x);return x;}templateinline int read(Tp&x,Ts&...val){return read(x)&&read(val...);}inline int getline(char*c,const char&ed='\n'){char ch=getchar(),*s=c;while(ch!=ed&&ch!=EOF)*(c++)=ch,ch=getchar();*c='\0';return s!=c;}inline int getline(string&s,const char&ed='\n'){s.clear();char ch=getchar();while(ch!=ed&&ch!=EOF)s+=ch,ch=getchar();return s.size()>0;}template::value||is_same::value>::type* =nullptr>inline IO&write(Tp x){if(x<0)putchar('-'),x=-x;static char sta[41];int top=0;do sta[top++]=x%10^48,x/=10;while(x);while(top)putchar(sta[--top]);return*this;}inline IO&write(const string&str){for(char ch:str)putchar(ch);return*this;}inline IO&write(const char*str){while(*str!='\0')putchar(*(str++));return*this;}inline IO&write(char*str){return write((const char*)str);}inline IO&write(const char&ch){return putchar(ch),*this;}template::value>::type* =nullptr>inline IO&write(Tp x){if(x>1e18||x<-1e18){write("[Floating point overflow]");throw;}if(x<0)putchar('-'),x=-x;const static long long pow10[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,100000000000000000,100000000000000000};const auto&n=pow10[k];long long whole=x;double tmp=(x-whole)*n;long long frac=tmp;double diff=tmp-frac;if(diff>0.5){++frac;if(frac>=n)frac=0,++whole;}else if(diff==0.5&&((frac==0U)||(frac&1U)))++frac;write(whole);if(k==0U){diff=x-whole;if((!(diff<0.5)||(diff>0.5))&&(whole&1))++whole;}else{putchar('.');static char sta[21];int count=k,top=0;while(frac){sta[top++]=frac%10^48;frac/=10,count--;}while(count--)putchar('0');while(top)putchar(sta[--top]);}return*this;}templateinline IO&write(Tp x,Ts...val){return write(x),write(_sep),write(val...),*this;}templateinline IO&writeln(Ts...val){return write(val...),putchar('\n'),*this;}templateinline IO&writesp(Ts...val){return write(val...),putchar(' '),*this;}inline IO&writeln(void){return putchar('\n'),*this;}inline IO&sep(const string&s=" "){return _sep=s,*this;}inline IO&prec(const int&K=2){return k=K,*this;}}io;(魔改完想自己打包?将代码放入 Mivik 的 C++ 压行机 压缩后将所有的 *=nullptr 替换为 * =nullptr 即可!)
用法本模板实现了所有整数类型/所有浮点类型/字符类型/ std::string /C 风格字符串的读入/输出,且支持用户实现自定义 IO 函数。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879/* 读入 */int x = io.read(); // 返回值方式io.read(x); // 传参方式long long i64 = io.read(); // 可以通过模板指定返回值方式读入的数据类型,默认为 intio.read(i64); // 若通过传参方式读入则会自动推断类型double db;string str;io.read(x,i64,db,str); // 传参方式可以一次读入多个任意类型的数据// 传参方式下的返回值用于判断 EOF,一种常见的使用场景是具有多组数据的题目// 若成功读入,则返回 1,读到 EOF 则返回 0// 如果一次读入多个变量,只要有任何一个变量读到 EOF 则立刻终止并返回 0,全部成功读取返回 1while(io.read(x)) io.writeln(x);/* 输出 */io.write(x); // cout << x;io.writeln(x); // cout << x << endl;// cout << x << ' ' << i64 << ' ' << str << endl;io.writeln(x,i64,str);// 输出后加空格(用于输出数组等)io.writesp(x); // cout << x << " ";// prec(int) 用于设置浮点输出精度,默认保留两位小数db = 3.1415926;io.writeln(db); // 3.14io.prec(5).writeln(db); //3.14159io.prec(0).writeln(db); //3// sep(string) 用于设置输出分隔符,默认为空格// 同样的,参数只能为字符串!x = 1,i64 = 2;io.writeln(x,i64); // 1 2io.sep(",").writeln(x,i64); // 1,2// 一种常见的使用场景,用于实现格式化字符串的效果int T = io.read(), a, b;for(int t = 1; t <= T; t++){ io.read(a, b); io.sep("").writeln("Test case #",t,": ",a + b).sep();}/*输入:21 25 5输出:Test case #1: 3Test case #2: 10*/// 自定义 IO 函数// putchar -> io.putchar// getchar -> io.getchar// 你应当把这个玩意放在 struct IO{} 外面void writeString(string str){ for(char ch:str) io.putchar(ch);}writeString("Nr is very cute");// 刷新输出缓冲区 和 IO 交互题/*默认情况下,缓存模式开启后输出会被保存到缓存中,当缓存区满或程序退出时会自动将缓存内的所有东西吐到 stdout(读入同理,fread 一次从 stdin 读入一大块东西到缓存,解析干净之后再读第二块,因此你不能在缓存模式开启时使用键盘输入,也不能在交互题中使用缓存模式)。但是你可以用 io.flush() 函数手动刷新输出缓冲区,如果缓存模式开启,这会把输出缓存里所有东西吐到 stdout,否则会刷新 stdout 自带的缓存。因此在 IO 交互题中关闭缓存模式并在每次输出后调用 io.flush(),就像使用 cout/printf 一样。*/io.writeln("Hello World!").flush();// 叠叠乐// 所有函数支持链式调用io.setprec(3).writeln(114.514).setsep("").writeln("My name is Tadokoro Koji, my telephone number is ",1919810).setsep(" ").writeln("I am a 24-year-old student."); 性能LOJ #7 / 读入 3×1063\times 10^63×106个long long / 五组数据加和开启-O2优化不开启优化调试模式(getchar)288ms479ms缓存模式(fread)175ms429ms