C++/C语言通用快速输入输出(快读快写)
lixuean0408 2024-07-27 12:05:02 阅读 57
前言
在编写代码的时候、做信息题目的时候,如果输入输出的数据量比较大的话,经常一不小心就TLE(Time Limit Exceeded,即速度超限,时间超时,通俗的来说就是爆时间),这种情况下就需要scanf和printf,但是万一这两个家伙也不够用了咋办?那么就该是我们的快读快写闪亮登场啦!
普通快读
上定义
这可以使得代码更加具有可读性
<code>#define f_Getchar() getchar()
#define f_Putchar(ch) putchar(ch)
f_Getchar() 即快速(fast)获取字符
f_Putchar() 即快速输出字符
至于为什么要这样做后面再说
整数输入
int快读
inline void inputI(int* i){
char nagative = 0 ;
char ch = '\0' ;
(*i) = 0 ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
(*i) = ((*i) << 1) + ((*i) << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)(*i) = -(*i) ;
return ;
}
简单介绍原理:首先获取字符,如果是非数字,则一直获取直到获取到数字,如果有负号则标记。接着获取一段连续的数字字符,转换为数字。
long long快读
inline void inputLL(long long* i){
char nagative = 0 ;
char ch = '\0' ;
(*i) = 0 ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
(*i) = ((*i) << 1) + ((*i) << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)(*i) = -(*i) ;
return ;
}
原理同上
long long快读(无参数,返回数值)
inline long long inget(){
long long i = 0 ;
char nagative = 0 ;
char ch = '\0' ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
i = (i << 1) + (i << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)i = -i ;
return i ;
}
原理同上
浮点数输入
float 快读
inline void inputF(float* t){
(*t) = inget() ;
float t2 = 0.0F,p = 0.1 ;
char ch = f_Getchar() ;
while(ch > 47 && ch < 58 && p > 1e-6F){
t2 += (ch ^ '0') * p ;
p *= 0.1 ;
ch = f_Getchar() ;
}
*t += t2 ;
return ;
}
原理:获取两端分开的连续数字字符,前面一段作为整数部分,后面一段作为小数部分。
double 快读
inline void inputD(double* t){
*t = inget() ;
double t2 = 0.0,p = 0.1 ;
char ch = f_Getchar() ;
while(ch > 47 && ch < 58 && p > 1e-13){
t2 += (ch ^ '0') * p ;
p *= 0.1 ;
ch = f_Getchar() ;
}
*t += t2 ;
return ;
}
原理同上
字符串输入
字符串正常输入
inline void inputS(char* s){
char ch = f_Getchar() ;
while(ch == ' ' || ch == '\n')ch = f_Getchar() ;
while(ch != ' ' && ch != '\n')*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
e......这就不用多说了吧
字符串确定最大长度的输入
inline void inputSs(char* s,unsigned long long len){
char ch = f_Getchar() ;
while(ch == ' ' || ch == '\n')ch = f_Getchar() ;
while((len --) && (ch != ' ' && ch != '\n'))*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
输入一整行的字符串
inline void inputL(char* s){
char ch = f_Getchar() ;
while(ch == '\n')ch = f_Getchar() ;
while(ch != '\n')*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
字符输入
字符输入(输入可显示字符)
inline void inputC(char* ch){
(*ch) = f_Getchar() ;
while((*ch) == ' ' || (*ch) == '\n')(*ch) = f_Getchar() ;
return ;
}
获取字符(任意字符均可)
f_Getchar(&ch) ;
普通快写
整数快写
int快写
void outputI(int i){
if(i < 0)f_Putchar('-'),i = -i ;
if(i > 9)outputI(i / 10) ;
f_Putchar((i % 10) | 0x30) ;
return ;
}
long long快写
void outputLL(long long i){
if(i < 0)f_Putchar('-'),i = -i ;
if(i > 9)outputLL(i / 10) ;
f_Putchar((i % 10) | 0x30) ;
return ;
}
字符串快写
正常字符串快写
inline void outputS(const char* s){
while(*s)f_Putchar(*s ++) ;
return ;
}
输出一行字符串
inline void outputSL(const char* s){
while(*s && *s != '\n')f_Putchar(*s ++) ;
return ;
}
浮点数快写
double快写
#define outputD(x) printf("%g",x)
对于输出,printf是我目前发现的最快的方法
double快写(可控小数位数)
inline void outputDl(double x,unsigned char len) { printf("%.*lf",len,x) ; return ; }
float快写
#define outputF(x) printf("%g",x)
float快写(可控小数位数)
inline void outputFl(float x,unsigned char len) { printf("%.*f",len,x) ; return ; }
字符快写
#define outputC(ch) f_Putchar(ch)
超级快读快写
ok,现在也是该揭开悬念了,前面define的定义就是为了下面的内容!!!让我们把前面的定义替换成如下代码:
#ifdef IO_SUPER_FAST
#ifndef IO_BUFFER_SIZE
#define IO_BUFFER_SIZE (0xfffff)
#endif
static char i_buffer[IO_BUFFER_SIZE],*f = i_buffer,*b = i_buffer ;
char f_Getchar(){
if(f == b){
b = i_buffer + fread(i_buffer,1,IO_BUFFER_SIZE,stdin) ;
f = i_buffer ;
if(f == b)return EOF ;
}
return *(f ++) ;
}
static char o_buffer[IO_BUFFER_SIZE],*t = o_buffer ;
void f_Putchar(char x){
if((t - o_buffer) >= IO_BUFFER_SIZE){
fwrite(o_buffer,1,IO_BUFFER_SIZE,stdout) ;
t = o_buffer ;
}
*(t ++) = x ;
return ;
}
void put_buffer(){
fwrite(o_buffer,t - o_buffer,1,stdout) ;
t = o_buffer ;
return ;
}
#else
#define f_Getchar() getchar()
#define f_Putchar(ch) putchar(ch)
#define put_buffer()
#endif
当当当!!!这就是超级快读快写!
现在让我们一起解读
IO_SUPER_FAST
这是一个宏定义,如果在这段代码之前定义了IO_SUPER_FAST,#ifdef IO_SUPER_FAST判断成立,则会执行下面的两个函数、静态变量定义,即开启了超级快读快写
IO_BUFFER_SIZE
这定义了超级快读快写的缓冲区大小,如果没有定义过则定义为0xfffff,即十进制的1,048,575,这既不会使得程序内存超限,也可以提供一个很快的速度。(一般题目都会给出128MB即以上的内存,而这里只占用了不到一MB的内存,除非是程序压得很死,但是也可以手动更改,在代码前面定义就好了)
i_buffer
这是输入的缓冲区,大小由IO_BUFFER_SIZE决定
f
这是一个指针,指向当前正在使用的到的缓冲区的位置
b
这是一个指针,指向缓冲区内有效数据的结尾
f_Getchar
判断当前是否有有效的数据,如果有则返回,并使f增加一,否则重新读取数据,并重新判断,如若读取数据失败则返回EOF(文件末尾标志)
o_buffer
这是输出的缓冲区,大小由IO_BUFFER_SIZE决定
t
这是一个指针,指向当前输出缓冲区内,有效数据的末尾
f_Putchar
将一个字符输出到输出缓冲区内,如果输出缓冲区已满则将所有数据输出,并清空缓冲区。
put_buffer
将所有缓冲区内所有有效数据输出,并清空缓冲区。(一般放在完成输出时的地方,或者程序的末尾)
全代码
注意:
如果想要开启超级快读快写模式,只要在文件的最前面加上宏定义
#define IO_SUPER_FAST
语句即可。如果觉得还不够快,还可以在文件头部加上:
#define IO_BUFFER_SIZE (0xfffffff)
一定一定要在程序的最后(return 0之前)使用put_buffer()函数!
要不然就会有一些内容不被输出出来!
在控制台输入的时候!输入完一段之后它是不会成功获取内容、并且运行下面的代码输出的!
这不是卡住了!而是需要按下Ctrl+Z键手动结束输入才行!
要不然它就会卡住!直到缓冲区满为止!!!
#include <stdio.h>
//#define IO_SUPER_FAST
/*
超级快读快写的开关在这!!!!
如果没有注释掉上面那一条语句,
就会开启超级快读快写模式!
如果觉得还不够快,还可以在文件头部加上:
#define IO_BUFFER_SIZE (0xfffffff)
*/
#ifdef IO_SUPER_FAST
#ifndef IO_BUFFER_SIZE
#define IO_BUFFER_SIZE (0xfffff)
#endif
static char i_buffer[IO_BUFFER_SIZE],*f = i_buffer,*b = i_buffer ;
char f_Getchar(){
if(f == b){
b = i_buffer + fread(i_buffer,1,IO_BUFFER_SIZE,stdin) ;
f = i_buffer ;
if(f == b)return EOF ;
}
return *(f ++) ;
}
static char o_buffer[IO_BUFFER_SIZE],*t = o_buffer ;
void f_Putchar(char x){
if((t - o_buffer) >= IO_BUFFER_SIZE){
fwrite(o_buffer,1,IO_BUFFER_SIZE,stdout) ;
t = o_buffer ;
}
*(t ++) = x ;
return ;
}
void put_buffer(){
fwrite(o_buffer,t - o_buffer,1,stdout) ;
t = o_buffer ;
return ;
}
#else
#define f_Getchar() getchar()
#define f_Putchar(ch) putchar(ch)
#define put_buffer()
#endif
inline long long inget(){
long long i = 0 ;
char nagative = 0 ;
char ch = '\0' ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
i = (i << 1) + (i << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)i = -i ;
return i ;
}
inline void inputLL(long long* i){
char nagative = 0 ;
char ch = '\0' ;
(*i) = 0 ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
(*i) = ((*i) << 1) + ((*i) << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)(*i) = -(*i) ;
return ;
}
inline void inputI(int* i){
char nagative = 0 ;
char ch = '\0' ;
(*i) = 0 ;
while((ch = f_Getchar()) < 48 || ch > 57)if(ch == '-')nagative = 1 ;
while(ch > 47 && ch < 58){
(*i) = ((*i) << 1) + ((*i) << 3) + (ch & 0xCF) ;
ch = f_Getchar() ;
}
if(nagative)(*i) = -(*i) ;
return ;
}
inline void inputF(float* t){
(*t) = inget() ;
float t2 = 0.0F,p = 0.1 ;
char ch = f_Getchar() ;
while(ch > 47 && ch < 58 && p > 1e-13){
t2 += (ch ^ '0') * p ;
p *= 0.1 ;
ch = f_Getchar() ;
}
*t += t2 ;
return ;
}
inline void inputD(double* t){
*t = inget() ;
double t2 = 0.0,p = 0.1 ;
char ch = f_Getchar() ;
while(ch > 47 && ch < 58 && p > 1e-13){
t2 += (ch ^ '0') * p ;
p *= 0.1 ;
ch = f_Getchar() ;
}
*t += t2 ;
return ;
}
inline void inputS(char* s){
char ch = f_Getchar() ;
while(ch == ' ' || ch == '\n')ch = f_Getchar() ;
while(ch != ' ' && ch != '\n')*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
inline void inputSs(char* s,unsigned long long len){
char ch = f_Getchar() ;
while(ch == ' ' || ch == '\n')ch = f_Getchar() ;
while((len --) && (ch != ' ' && ch != '\n'))*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
inline void inputL(char* s){
char ch = f_Getchar() ;
while(ch == '\n')ch = f_Getchar() ;
while(ch != '\n')*s = ch,++ s,ch = f_Getchar() ;
*s = '\0' ;
return ;
}
inline void inputC(char* ch){
(*ch) = f_Getchar() ;
while((*ch) == ' ' || (*ch) == '\n')(*ch) = f_Getchar() ;
return ;
}
void outputLL(long long i){
if(i < 0)f_Putchar('-'),i = -i ;
if(i > 9)outputLL(i / 10) ;
f_Putchar((i % 10) | 0x30) ;
return ;
}
void outputI(int i){
if(i < 0)f_Putchar('-'),i = -i ;
if(i > 9)outputI(i / 10) ;
f_Putchar((i % 10) | 0x30) ;
return ;
}
inline void outputS(const char* s){
while(*s)f_Putchar(*s ++) ;
return ;
}
inline void outputSL(const char* s){
while(*s && *s != '\n')f_Putchar(*s ++) ;
return ;
}
#define outputC(ch) f_Putchar(ch)
#define outputD(x) printf("%g",x)
inline void outputDl(double x,unsigned char len) { printf("%.*lf",len,x) ; return ; }
#define outputF(x) printf("%g",x)
inline void outputFl(float x,unsigned char len) { printf("%.*f",len,x) ; return ; }
结尾
全部代码可以封装成一个文件,要用的时候直接include包含即可。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。