在这种情况下,为什么“printf scanf”比“cout cin”慢?

时间:2013-08-28 14:01:30

标签: c++

我试图完成一个UVa问题:11559 - 活动策划。但是,我发现了让我困惑的事情。我使用printf和scanf作为IO编写了一个代码,但我在判断中得到了“超出时间限制”。我用cin和cout改变了我的代码,然后我得到了“接受”。 cin或cout不比scanf和printf慢?这是我的代码。

“stdio.h”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W)){
        int cost = inf;
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d\n",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;

}

“iostream”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(!cin.eof()){
        int cost = inf;
        cin >> N >> B >> H >> W;
        if(cin.eof()) break;
        for(int i = 0; i < H; i++){
            int P, k ;
            cin >> P;
            for(int j = 0; j < W; j++){
                cin >> k;
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) cout << cost << endl;
        else{
            cout << "stay home" << endl;
        }
    }
    return 0;
}

3 个答案:

答案 0 :(得分:4)

不,cincout与使用printf / scanf有显着差异。但是,endl会调用ofstream::flush(),这与printf("%d\n", cost); fflush(stdout);相同,我希望如果你这样做,它也会在那里运行得更慢。

此外,将cinscanf或类似内容混合会增加更多时间,因为代码必须同步&#34;同步&#34;两个I / O流始终。我建议你将scanf输入重写为:

while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){
    int cost = inf;
    // remove scanf and cin.eof() line here
    ...
}

证明我的观点(至少是输出):

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            printf("%d", i);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            cout << i << "\n";
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}

当没有参数(argc == 1)运行并且使用参数(argc == 2运行)时,此输出为:

$ ./a.out > foo.txt
Time: 1672894
$ ./a.out 1 > foo.txt
Time: 1513620

赞成printf的差异大约为10%。但是,当我运行任何基准测试时,我的系统中存在相当多的变化,因此应该采用一点点盐。请注意,使用endl代替"/n"会产生显着差异!

cinscanfscanf的不利之处有一些区别:

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            scanf("%d", &tmp);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            cin >> tmp;
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}


$ ./a.out < foo.txt
Time: 1990454
$ ./a.out 1 < foo.txt
Time: 4804226

正如您所看到的,scanf慢了近2.5倍......但是,我看到其他情况并没有那么大的差异。我不完全确定为什么会有这么大的差异。

总而言之,存在差异,但我相信James Kanze的答案更接近于解释发生了什么 - 代码根本无法完成,因为cin.eof()未被scanf设置。

答案 1 :(得分:1)

有一件事是肯定的:scanfstd::cin.eof()没有影响。 所以你的第一个代码有一个无限循环。第二个代码 实际上从std::cin读取内容,并最终会 导致std::cin.eof()返回true。

然而,这两个代码都有许多其他问题。鉴于你的 等级,你应该忘记scanf;这很危险 而且复杂。到处使用std::cin。并检查它 在输入之后成功,但在使用结果之前 (总是)。 (std::cin.eof() 告诉您是否< 先前的输入成功,下一次输入是否成功或 失败。在你知道之前的输入失败之前,它就是 使用可能是一个错误。)

编写代码的惯用方法会涉及到一些问题 像:

while ( std::cin >> N >> B >> H >> W ) ...

(除了没有经验丰富的C ++程序员会使用全局 他们的变量;就此而言,也不是单一的资本 字母作为名称。)应处理其他输入 与此类似。

答案 2 :(得分:0)

确定。我知道答案就在那里,但我仍然没有看到清楚和干净的解释为什么OP观察。所以,从詹姆斯和玛特的答案中获得最大的好处,我会试着找到一个很容易理解的解释。

问题是第一个代码运行速度不慢 per-se 。正如詹姆斯所说,有一个可能的无限循环。

为什么第一个代码似乎运行得慢?由于无限循环,自动判断在时间限制之后将其杀死。算法和I / O并不慢。

鉴于你的时差:0.022s到1s。由于c和c ++之间的I / O实现差异,没有办法(实际上)会有这么大的差异。

我没有输入示例。但我的赌注是,如果你从Mats的回答中得到建议,并使用以下代码,第一个代码将正常工作并给出相同的时间结果。

#include <stdio.h>
#include <stdlib.h>
#define inf 500000000
int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){ //Mats' suggestion
        int cost = inf;
        //if(cin.eof()) break; //not needed `while` checks it
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;
}