C++/C语言通用快速输入输出(快读快写)

文章介绍了在处理大量数据时,如何使用自定义的快速读写函数(如整数、浮点数、字符串的快速输入和输出)来避免时间限制。此外,还介绍了超级快读快写模式,通过大缓冲区和高效数据传输提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在编写代码的时候、做信息题目的时候,如果输入输出的数据量比较大的话,经常一不小心就TLE(Time Limit Exceeded,即速度超限,时间超时,通俗的来说就是爆时间),这种情况下就需要scanf和printf,但是万一这两个家伙也不够用了咋办?那么就该是我们的快读快写闪亮登场啦!

普通快读

上定义

这可以使得代码更加具有可读性

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

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值