Competitive Programming Note
本文已停止更新,新版請至 WiwiHo 的競程筆記
重載 <<
和 >>
就能讓原本不能直接輸入輸出的東西可以直接 cin/cout 了,例如:
EOF 是 End of File 的縮寫。有些題目會在一個檔案放多筆測資,比較現代的題目會先輸入一個數字告訴你接下來有幾筆,但比較古老的題目或心理比較古老的人出的題目就會跟你說「以 EOF 結束」,所以你必須一直讀到檔案結束為止,做法很簡單:
cin >> ...
除了把東西輸入到變數裡,也會回傳 cin 本身(這就是為什麼可以像 cin >> a >> b >> c >> ...
串一大串),而 cin 可以轉型成 bool,如果遇到 EOF(或其他原因導致輸入失敗)了它就是 false,否則它就是 true。
EOF 這東西不是一個字元,所以你可能會想,terminal 不是 file,不就沒有 EOF 了嗎?在 Windows 可以用 ctrl+z 製造出 EOF,其他系統可以用 ctrl+d。
用像是 cin >> ...
的方式輸入的話,會先忽略緩衝區前面的所有空白字元(空格、換行等等),然後讀取非空白字元,直到遇到空白字元再停下來。
但是,當遇到這種情況,就會需要一次輸入一整行:你需要知道哪些東西在同一行,而且又不確定一行有幾個,方法是這樣:
getline 也可以放進 while 裡判 EOF。
getline 跟 >>
混用的話會發生一個問題,假設有兩行輸入,第一行有一個數字,下一行有未知數量的以空格隔開的數字,首先它們會全部進入緩衝區,如果你先用 >>
輸入了一個數字,那麼在緩衝區內的這個數字會被移除,但它後面的換行不會,所以你這個時候用 getline,就得到一個空字串,解決方法也很簡單,就是 getline 一次把空白行清掉後,再 getline 一次。
直接看題目:ZeroJudge c268,這題表面上是要你找三個數字當三角形的邊長,可以 做完,可是第一 超大,把數字排序好後就 TLE 了,就算不排序,雖然輸入的複雜度是 ,但輸入常數很大,輸入這麼多東西也會 TLE 的。
可以發現到若輸入的數字都不能構成三角形,那麼在數字都盡量小的情況下,把它們排序後會變成費氏數列,而輸字的最大值又是 ,費氏數列還沒到第 50 項就會超過了,所以可以得出 的時候保證有解。
現在排序的問題解決了,那輸入的問題呢?它是一個檔案多筆測資,所以也不能讀到 就直接 return,解決方法是:
這麼做可以忽略掉到一部分的輸入,第一個參數是忽略的字元上限,打一個很大的數字就行了,第二個是停下來的字元,到下一個這個字元之前和它本身的字元都會被忽略掉。
這也是 getline 解決空行的解法之一。
需要輸出浮點數的題目,要嘛就是要求跟答案的差距要在某個範圍內,不然就是要求你四捨五入到第幾位,所以我們要能夠控制輸出的小數點後位數。方法是這樣:
沒加 fixed 的話,會變成是指定總共的位數,如果小數點前的位數超過就會變科學記號,而加上 fixed 就是指定小數點後的位數了,然後它也會自己四捨五入,非常方便。還有它只作用在浮點數,像是 int 不會跑出 .0000,字元也還是以字元的形式輸出。
數字寬度和數字位數不一樣,輸字寬度是指輸出的總字元數不到寬度的時候,就會在它之前補上數個某固定字元。指定寬度是 setw(n)
,補上的字元是 setfill(c)
,預設空格,用法就一樣是 cout << setw(n) << setfill(c) << ...
。要特別注意的是,setw
只作用在下一個輸出的數字(可以是浮點數或整數)上,而 setfill 不會失效。