C++快读快写模板库——“QuickIO.hpp”
更新日志
2022年4月30日更新
- 新增对高精度无符号整数类型
ds::big_uint_t
的输出支持(参见我的"BigInt.hpp"
,但这时这个库尚未发布);
2022年4月8日更新
- 迎合
"TypeName.hpp"
的更新修改了所有的char
为char8_t
;
2022年4月3日更新
- 修复了一些函数在输出到文件时会错误地将部分字符输出到标准输出流的bug;
2022年3月29日更新
- 为了迎合标准库的命名规范,发布了"TypeName.hpp"类型名作出规范,并基于该库修改本库所有函数名、参数名、变量名使其符合规范;
- 将
file_stream_t
和file_stream_reference_t
的定义移至qio::fio
命名空间;
- 对
write_bin
、write_oct
、write_hex
函数新增了控制是否输出前缀的参数,修复了write_bin
、write_oct
、write_dec
、write_hex
的返回值错误问题;
2022年1月31日更新
- 将
open
、redirect
、close
的定义移至qio::fio
命名空间;
- 新增了获取文件指针位置的
getPos
函数、移动文件指针的setPos
函数,并定义了偏移文件指针起点分别有SET
、CUR
和END
,分别表示从文件开头、文件指针当前位置、文件末偏移;
- 新增了刷新文件流状态的
refresh
函数,可用于读写状态切换等;
- 新增了对无符号整数(包括
Uint8
、Uint16
、Uint32
和Uint64
)的二进制、八进制、十进制、十六进制输出支持,分别是writeBin
、writeOct
、writeDec
和writeHex
函数,其中二进制、八进制、十六进制输出结果将分别添加前缀"0b"
、"0o"
、"0x"
,十六进制输出统一使用小写字母;
- 优化了
_writeInt
和_writeUint
的写法以略微减少耗时,尽管牺牲了代码的可读性;
- 新增了对地址的输出支持;
- 祝大家除夕快乐!
2022年1月24日更新
- 规范了
CString
类型的引用(现为CStringReference
,请不要使用CString &
)和常量引用(现为ConstStringReference
,请不要使用const CString &
),避免出现奇怪的编译错误;
- 为
String
类型添加了可以限制最大长度的read
函数和readLine
函数;
- 改变了
read(CStringReference, FileStream)
、read(CStringReference, Size maxLen, FileStream)
、readLine(CStringReference, FileStream)
以及readLine(CStringReference, Size maxLen, FileStream)
函数赋予新的返回值意义:返回18446744073709551615ULL
(即EOF
,即-1
)表示end-of-file,否则表示成功读取的字符串的长度(不包括结束符'\0'
);
- 修复了与
String
类型相关的read
及readLine
函数的返回值不能清晰反映问题的问题;
- 补上了在删除模板时忘记补上的
writeLine(const String &, FileStream)
函数;
附
注意事项
- 与
CString
类型相关的read
函数、readLine
函数返回的是成功读取的字符串长度,此处'\0'
不计入长度;
- 命名为
maxSize
的参数表示的是最大内存空间大小,此处'\0'
计入大小;
- 命名为
maxLen
的参数表示的是最大字符串长度,此处'\0'
不计入长度;
2022年1月21日更新
- 修改命名空间名为
qio
,昨天忘记改了;
- 修正了一些错误;
- 为
read<T>(FileStream)
新增默认模板参数为int
类型;
- 新增文件打开函数
open
,文件关闭函数close
,文件重定向函数redirect
;
- 删除了一个没有用的函数模板
read<T, Ret>
,将其实例改写为重载的函数;
2022年1月20日更新
- 本库更名为
QuickIO.hpp
,以避免对fio
的误解;
- 将所有
get
函数更名为read
,将所有getLine
函数更名为readLine
,将所有put
函数更名为write
,将所有putLine
函数更名为writeLine
,以避免在同时using namespace std
和using namespace fio
时发生冲突;
- 暂时移除对含可变参数模板的函数,因为有可能有编译错误和意想不到的耗时,以后说不定会重新加入;
2022年1月19日更新
- 确定命名规范;
- 通过using来为一些类型创建别名,使其符合命名规范;
- 修改了一些函数名,使其符合命名规范;
- 新增可变参数模板函数,以便更加简洁地输入输出多个数据;
- 修复了一些已知的bug,包括某些函数在某些编译器下可能产生警告或编译错误的问题;
附
本库命名规范
- 命名空间采用缩写的小写字母;
- 类型名采用“大驼峰”命名格式;
- 变量名(包括参数名)采用“小驼峰”命名格式;
- 常量、宏定义及其参数完全采用大写字母,单词间用下划线“_”连接;
- 在标识符可能重复的时候,采用“匈牙利命名法”;
2022年1月16日更新
- 重构代码,通过模板实例化和函数重载等形势代替原来冗长的函数名;
- 改进了返回值含义;
2021年12月31日更新
- 修复了一堆已知的bug;
2021年12月25日更新
- 新增对C++
bool
类型输入输出的支持;
- 完善了整数输入的错误反馈和读取逻辑;
- 更新了CSDN资源区的源码;
- 完善了本更新日志格式;
2021年12月17日更新
- 新增对C++
string
类输入输出的支持;
- 完善了输入输出错误反馈(通过返回EOF);
2021年12月14日更新
- 为
get_integer<T>(std::FILE *)
新增默认模板参数为int类型;
2021年12月4日更新
- 新增对C文件流(
std::FILE *
的快速读写对象支持;
- 新增对C字符串(
char *
及const char *
)的快速读写支持;
2021年11月30日
- 正式发布到CSDN;
模板库源码
#ifndef QUICKIO_HPP
#define QUICKIO_HPP
#include "TypeName.hpp"
#include <cstdio>
#include <string>
#include "BigInt.hpp"
namespace qio
{
namespace fio
{
using file_stream_t = std::FILE *;
using file_stream_reference_t = std::FILE *;
using mode_t = uint32_t;
using offset_t = int32_t;
using origin_t = uint8_t;
}
namespace fio
{
static const mode_t APP = 0b1;
static const mode_t BIN = 0b10;
static const mode_t IN = 0b100;
static const mode_t OUT = 0b1000;
static const origin_t SET = 0, CUR = 1, END = 2;
inline file_stream_t open(const_c_string_t file,
mode_t m_mode = IN | OUT)
{
char8_t s_mode[] = {
((m_mode & APP) ? 'a' : ((m_mode & IN) ? 'r' : 'w')),
((m_mode & BIN) ? 'b' : 't'),
((((m_mode & IN) && (m_mode & OUT)) ||
((m_mode & IN) && (m_mode & OUT)))
? '+'
: '\0'),
'\0'};
return (std::fopen(file, s_mode));
}
inline bool open(file_stream_t &file_stream, const_c_string_t file,
mode_t m_mode = IN | OUT)
{
return (file_stream = open(file, m_mode));
}
inline bool redirect(file_stream_reference_t file_stream,
const_c_string_t s_new_file,
mode_t m_mode = IN | OUT)
{
char8_t s_mode[] = {
((m_mode & APP) ? 'a' : ((m_mode & IN) ? 'r' : 'w')),
((m_mode & BIN) ? 'b' : 't'),
((((m_mode & IN) && (m_mode & OUT)) ||
((m_mode & IN) && (m_mode & OUT)))
? '+'
: '\0'),
'\0'};
return std::freopen(s_new_file, s_mode, file_stream);
}
inline offset_t get_pos(file_stream_t file_stream)
{
return std::ftell(file_stream);
}
inline bool set_pos(file_stream_t file_stream, offset_t pos, origin_t origin = SEEK_SET)
{
return !std::fseek(file_stream, pos, origin);
}
inline bool refresh(file_stream_t file_stream)
{
return !std::fseek(file_stream, 0L, SEEK_CUR);
}
inline bool close(file_stream_t &file_stream)
{
bool ret = !std::fclose(file_stream);
file_stream = nullptr;
return ret;
}
}
template <typename T = int>
T read(fio::file_stream_t file = stdin);
inline void skip_blank(fio::file_stream_t file = stdin)
{
char8_t ch = std::fgetc(file);
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
{
ch = std::fgetc(file);
}
std::ungetc(ch, file);
}
template <typename int_t>
inline int _read_int(int_t &x, fio::file_stream_t file = stdin)
{
using std::fgetc;
x = 0;
int ret = 0, nega = 0;
char8_t ch = fgetc(file);
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
{
ch = fgetc(file);
}
if (~ch)
{
if (ch == '-')
{
nega = true;
ch = fgetc(file);
}
else if (ch == '+')
{
ch = fgetc(file);
}
}
else
{
ret = EOF;
goto _RET;
}
while ('0' <= ch && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ '0');
ret = 1;
ch = fgetc(file);
}
if (nega)
{
x = -x;
}
_RET:
std::ungetc(ch, file);