zoukankan      html  css  js  c++  java
  • C++读入神器——文操快读(oj也可以用)

    当某天,本蒟蒻沉迷于卡常的时候:

    图

    我……

    突然,YYKdalao说:用文操快读啊!

    然后

    图2

    喔~目瞪口呆

    不多说,上源码:

    本来用的读入方式:

    inline void Read( int &x ) {
    	x = 0; char ch = getchar();
    	for( ; ch < '0' || ch > '9'; ch = getchar() );
    	for( ; ch >= '0' && ch <= '9'; ch = getchar() )
    		x = x * 10 + ch - '0';
    	return;
    }
    

    文操快读:

    const int MAX_SIZE = 1 << 15;
    char *l, *r, buf[ MAX_SIZE ];
    inline int gc() {
    	if( l == r )
    		if( l == ( r = ( l = buf ) + fread( buf, 1, MAX_SIZE, stdin ) ) ) return -1;
    	return *l++; 
    }
    inline void Read( int &x ) {
    	char c = gc();
    	for(; c < 48 || c > 57; c = gc() );
    	for( x = 0; c > 47 && c < 58; c = gc() )
    		x = ( x << 3 ) + ( x << 1 ) + ( c ^ 48 );
    	return;
    }
    

    以下为2019.11.04 update
    实际上,输出也同样可以使用 fwrite 加速。并且 fwrite 可以直接输出到屏幕上。(这与 fread 需要重定向stdin,或者用命令行里的< 不同。)更为方便的是,可以使用 sprintf 或者 vsnprintf 来方便地将一些内容写入字符数组中。下面贴上模板:

    说明:你可以像 printf 和 scanf 一样使用里面的 Printf 和 Scanf 函数。但是 Scanf 函数的实现有些愚蠢(只能用%d表示一个int,并且不能有其他东西)。所以如果没有特殊需求的话最好用 Read 读取单个整数。你也可以自己写适合的 Read 函数。 输出流最后不一定需要 FlushOutput ,因为在销毁结构体的时候会执行这一步(这并不意味着你不需要fclose)。你可以通过更改 MAX_OUTPUT_ONCE 的值来更改 Printf 函数单次最大输出量。(如果超过了也许仍然能够正确输出,但那样会有一些不必要的错误。)
    v0.1.0 之后提供了真正像scanf那样的读入方法。你可以用三句话实现(但是这仅仅是方便读入,并没有加速这个过程(fread带来的优化被memcpy抵消了QwQ)):

    IO.Ready(); //预留足够的空间(至少为 MAX_INPUT_ONCE,不过你也需要保证一次读入的长度不超过 MAX_INPUT_ONCE)
    sscanf(IO.It(), "...%n", ..., &IO.C); //读入
    IO.Forward(); //刷新流,不然下一次读入会读重复的内容
    

    注意: 结构体创建之后,就会从输入流中预读入。默认输入输出流是 stdin 和 stdout。所以不使用 FastIO 的时候请不要进行声明。

    /*====================    Header : FastIO    ====================*/
    /*====================     version 0.1.1     ====================*/
    /*==================== Programed By chy-2003 ====================*/
    /*
     * Logs : 
     * version 0.1.1 : Fix bugs when flush input buffers
     * version 0.1.0 : Add new ways to read
     *     new    function char *It();
     *     new    function void Ready();
     *     new    function void Forward();
     *     You can read any thing like : but to make sure read less than MAX_INPUT_ONCE charactors once.
     *         IO.Ready(); 
     *         sscanf(IO.It(), "...%n", ..., &IO.C); 
     *         IO.Forward();
     * version 0.0.1 : Update
     *     change function int GetChar();    : private -> public
     *     new    function int UnGetC();     : public (unget the last char. Return value 0:success; -1:fail)
     *     change function void Read(int &); : rewrite with UnGetC. will run UnGetC() after reading an integer
     * version 0.0.0 : Creat
     *     function 'Read' and 'Scanf' will return the number of values get successfully.
     *     function 'Read' : 
     *         int Read(int&);
     *     funtion 'Scanf' : 
     *         Warning : This funtion works in a stupid way
     *         int Scanf(const char *, ...);
     *         supports : all(just like printf);
     *
     *     funtion 'Printf' : 
     *         Warning : Output may be cut off if the length longer than ((1 << 9) - 1), or you can set MAX_OUTPUT_ONCE equals to MAX_OUTPUT_BUFFER_SIZE
     *         void Printf(const char *, ...);
     *         supports : all(just like printf)
     */
    
    #ifndef _MY_FASTIO_
    #define _MY_FASTIO_
    
    #include <cstdio>
    #include <cstring>
    #include <stdarg.h>
    
    #define MAX_INPUT_BUFFER_SIZE (1 << 15)
    #define MAX_OUTPUT_BUFFER_SIZE (1 << 15)
    #define MAX_INPUT_ONCE (1 << 9)
    #define MAX_OUTPUT_ONCE (1 << 9)
    //notice : I check the buffer BEFORE every option.
    //notice : please make sure MAX_INPUT_BUFFER_SIZE > 2 * MAX_INPUT_ONCE
    
    struct FastIO {
    //private:
        char *InputBufferLeft, *InputBufferRight, InputBuffer[MAX_INPUT_BUFFER_SIZE + 1];//The last position is for ''
        char OutputBuffer[MAX_OUTPUT_BUFFER_SIZE + 1]; // The last position is for ''
        int OutputBufferUsed;
        FILE *InputStream, *OutputStream;
        char cTemp;
        short iTemp;
        bool CanGet;
    
        inline void ClearInputBuffer();
        inline int GetFromInputStream();
        inline void SetInputBufferToLeft();
        inline bool EndOfFile();
    
    public:
        int C;
        //Basic
        FastIO(FILE *_InputStream = stdin, FILE *_OutputStream = stdout);
        ~FastIO();
    
        //Input
        inline int GetChar();
        inline int UnGetC();
        inline int Read(int &x);
        inline int Scanf(const char *Format, ...);
        inline void Ready();
        inline void Forward();
        inline char *It();
    
        //Output
        inline void FlushOutput();
        inline void Printf(const char *Format, ...);
    };
    
    FastIO::FastIO(FILE *_InputStream, FILE *_OutputStream) :
        InputStream(_InputStream), OutputStream(_OutputStream),
        InputBufferLeft(InputBuffer), InputBufferRight(InputBuffer), OutputBufferUsed(0) {
            InputBuffer[MAX_INPUT_BUFFER_SIZE] = OutputBuffer[MAX_OUTPUT_BUFFER_SIZE] = '';
            CanGet = true;
            GetFromInputStream();
            return;
        }
    
    FastIO::~FastIO() {
        FlushOutput();
        return;
    }
    
    inline void FastIO::ClearInputBuffer() {
        InputBufferLeft = InputBufferRight = InputBuffer;
        return;
    }
    
    inline int FastIO::GetFromInputStream() {
        if (!CanGet) return 1;
        char *Last = InputBufferRight;
        InputBufferRight = InputBufferRight + fread(InputBufferRight, 1, InputBuffer + MAX_INPUT_BUFFER_SIZE - InputBufferRight, InputStream);
        if (InputBufferRight == Last) CanGet = false;
        return !CanGet;
    }
    
    inline void FastIO::SetInputBufferToLeft() {
        memcpy(InputBuffer, InputBufferLeft, InputBufferRight - InputBufferLeft);
        InputBufferRight = InputBuffer + (InputBufferRight- InputBufferLeft);
        InputBufferLeft = InputBuffer;
        return;
    }
    
    inline int FastIO::GetChar() {
        if (InputBufferLeft == InputBufferRight) {
            ClearInputBuffer();
            if (GetFromInputStream()) return -1;
        }
        return *InputBufferLeft++;
    }
    
    inline int FastIO::Read(int &x) {
        cTemp = GetChar();
        iTemp = 1;
        for(; cTemp < 48 || cTemp > 57; cTemp = GetChar())
            if (cTemp == -1)
                return 0;
            else
                if (cTemp == '-')
                    iTemp = -1;
        for(x = 0; cTemp > 47 && cTemp < 58; cTemp = GetChar())
            x = (x << 3) + (x << 1) + (cTemp ^ 48);
        UnGetC();
        x *= iTemp;
        return 1;
    }
    
    inline int FastIO::Scanf(const char *Format, ...) {
        int CountRead, Len, i, j;
        CountRead = 0;
        Len = strlen(Format);
        va_list ap;
        va_start(ap, Format);
        for (i = 0, j; i < Len; i = j + 1) {
            j = i;
            while (j + 1 < Len && Format[j + 1] != '%') ++j;
            if (j - i == 1 && Format[j] == 'd') {
                int *x;
                x = va_arg(ap, int *);
                Read(*x);
                ++CountRead;
            }
        }
        va_end(ap);
        return CountRead;
    }
    
    inline void FastIO::Ready() {
        if (InputBufferRight - InputBufferLeft < MAX_INPUT_ONCE && CanGet && (InputBufferRight - InputBuffer == MAX_INPUT_BUFFER_SIZE)) {
            SetInputBufferToLeft();
            GetFromInputStream();
        }
        return;
    }
    
    inline char *FastIO::It() {
        return InputBufferLeft;
    }
    
    inline void FastIO::Forward() {
        InputBufferLeft = InputBufferLeft + C;
        return;
    }
    
    inline void FastIO::FlushOutput() {
        if (OutputBufferUsed)
            fwrite(OutputBuffer, 1, OutputBufferUsed, OutputStream);
        OutputBufferUsed = 0;
        return;
    }
    
    inline void FastIO::Printf(const char *Format, ...) {
        if (OutputBufferUsed >= MAX_OUTPUT_BUFFER_SIZE - MAX_OUTPUT_ONCE)
            FlushOutput();
        va_list ap;
        va_start(ap, Format);
        OutputBufferUsed += vsnprintf(OutputBuffer + OutputBufferUsed, MAX_OUTPUT_BUFFER_SIZE - OutputBufferUsed, Format, ap);
        va_end(ap);
        return;
    }
    
    inline int FastIO::UnGetC() {
        if (InputBuffer != InputBufferLeft) {
            --InputBufferLeft;
            return 0;
        }
        return -1;
    }
    
    #undef MAX_INPUT_BUFFER_SIZE
    #undef MAX_OUTPUT_BUFFER_SIZE
    #undef MAX_INPUT_ONCE
    #undef MAX_OUTPUT_ONCE
    
    #endif
    
    
    /*==================== End of Header : FastIO ====================*/
    
  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/chy-2003/p/9916869.html
Copyright © 2011-2022 走看看