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 '\0'
    char OutputBuffer[MAX_OUTPUT_BUFFER_SIZE + 1]; // The last position is for '\0'
    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] = '\0';
        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 ====================*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM