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