[英]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("%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;
}
不, cin
和cout
與使用printf
/ scanf
並無顯着差異。 但是, endl
將調用ofstream::flush()
,它與printf("%d\\n", cost); fflush(stdout);
printf("%d\\n", 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
支持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
設置。
可以肯定的是: scanf
對std::cin.eof()
沒有影響。 因此,您的第一個代碼有一個無限循環。 第二個代碼實際上從std::cin
讀取內容,並最終使std::cin.eof()
返回true。
但是,這兩個代碼都有許多其他問題。 給定您的水平,您應該忘記scanf
; 這遠非危險而復雜。 到處使用std::cin
。 並檢查其是否成功輸入后 ,但使用效果(總是)前。 ( std::cin.eof()
不告訴你前面的輸入是否成功,也不確定下一個會成功或失敗。直到你知道,以前的輸入失敗,它的使用可能是一個錯誤。)
編寫代碼的慣用方式將涉及以下內容:
while ( std::cin >> N >> B >> H >> W ) ...
(除非沒有經驗豐富的C ++程序員會為它們使用全局變量;因此,也不要使用單個大寫字母作為名稱。)其他輸入也應以類似方式處理。
好。 我知道答案已經存在,但是我仍然看不到OP為何會觀察到的明確解釋。 因此,要從James's和Mats's的答案中獲得最大的收益,我將嘗試獲得一個很好的易於理解的解釋。
事情是第一次代碼不能運行每本身慢。 就像詹姆斯所說的那樣,有一個可能的無限循環。
為什么第一段代碼運行速度較慢? 由於無休止的循環,自動判斷會在時間限制后將其殺死。 算法和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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.