C++ 之cin與cout常見問題詳解

經常要使用到cin和cout,花了點時間,把常見的問題整理了一下,供記性不好時查閱。

在程序中包含iostream文件將自動創建cin對象和cou對象,即標準輸入流和標準輸出流。


關於cout :

<<操作符的默認含義是按位左移操作符,但ostream類重新定義了<<操作符,將其重載爲輸出方法。<<支持C++的所有的基本類型。對於每一種數據類型,C++都提供了operator<<()的定義。例如,如果表達式cout << 100對應於下面的方法:

Ostream & operator<<(int);

Ostream類還爲以下的指針類型定義了插入操作符函數:

Const signed char*;

Const unsigned char*;

Const char*;

Void *;

Cout 支持拼接輸出:

如: cout << "hello" <<"world"<<endl;


怎樣刷新輸出緩衝區?

由於ostreamcout對象處理的輸出進行緩衝,所以輸出不會立即發送到目的地址,而是被存儲在緩衝區中,直到緩衝區填滿。然後,程序將刷新緩衝區,把內容發送出去,並清空緩衝區,以存儲新的數據。通常,緩衝區爲512字節或其整數倍。

有兩種方式實現緩衝區的手動刷新:

Flush:刷新緩衝區

Endl:刷新緩衝區,並插入一個換行符

例如: 

  cout << "hello world" << flush;

  Cout << "hello world" <<endl;


關於cin:

Cin對象將標準輸入表示爲字節流。輸入可以是字符串的一部分、int值、float值等,istreaml類重載了抽取操作符>>,使之能夠識別C++所有的基本數據類型,所以,抽取還涉及到類型轉換。編譯器將根據數據接收者的類型,匹配適當的的函數。

例如: cin >> value_holder 

如果value_holderint型,則將匹配函數

istream & operator>>(int &); //注意函數原型,參數和返回值都是引用

而如果value_holderchar類型,則將匹配函數

istream & operator >>(char &);

istream類爲下列字符指針類型重載了>>抽取操作符:

signed char*;

char *;

unsigned char *;

Cin的常見用法:

用法1:最基本,也是最常用的用法,輸入一個數字:

[java] view plaincopy
  1. #include <iostream>  
  2.  using namespace std;  
  3.  int main () {  
  4.  int a,b;  
  5.  cin>>a>>b;   
  6.  cout<<a+b<<endl;   
  7.  return 0;  
  8. }  

注意:>> 是會過濾掉不可見字符(如 空格 回車,TAB 等) 
cin>>noskipws>>input[j];//不想略過空白字符,那就使用 noskipws 流控制

用法2:接受一個字符串,遇空格“TAB”回車都結束

[java] view plaincopy
  1. #include <iostream>   
  2. using namespace std;   
  3. int main () {   
  4.  char a[20];  
  5.  cin>>a;   
  6.  cout<<a<<endl;  
  7. return 0  
  8. }  

Cin有一個比較“智能”之處,即它會讀取從非空白字符開始,到與目標類型不匹配的第一個字符之間的全部內容。

例如,對於下面的代碼:

Int value;

Cin >> -123a;

操作符將提取-,1,2,3,因爲它們都是整數的有效部分。但是a字符不是有效字符,因此輸入中最後一個可接受的字符是3a將留在輸入流中,下一個cin語句將從這裏開始讀取。與此同時,操作符將字符序列-123轉換爲一個整數值,並將它賦給value


怎樣實現循環輸入?

先看這樣一段代碼:

[java] view plaincopy
  1. int sum =0;  
  2. int input;  
  3. While(cin >> input){  
  4.     Sum += input;  
  5. }  

這段代碼實現了循環輸入,循環體中當然可以用別的數據結構比如容器來接收輸入,這不是一個死循環嗎?當然,如果一直輸入的是正確的int型數據,輸入將一直進行下去,直到地老天荒!結束這個循環的方法很簡單,輸入一個錯誤字符即可。

cin操作未能讀取到預期的字符時,它將設置流狀態failbit.,此時,if或者else將斷定cin對象爲false


怎樣恢復流狀態?

>>提取到非預期字符時,會設置failbit,此時流會關閉。如果要繼續輸入,必須要重置流狀態,同時還要清空流緩存中遺留的數據。

Cin.clear();//重置流狀態

Cin.sync();//清空流緩存

這兩個函數要同時使用纔算完成重置流狀態。

以下代碼說明sync()函數的功能:

[java] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. int main () {  
  5.   char first, second;  
  6.   
  7.   cout << "Please, enter a word: ";  
  8.   first=cin.get();  
  9.   cin.sync();  
  10.   
  11.   cout << "Please, enter another word: ";  
  12.   second=cin.get();  
  13.   
  14.   cout << "The first word began by " << first << endl;  
  15.   cout << "The second word began by " << second << endl;  
  16.   return 0;  
  17. }  

怎樣得到整行數據?

如果想得到整行數據,cin有諸多限制。這時可以借用非格式化輸入函數。

istream & getline(char*,int,char);

istream & getline(char* ,int);

這是istream提供的整行錄入函數,但是都需要制定接收字符串的長度,streamstring提供了一個更便捷的getline版本:

istream &getline(istream&,string)

這個函數接受兩個參數:一個輸入流對象和一個string對象。getline函數從輸入流的下一行讀取,並保存讀取的內容到string中,但不包括換行符。和輸入操作符不一樣的是,getline並不忽略行開頭的換行符。只要getline遇到換行符,即便它是輸入的第一個字符,getline也將停止讀入並返回。如果第一個字符就是換行符,則string參數將被置爲空string 

getline函數將istream參數作爲返回值,和輸入操作符一樣也把它用作判斷條件。

例如: 

[java] view plaincopy
  1. int main(){  
  2. string line;  
  3. while (getline(cin, line))   
  4.   cout << line << endl;  
  5. return 0;  
  6. }   

由於getline函數返回時丟棄換行符,換行符將不會存儲在string對象中。 



參考資料:

《C++ primer》

《C++ primer plus》


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章