我试图完成一个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;
}
答案 0 :(得分:4)
不,cin
和cout
与使用printf
/ scanf
有显着差异。但是,endl
会调用ofstream::flush()
,这与printf("%d\n", cost); fflush(stdout);
相同,我希望如果你这样做,它也会在那里运行得更慢。
此外,将cin
与scanf
或类似内容混合会增加更多时间,因为代码必须同步&#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"
会产生显着差异!
cin
与scanf
对scanf
的不利之处有一些区别:
#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)
有一件事是肯定的:scanf
对std::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;
}