为什么在这种情况下"printf scanf"比"cout cin"慢?
Why do "printf scanf" is slower than "cout cin" in this case?
我试图完成一个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("%dn",cost);
else{
printf("stay homen");
}
}
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;
}
否,cin
和cout
与使用printf
/scanf
没有显著差异。然而,endl
将调用ofstream::flush()
,这与printf("%dn", cost); fflush(stdout);
是一样的,我希望如果你这样做,它在那里也会运行得更慢。
此外,将cin
与scanf
或类似内容混合使用会增加更多时间,因为代码必须始终"同步"两个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
大约10%的差异有利于printf
。然而,当我运行任何基准测试时,我的系统都会有很大的变化,所以应该谨慎对待。请注意,使用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
设置。
scanf
对std::cin.eof()
没有影响。因此,您的第一个代码有一个无休止的循环。第二个代码实际上从std::cin
中读取了一些内容,并且最终导致CCD_ 25返回true。
然而,这两种代码都存在许多其他问题。鉴于您级别,您应该忘记scanf
;太危险了复杂。处处使用std::cin
。检查一下在输入之后,但在使用结果之前成功(总是)。(std::cin.eof()
是否不告诉您上一次输入成功,下一次输入是否成功或失败在您知道以前的输入失败之前使用可能是一个错误。)
编写代码的惯用方法会涉及到一些内容类似:
while ( std::cin >> N >> B >> H >> W ) ...
(除了没有一个经验丰富的C++程序员会使用全局变量;也没有一笔资本字母作为名称。)应处理其他输入类似地。
好的。我知道答案就在那里,但我仍然没有看到一个明确的解释,为什么OP会观察到。所以,为了充分利用詹姆斯和马茨的答案,我会努力得到一个简单易懂的解释。
问题是第一个代码本身运行速度并不是较慢的。正如詹姆斯所说,可能存在一个无限循环。
为什么第一个代码运行得较慢因为有一个无休止的循环,自动判断会在时间限制后杀死它。算法和I/O并不慢。
考虑到时差:0.022秒到1秒。由于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 homen");
}
}
return 0;
}
- 为什么 printf 在 C++ 中的执行速度比 cout 快?另外scanf比cin慢,为什么?
- 使用 CIN COUT 显示垃圾值的文件对象?
- 当我们声明 cin 为 int 并从 cin 中获取输入并在 cout 中打印 cin 时会发生什么?
- 为什么我的 cout 一次执行,尽管 cin 应该在两者之间读取?
- 两个 cin / cout 语句合并为一个
- 防止 cin、cout、cerr 被实例化
- 无法让我了解 cin.get 和 cout 在这里的工作方式
- 使用 std::endl 与 "n" 当 cin 和 cout 被解绑时
- CIN 和 COUT 如何在以下程序中工作
- 使用自定义宏来简化 cin 和 cout 语句等内容被认为是更好还是更差
- 简单的cin cout代码由"build and run"运行,但从bin/debug/x开始工作.exe
- 通过 cin/cout 的协议单元测试 - 如何阻止流以等待内容?
- 为什么 CIN / COUT 比 scanf/printf 慢
- 从printf-scanf转换为cin-cout时出现问题
- cin/cout 使用什么技术/模式允许例如 cout << x << y
- 为什么我不能将 cin/cout 放在一个函数中并从 main() 调用该函数
- 交替使用cin/cout很慢
- 关于 cin/cout 过载的简单问题 4.
- cin / cout being skipped
- c++, cin, cout, threads和sync_with_stdio的输出损坏