UOJ Logo AnzheWang的博客

博客

基于fread,fwrite的cin,cout

2017-08-09 22:01:59 By AnzheWang

第一篇uoj博客~

相信很多同学都喜欢cin,cout的方便,却因为cin,cout的常数太大而常常弃之不用,所以经常会写上输入输出优化,很多同学甚至嫌输入输出优化麻烦直接用scanf,printf了

所以我的这个模板强行把常数小的fread,fwrite套在了结构体里,并给结构体赋予了>>,<<运算符,常数方便两不误!(当然是指刷题)

因为为了代码的整齐度之类的(写的比较全,强迫症),并没有去搞什么奇技淫巧的优化了,所以常数可能相对于大神来说,会偏大???

特别地,我的浮点数输入对于1e-6,2.1e-3这种能够接受,为什么呢?因为一次模拟赛,出题人卡输入的常数,结果又是用cout造的数据,什么意思?你们可以尝试一下

std::cout<<0.0000001<<std::endl;

然后我那天一直以为被卡精度,结果(mmp)。。。。于是我在板子上加了这个。

总的来说有以下优点:

1.使用方便(对于喜爱文件读入读出的同学更开心了,喜爱控制台的可就不那么好接受了--)//什么你觉得断点输出很麻烦?SF会查不出来?试试cerr吧!

2.速度客观 略快于一般的getchar的读入优化(常数大师的除外,常数大师可能不用getchar吧?),远快于std的cin,cout

3.输入输出较为齐全,适用于绝大部分题目

4.支持多文件输入,你可以直接用FILE *fp = fopen 打开一个新的文件然后io::filein fin(fp); fin.in()就好啦!是不是很方便呢

有以下缺点:

1.double,float的输出不够优美,我是用sprintf的,因为单单的写四舍五入乘法除法浮点数的效率已经和printf差不了多少了,所以直接上了sprintf,速度还是灰常快滴(你同样也可以用cout.bit(x)来将其改为保留小数点后x位)

2.不支持long double的输出(感觉也很少用。。。其实是我不是很会写...0.0)

希望各路大神不喜勿喷,喜欢的同学可以拿去尝试一下,有什么意见和bug可以在评论区告诉我,谢谢。

更新: 2017.8.18 内容:将文件内置于两个结构体中,并通过一个宏变量LOCAL来决定是否打开文件,从本地交题到OJ上请删除或者注释掉#define LOCAL

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <complex>
#include <bitset>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define rep(i, a, b) for(rg int (i) = (a), __omega = (b); (i) <= __omega; ++(i))
#define down(i, a, b) for(rg int (i) = (a), __omega = (b); (i) >= __omega; --(i))
#define run(x) for(rg int __omega = (x); __omega; --__omega)

#define cmax(i, j) ((i) < (j) ? (i) = (j) : (i))
#define cmin(i, j) ((i) > (j) ? (i) = (j) : (i))
#define dmax(i, j) ((j) < (i) ? (i) : (j))
#define dmin(i, j) ((i) < (j) ? (i) : (j))
#define dabs(i) ((i) > 0 ? (i) : -(i))
#define cabs(i) ((i) < 0 ? (i) = -(i) : (i))
#define dsqr(i) ((i)*(i))

#define rg register
#define int64 long long
#define uint unsigned int
#define uint64 unsigned long long

namespace io {

    const int IO_size = 1<<25;

    struct filein {

        char B[IO_size], *S;
        FILE *file;

        inline void operator = (rg FILE *f) { file = f; }
        filein(FILE *f = NULL) { S = B; if(f) *this = stdin; }
        void setfile(const char *filename) { file = fopen(filename, "r"); in(); }
        void closefile() { fclose(file); }
        inline void in() { fread(B, 1, IO_size, file); }

        template<typename type>
        inline type read_int() {
            rg type aa; rg char cc;
            for(; (*S < 48 || *S > 57) && *S != '-'; S++);
            cc = *S == '-' ? (S++, 0) : 1, aa = *S++-48;
            for(; *S >= 48 && *S <= 57; S++) aa = (aa<<1)+(aa<<3)+*S-48;
            cc ? : aa = -aa; return aa;
        }

        template<typename type>
        inline type read_float() {
            rg type aa, bb = 0, gg = 1; rg char cc;
            rg char ch;
            for(; (*S < 48 || *S > 57) && *S != '-'; S++);
            cc = *S == '-' ? (S++, 0) : 1, aa = *S++-48;
            for(; *S >= 48 && *S <= 57; S++) aa=aa*10+*S-48;
            if(*S == 'e') {
                bb += aa; aa = 0;
                S++; int k = read_int<int>();
                if(k < 0) while(k) bb /= 10, k++;
                else while(k) bb *= 10, k--;
            }
            if(*S == '.') {
                for(S++; *S >= 48 && *S <= 57; S++)
                    bb += (*S-48)*(gg /= 10);
                if(*S == 'e') {
                    bb += aa; aa = 0;
                    S++; int k = read_int<int>();
                    if(k < 0) while(k) bb /= 10, k++;
                    else while(k) bb *= 10, k--;
                }
            }
            aa += bb, cc ? : aa = -aa;
            return aa;
        }

        inline char getc() { return *S++; }
        inline void gets(rg char *s) {
            for(; *S == ' ' || *S == '\n'; S++);
            for(; *S != ' ' && *S != '\n' && ~*S && *S; *s++ = *S++);
            *s++ = '\0';
        }

    } cin(stdin);

    struct fileout {

        char U[IO_size], *O, bit_float[20], bit_double[20];
        FILE *file;

        inline void operator = (rg FILE *f) { file = f; }
        fileout(FILE *f = NULL) { O = U; bit(6); if(f) *this = f;}
        void setfile(const char *filename) { file = fopen(filename, "w"); }
        void closefile() { out(); fclose(file); }
        inline void out() { fwrite(U, 1, O-U, file), O = U; }

        template<typename type>
        inline void write(rg type a) {
            static char stack[50];
            rg int i = 0;
            if(!a) { *O++ = 48; return; }
            a < 0 ? a = -a, *O++ = '-' : 1;
            for(; a; a /= 10) stack[++i] = a%10;
            for(; i; *O++ = stack[i--]+48);
        }

        inline void bit_f(rg int len) {
            rg char *it = bit_float;
            *it++ = '%', *it++ = '.';
            if(len > 9) *it++ = len/10+48, *it++ = len%10+48;
            else *it++ = len+48;
            *it++ = 'f';
            *it++ = '\0';
        }

        inline void bit_d(rg int len) {
            rg char *it = bit_double;
            *it++ = '%', *it++ = '.';
            if(len > 9) *it++ = len/10+48, *it++ = len%10+48;
            else *it++ = len+48;
            *it++ = 'l', *it++ = 'f';
            *it++ = '\0';
        }

        inline void bit(rg int len) { bit_f(len), bit_d(len); }
        inline void write_float(rg float a) { O += sprintf(O, bit_float, a); }
        inline void write_double(rg double a) { O += sprintf(O, bit_double, a); }
        inline void putc(rg char c) { *O++ = c; }
        inline void puts(rg const char *s) { for(; *s; s++) *O++ = *s; }

    } cout(stdout);

    inline filein& operator >> (rg filein& _in, rg int& x) { x = _in.read_int<int>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg int64& x) { x = _in.read_int<int64>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg uint& x) { x = _in.read_int<uint>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg uint64& x) { x = _in.read_int<uint64>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg char& ch) { ch = _in.getc(); return _in; }
    inline filein& operator >> (rg filein& _in, rg char *s) { _in.gets(s); return _in; }
    inline filein& operator >> (rg filein& _in, rg float& x) { x = _in.read_float<float>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg double& x) { x = _in.read_float<double>(); return _in; }
    inline filein& operator >> (rg filein& _in, rg long double& x) { x = _in.read_float<long double>(); return _in; }

    inline fileout& operator << (rg fileout& _out, rg int x) { _out.write<int>(x); return _out; }
    inline fileout& operator << (rg fileout& _out, rg int64 x) { _out.write<int64>(x); return _out; }
    inline fileout& operator << (rg fileout& _out, rg uint x) { _out.write<uint>(x); return _out; }
    inline fileout& operator << (rg fileout& _out, rg uint64 x) { _out.write<uint64>(x); return _out; }
    inline fileout& operator << (rg fileout& _out, rg char ch) { _out.putc(ch); return _out; }
    inline fileout& operator << (rg fileout& _out, rg const char *s) { _out.puts(s); return _out; }
    inline fileout& operator << (rg fileout& _out, rg float x) { _out.write_float(x); return _out; }
    inline fileout& operator << (rg fileout& _out, rg double x) { _out.write_double(x); return _out; }

    const char endl = '\n';
}

namespace work_space {

    #define LOCAL

    using namespace io;

    void main() {
        rg int a, b;
        cin >> a >> b;
        cout << a+b << endl;
    }

}

#ifdef LOCAL
#define setfile(s) io::cin.setfile(s".in"), io::cout.setfile(s".out")
#define closefile() io::cin.closefile(), io::cout.closefile()
#else
#define setfile(s) io::cin.in()
#define closefile() io::cout.out()
#endif
#define filename "data"

int main() {
    setfile(filename);
    work_space::main();
    closefile();
    return 0;
}

评论

mcfxmcfx
重载逗号多好(滑稽)
zhouyi
WangVanZhe
zcysky
前排膜mcfx
riteme
赞一个,但是cin/cout不慢啊...而且输出是可以设置精度的啊QAQ
TRCYX
能不能考虑workspace里面的东西写进in的构造函数和out的析构函数。。或者在setfile里调用cin.in(),closefile里调用cout.out()之类的 用户可以少写点东西

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。