源码见 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
的方式来进行读写不要与相应的输入输出流混合使用(比如同时使用
fread
和cin
,fwrite
和cout
),fread/fwrite
是一次性从缓存中读取 / 输出数据,混合使用会导致变量数据错误等无法解决的问题支持 Linux 和 Windows 环境,如果可能,会尝试写一个
mmap
版本(Windows下通过CreateFileMapping
实现)经调试应该没有什么大的问题,如果有的话可以 Luogu 私信我,会尽快修改
请保证您传入的参数是合法的,出现任何未知的问题概不负责
功能介绍
若要使用此模板,请通过
BetterIO::betterInput in
和BetterIO::betterOutput out
来创建对象支持整形、字符、字符串、浮点数的输入,整形、字符、字符串、浮点数、
char*
的输出(在现在的竞赛环境下几乎不会用到char*
类型的输入,故舍弃)关于
bool
类型的数据,对其单独写一个输入 / 输出函数是没有任何意义的,故舍弃您可以使用
in >> x;
读入一个以上任意的一个类型的数据,使用in >> x >> y >> z >> ...;
读入任意个以上支持的数据类型对于
char
与std::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 ...;
输出任意个以上支持的数据类型(带空格)对于浮点类型的数据(
float
和double
),默认输出精度为 6 位小数,不支持更改精度绝不是我太懒了懒得写若有其它精度输出的需求请用其它输出方式
性能比较
待补 —— 25.7.26