[转载]整数读入优化 C++

一、背景

这是某道题目的状态:

我的代码:

大牛的代码:

我瞬间萌币了!

我有这么慢?Are you kidding me?

点进去一看:

[cpp] view plain copy print?
void Read(int & p)  
{  
    p=0;  
    int flag=1;  
    char c=getchar();  
    while(c<'0' or c>'9')   
    {  
        if(c=='-') flag=-1;  
        c=getchar();  
    }  
    while(c>='0' and c<='9')  
        p=p*10+(c-'0'),c=getchar();  
    p*=flag;  
}  

这是什么?

原来,这是读入优化啊!

二、读入优化的原理与实现

C语言和C++库里有很多种输入方式,我们最常用的是scanf和cin。除此之外,还有:

char c[]; gets(c);//读入一行字符串,但是需要注意的是,它只会在遇到’\n’后停止,不会因为超过c的内存上限而停止。所以容易溢出。

char c[]; fgets(c,len,stdin);//读入一行字符串。和gets不同的是,它如果读入了len-1个字符,就会停止。

char c=getchar();//就像scanf一样,只读入一个字符,并返回这个字符,需要#include头文件。与scanf不同的是,它没有缓冲,也就意味着它会更快。

char c=getch();//直接读入一个字符,而不会回显。也就是说,你读入了一个字符,它不会在界面里显现而直接读入getch,getch也会直接返回这个字符。比如说你写了一个程序小游戏,你肯定不希望看到wasdwasdwasd满天飞,所以就用getch。需要#include

[cpp] view plain copy print?
int Read()  
{  
    int p=0;  
    char c=getchar();  
    while(c<'0' or c>'9') c=getchar();  
    while(c>='0' and c<='9')  
        p=p*10+(c-'0'),c=getchar();  
    return p;  
}  

调用p=Read();即可。

其实(c>=’0’ and c<=’9’)也是一个函数isdigit(c),如果c是代表数字的字符,就返回1,否则返回0,需要#include头文件。

所以也可以写成:


[cpp] view plain copy print?
void Read(int & p)  
{  
    p=0;  
    char c=getchar();  
    while(!isdigit(c)) c=getchar();  
    while(isdigit(c))  
        p=p*10+(c-'0'),c=getchar();  
}  

的形式。

三、整数读入优化的特殊处理——负数

对于一个负数,读入优化只会读入数字,负号并不会被读入。

所以需要读入负数,要特判这个字符是不是负号,如果是,那么这个值要改成负数。

这就是文章开头的代码:

[cpp] view plain copy print?
void Read(int & p)  
{  
    p=0;  
    int flag=1;  
    char c=getchar();  
    while(c<'0' or c>'9')   
    {  
        if(c=='-') flag=-1;  
        c=getchar();  
    }  
    while(c>='0' and c<='9')  
        p=p*10+(c-'0'),c=getchar();  
    p*=flag;  
}  

但是,这个代码有一个弊端。所有的‘-’都必须代表负号。如果是减号,比如4-3,就会读错。

四、验证读入优化的效率

用freopen生成五百万个数的文本,并分别用scanf,cin和读入优化读入。

文本生成:



[cpp] view plain copy print?
#include  
int main()  
{  
    freopen("test.txt","w",stdout);  
    const int N=5000000;  
    for(int i=1;i<=N;i++)  
        printf("%d  ",N);  
}  

验证程序:

[cpp] view plain copy print?
#include  
#include  
#include  
#include  
#include  
#include  
using namespace std;  
void s(int & p)  
{  
    scanf("%d",&p);  
}  
void c(int & p)  
{  
    cin>>p;  
}  
void Read(int & p)  
{  
    p=0;  
    char c=getchar();  
    while(!isdigit(c)) c=getchar();  
    while(isdigit(c))  
        p=p*10+(c-'0'),c=getchar();  
}  
double t1,t2;  
int main()  
{  
    freopen("test.txt","r",stdin);  
    int p;  

    t1=clock();  
    //for(int i=1;i<=5000000;i++) s(p);  
    //for(int i=1;i<=5000000;i++) c(p);  
    for(int i=1;i<=5000000;i++) Read(p);  
    t2=clock();  

    //printf("scanf took %.2lf second",(t2-t1)/1000);  
    //printf("cin took %.2lf second",(t2-t1)/1000);  
    printf("Read took %.2lf second",(t2-t1)/1000);  
}  

结果:

scanf took 0.85 second

cin took 14.63 second

Read took 0.35 second

所以说读入优化还是很快的。

你可能感兴趣的:(C语言)