Re: [問題] acm100...time exceed..
※ 引述《tvbic (輕薄的機掰)》之銘言:
: while(true)
: {
: cin>>a>>b;
: cout<<a<<" "<<b<<" "<<test(a,b)<<endl;
: }
: =============================================
: while(cin>>a>>b)
: {
: cout<<a<<" "<<b<<" "<<test(a,b)<<endl;
: }
: =========================================================
: 請問一下...這二種寫法有什麼不一樣嗎..??
: 第二個可以過...可是第一個過不了...顯示time limit exceeded
推文有解釋過的,就不再說了。
將 cin 的讀入放到 while 的條件測試中,是 C++
極常用的 idiom. 一方面達到讀值的作用(side effect)
一方面 cin >> a >> b 這整個 expression 的結果就
是傳回被讀值後的 cin, cin 本身無所謂 true 或 false,
可是 while 條件需要 true 或 false, 於是程式就要去
找 cin 所屬的 class (也就是 istream)是否有定義任何
conversion operator, 結果很高興的發現了它有重載(overload)
operator void*
operator void* 若是傳回 null (0) 就代表 false, 其他一切
non-null pointer 值就是 true. 在 operator void* 這個
overloaded function 的定義中,其實它是測試 cin 的狀態是否為
fail(),若成員函式 fail()為真,則operator void* 傳回 null
pointer (0), 那麼 while 的測試就失敗,迴圈結束;否則 operator void*
就傳回某個 non-null pointer 表示為 true, 那麼 while就測
試成功了,迴圈繼續。
那麼這個 fail() 何時會為真呢?情況有數種,包括讀到檔尾(eof),
或是讀到不合預期的東東,像是我們這裡要讀 int a, 和 int b,
也就是 cin >> a >> b; 結果卻讀到了英文字母,那就會 fail(),
甚至另外也會檢查 istream buffer 是否壞掉了,那也會 fail().
另外 istream 也有重載 operator ! 其結果和上述顛倒。fail()
時傳回真, !fail() 傳回假。
另外補充,有很多人會寫
while ( ! cin.eof() ) {
cin >> a >> b;
// 或是
getline(cin, str);
// ...
// 處理 a,b 或 str
}
這種寫法通常是錯誤的,因為 eof() 幾乎都是發生在迴圈內。
好比說資料共十筆,那麼迴圈跑十次,都沒問題,甚至第十一次
還是可以繼續進入迴圈,只是在這次的迴圈內,cin 要再讀進一筆
資料時,才會發現已經讀到檔尾了(讀完第十筆時還不知道!)
讀取失敗,而 a,b 或是 str 的值仍然保留上一次讀到的,結果
程式還認定說它是有效的並加以處理,那就錯了。
所以正確的寫法同樣是將 cin >> a >> b 或是 getline(cin, str)
寫進 while (...) 條件中。至於 eof() 的使用時機,反而要在
整個迴圈結束,在程式後面,有需要檢查為什麼會結束迴圈時,
才來使用 eof(), 因為如同前面所說, 有可能是到了檔尾,也有
可能是讀到不合所需的資料,或是 istream buffer 壞掉。
但像 ACM 的 input, 都可以放心的假定它給的資料不會有這些問題。
所以都不用再做離開迴圈後的額外檢查。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.166
推
220.138.122.24 06/12, , 1F
220.138.122.24 06/12, 1F
→
220.138.122.24 06/12, , 2F
220.138.122.24 06/12, 2F
推
218.170.46.188 06/14, , 3F
218.170.46.188 06/14, 3F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章