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包含即可。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。