一、緩衝
C++ 的輸入輸出均通過緩衝區來實現。緩衝區主要是為了解決速度不匹配的問題。
二、輸入(cin)
阻塞輸入。當輸入快取中無字元時則等待使用者輸入。
輸入緩衝
輸入緩衝是一種行緩衝。在輸入資料只要沒有碰到換行符(回車)就將資料存入輸入緩衝區,當碰到換行符之後就將緩衝區中的資料取出供變數使用,但是緩衝區中的換行符會被留在輸入緩衝區中。
cin>>
- 讀取:從輸入快取中直接讀取(若輸入快取無有效字元,則要求使用者輸入)。
- 不讀取快取首部的無效字元(空格、回車、換行)。
- 結束條件:空格、回車、換行。
- 其餘字元留在快取區中。
cin.get
a=cin.get() 或 cin.get(a)
- 讀取:從輸入快取中直接讀取一個字元(若輸入快取無字元,則要求使用者輸入)。
- 任意字元均可,包括無效字元(空格、回車、換行)。
cin.get(arrayname,size)
- 讀取:從輸入快取中直接讀取(若輸入快取無字元,則要求使用者輸入)。
- 若快取首部為空格、換行,則直接讀取。
- $\star$ 若快取首部為換行符,則將 '\0' 賦給目標,設定失效位failbit,緩衝區被禁止讀取,回車留在緩衝區。
- 結束條件:回車、到達size-1長度(最後一個字元存結束符)。
- $\star$ 讀取結束後不會刪除快取區中的換行符。
- $\star$ 超出size-1長度的字元留在緩衝區,供下一次讀取。
- 只能將字串讀入C風格的字串中,即char*。
cin.get(arrayname,size,s)
s為結束符,cin.get(arrayname,size) 預設結束符為換行符。其餘用法和 cin.get(arrayname,size) 均一樣。
cin.getline
無讀取單個字元的形式
cin.getline(arrayname,size)
- 讀取:從輸入快取中直接讀取(若輸入快取無字元,則要求使用者輸入)。
- 若快取首部為空格、換行,則直接讀取。
- $\star$ 若快取首部為換行符,則將 '\0' 賦給目標,將換行符刪除,結束此次讀取。
- 結束條件:回車、到達size-1長度(最後一個字元存結束符)。
- $\star$ 讀取結束後會刪除快取區中的換行符。
- $\star$ 超出size-1長度,則設定失效位failbit,阻斷cin流,緩衝區被禁止讀取。
- 只能將字串讀入C風格的字串中,即char*。
cin.getline(arrayname,size,s)
s為結束符,cin.getline(arrayname,size) 預設結束符為換行符。其餘用法和 cin.getline(arrayname,size) 均一樣。
getline(推薦!)
getline(cin, str)
- cin.getline()屬於istream流,只能讀入char*型別中。而getline(cin, str)屬於string流,可以讀入string型別中。
- cin與getline不能連用。因為cin會將 '\n' 留在緩衝區中,getline(cin, str) 遇到 '\n' 會直接返回。因此需要在cin>> 後加上cin.ignore()取出換行符。
cin.ignore
cin.ignore(size,s)
捨棄緩衝區中的長度為size或字元s之前的資料。
cin.ignore()
預設時size=1, s=EOF(檔案結束符)。常用來防止接收上次輸入的回車符。
cin.ignore(std::numeric_limits< streamsize >::max(), '\n')
其中,numeric_limits
常用來清除輸入緩衝區的所有內容,使上次的輸入殘留下的資料不要影響到下一次的輸入。不要使用cin.sync(),sync()原意是同步輸入流,而不是清空緩衝區,在不同編譯器裡的實現可能不同,linux下g++就無法實現。
加'\n'為清除緩衝區中一行,但緩衝區中可能不止有一行。不加'\n'為清除EOF前所有的資料,但必須要確保緩衝區中有EOF符號,否則就會一直阻塞。
cin.clear
cin.clear() 將流cin中的所有狀態值都重設為有效狀態。
常用cin.clear() + cin.ignore(std::numeric_limits< streamsize >::max(), '\n') 清空緩衝資料。
三、輸出(cout、cerr、clog)
cout
標準輸出。有緩衝。
cout<<
表示輸出到緩衝區,並不是直接輸出到console。而是遇到endl和flush之類的才輸出。
endl、flush 和 \n
- endl: 換行+重新整理輸出緩衝
- \n: 換行
- flush: 重新整理
由於輸出緩衝區為行緩衝,遇到換行符自動換行。因此 endl 和 \n 在使用上沒有什麼區別。若在 cout 後三者都不加,則不會輸出到console,直到後面程式重新整理緩衝區或程式結束。
cerr
沒有緩衝,傳送給它的內容立即被輸出。
clog
有緩衝。