LOADING

加载过慢请开启缓存 浏览器默认开启

『奇淫巧技之最强 C++ 封装快读快写模板』

源码见 Github

或直接在以下代码块中直接复制:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <new>
#include <type_traits>

namespace BetterIO {
    namespace ExtraType {
        inline bool isDigit(const char &ch) {
            return '0' <= ch && ch <= '9';
        }
        inline bool isLetter(const char &ch) {
            return 'A' <= ch && ch <= 'Z'
                || 'a' <= ch && ch <= 'z';
        }
        inline bool isChar(const char &ch) {
            return isDigit(ch) || isLetter(ch);
        }
        inline bool isVaild(const char &ch) {
            return '!' <= ch && ch <= '~';
        }
    }
    using std::string, std::is_same_v;
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 1 << 16
#endif
    class betterInput {
        FILE *stream;
        char *buffer, *iter;
        int buffer_size, volume;
        void input() {
            volume = fread(buffer, 1, buffer_size, stream);
            iter = buffer;
        }
        inline void getChar(void) {
            if(iter - buffer == volume) input();
            else ++iter;
        }
    public:
        betterInput(FILE *stream = stdin) {
            this -> stream = stream;
            buffer_size = BUFFER_SIZE;
            buffer = new char [buffer_size];
            iter = buffer;
            volume = 0;
        }
        template <typename _Tp> betterInput& operator >> (_Tp &var) {
            if constexpr(is_same_v<_Tp, char> || is_same_v<_Tp, string>) return inputCharType(var);
            else {
                static bool neg = false;
                while(!ExtraType::isDigit(*iter)) {
                    neg ^= *iter == '-';
                    getChar();
                }
                var = 0;
                if constexpr(is_same_v<_Tp, float> || is_same_v<_Tp, double>) return inputFloat(var, neg);
                else {
                    while(ExtraType::isDigit(*iter)) {
                        var = (var << 1) + (var << 3) + (*iter ^ '0');
                        getChar();
                    }
                    if(neg) var = ~var + 1;
                }
            }
            return *this;
        }
        template <typename _Tp> betterInput& inputCharType(_Tp &var) {
            while(!ExtraType::isVaild(*iter)) getChar();
            if constexpr(is_same_v<_Tp, char>) var = *iter, getChar();
            else {
                var.clear();
                while(ExtraType::isVaild(*iter)) {
                    var.push_back(*iter);
                    getChar();
                }
            }
            return *this;
        }
        template <typename _Tp> betterInput& inputFloat(_Tp &var, const bool &neg) {
            while(ExtraType::isDigit(*iter)) {
                var = var * 10 + (*iter ^ '0');
                getChar();
            }
            if(*iter == '.') {
                getChar(); 
                _Tp dec = 0.1;
                while(ExtraType::isDigit(*iter)) {
                    var += dec * (*iter ^ '0');
                    dec /= 10;
                    getChar();
                }
            } else getChar();
            if(neg) var = -var;
            return *this;
        }
        ~betterInput() { delete[] buffer; }
    };
    class betterOutput {
        FILE *stream;
        char *buffer;
        int buffer_size, volume;
        inline void putChar(const char &ch) {
            if(buffer_size == volume) flush();
            buffer[volume++] = ch;
        }
    public:
        betterOutput(FILE *stream = stdout) {
            this -> stream = stream;
            buffer_size = BUFFER_SIZE;
            buffer = new char [buffer_size];
            volume = 0;
        }
        void flush(void) {
            fwrite(buffer, 1, volume, stream);
            volume = 0;
        }
        template <typename _Tp> betterOutput& operator << (_Tp var) {
            if(var < 0) putChar('-'), var = -var;
            if constexpr(is_same_v<_Tp, float> || is_same_v<_Tp, double>) return outputFloat(var);
            else {
                static char digit[25];
                static short cur = 0;
                do digit[cur++] = static_cast<char> (var % 10 + '0'); while(var /= 10);
                while(cur) putChar(digit[--cur]);
            }
            return *this;
        }
        betterOutput& operator << (const char &var) {
            putChar(var);
            return *this;
        }
        betterOutput& operator << (const char *var) {
            while(*var) putChar(*var++);
            return *this;
        }
        betterOutput& operator << (const string &var) {
            for(auto cur: var) putChar(cur);
            return *this;
        }
        template <typename _Tp> betterOutput& outputFloat(_Tp &var) {
            const string str_var = std::to_string(var);
            for(auto cur: str_var) putChar(cur);
            return *this;
        }
        ~betterOutput() { flush(); delete[] buffer; }
    };
#undef BUFFER_SIZE
}

signed main() {

    return 0;
}

模板简介

为了更好地食用模板,请务必仔细阅读以下内容

  • 完整版代码长度4.7k,不考虑写成头文件(毕竟竞赛没有多文件)。或者也可以选择 Lite 版 模板

  • 使用 fread/fwrite 函数实现。默认缓冲区大小为 $2^{16}$,也可以通过更改模板中 BUFFER_SIZE 的值来更改缓冲区大小(不建议超过 $2^{23}$)

  • 重载了 >><<,可以像使用 cin/cout 的方式来进行读写

  • 不要与相应的输入输出流混合使用(比如同时使用 freadcinfwritecout),fread/fwrite是一次性从缓存中读取 / 输出数据,混合使用会导致变量数据错误等无法解决的问题

    支持 Linux 和 Windows 环境,如果可能会尝试写一个 mmap 版本(Windows下通过 CreateFileMapping 实现)

  • 经调试应该没有什么大的问题,如果有的话可以 Luogu 私信我,会尽快修改

    请保证您传入的参数是合法的,出现任何未知的问题概不负责

功能介绍

  • 若要使用此模板,请通过 BetterIO::betterInput inBetterIO::betterOutput out 来创建对象

  • 支持整形、字符、字符串、浮点数的输入,整形、字符、字符串、浮点数、char* 的输出(在现在的竞赛环境下几乎不会用到 char* 类型的输入,故舍弃)

    关于 bool 类型的数据,对其单独写一个输入 / 输出函数是没有任何意义的,故舍弃

  • 您可以使用 in >> x; 读入一个以上任意的一个类型的数据,使用 in >> x >> y >> z >> ...; 读入任意个以上支持的数据类型

  • 对于 charstd::string 类型的输入,默认有效字符的范围为 ACSII 码表中的 33 至 126

    您可以通过更改以上输入类型的判定条件输入特定字符范围的数据

    ...
    template <typename _Tp> betterInput& inputCharType(_Tp &var) {
        while(!ExtraType::isVaild(*iter)) getChar(); // 更改 ExtraType::isVaild 函数以输入特定字符范围数据
            if constexpr(is_same_v<_Tp, char>) var = *iter, getChar();
    ...
    
  • 命令行输入完数据后,使用 ctrl + z 刷新缓冲读入数据。文件流无需注意此项

  • 您可以使用 out << x; 输出一个以上任意的一个类型的数据,使用 out << x << ' ' << y << ' ' << z ...; 输出任意个以上支持的数据类型(带空格)

  • 对于浮点类型的数据(floatdouble),默认输出精度为 6 位小数,不支持更改精度绝不是我太懒了懒得写

    若有其它精度输出的需求请用其它输出方式

性能比较

待补 —— 25.7.26