Skip to content

cin 使用筆記

以下將由問題開頭,介紹各個小重點,如果問題能正確答出來,就可以跳過該小節囉0.<

目錄
寫入單位
Buffer 與 cin.ignore()
Error Flag 與 cin.clear()

1. 寫入單位

problem 1
string a = "hello" ;
cin >> a;

輸入為:
a new world

問 變數a 的內容?

  1. hello
  2. world
  3. a
  4. a new world

答案為3

原因在於空格、tab、換行都是cin的讀取變數終止條件
若讀取到這些,cin就會把剛剛讀到的東西放進變數中,以此例而言,碰到a前面的空格就結束一次操作,所以a這個變數的值被改寫成a

problem 2
char a = '1' ;
char b = '2' ;
char c = '3' ;
char d = '4' ;
char e = '5' ;
cin >> a >> b >> c >> d >> e ;
cout << a << b << c << d <<e ;
輸入為:
a\tcat\n
\n

問 執行結果為? (note \t為tab,\n為換行)

  1. a cat
  2. acat\n
  3. a cat
  4. acat5
  5. 12345

答案為4,由此可知只要使用cin,讀取單位就連char也是會遇到空格就不反應

2. Buffer與cin.ignore()

problem 3
int Number = 0; 
string name[2];

while(Number<2){
	cout<<"what is your name?"<<endl;
	cin>>name[Number];
	Number+=1;
}

輸入:
Anya Hsiao
Willy Fang
Harry Chin

//再繼續執行
string Test;
cin>>Test;

請問此時Test變數會得到甚麼結果?

  1. 沒有結果,等待使用者輸入
  2. Harry Chin
  3. Willy
  4. Fang

答案為3

除了遇到空格就將值輸入變數以外,cin/cout等IO輸入還有Buffer的存在
會先將輸出/輸入記到一塊暫存記憶體裡,方便後續cin/cout取用,所以前兩次輸入會把Anya與Hsiao吃進去,最後一個變數則會吃到Willy
如果後續還有cin,則會依序吃入Fang,Harry,Chin

cin.ignore(Max,delim)

這是一個清空buffer的函式,如果在string Test;前呼叫此函數
則會讓buffer清空,那答案就會變成1) 沒有結果,等待使用者輸入

Max參數,填入最多無視多少字元的buffer殘留內容,為一整數
delim參數,填入無視到哪一個字符停止,通常為換行

cin.ignore(256,'\n’)常常與cin.clear()一起用在發生錯誤輸入的時候

  • 注意: 在unix資料重導時可能ignore會失效,要用另外的方法把cin關掉

3. Error Flag 與 cin.clear()

problem 4
int a = 1024;
int b = 2048;
char c = '-';
//scanf version  ===========
scanf("%d",&a);
scanf("%d",&b);
scanf("%c",&c);
// =========================

//cin version  ===========
cin >> a >> b >> c
// =========================

//輸入
314 e 271 

問 scanf 版本 與 cin版本 各變數內容為何(以(a,b,c)表示)?

  1. scanf:(314,271,e)
    cin:(314,271,e)
  2. scanf:(314,2048,-)
    cin:(314,2048,-)
  3. scanf:(314,2048,e)
    cin:(314,2048,e)
  4. scanf:(314,2048,e)
    cin:(314,0,-)

答案為4

首先解釋scanf版本
a能讀到東西沒有問題
b因為當下buffer內的東西為e 271
所以會讀到e,但是e不是整數!,所以b判斷為沒有讀到東西
因此留到c讀到e,然後結束

再來解釋cin版本
a一樣沒有問題
到b時buffer內容也為e 271
但此時b讀到e發現不是整數,觸發cin的error flag ,並且將b的變數值設為0 (因此整數無端在cin收到0,就是個錯誤訊號)

觸發過error flag的cin後續將不會再傳送值給變數 ,因此即使buffer內還有e,變數c也讀不到了

會有這個差異,主要也是因為scanf是函式,而std::cin是物件,可以記錄更多狀態

此外,>> 運算符會將cin運行成功與否作為True/False回傳
這也是為甚麼可以使用if(cin»x) 或 while(cin»x)等技巧

cin.clear()

這個函式是用來讓error flag解除,使cin可以繼續工作
因此也常在error handle與 cin.ignore(max,delim)合作

如果在b讀取錯誤後加入此行,即可讓c正確的被讀入

小結

  1. cin是一個輸入物件,以空格,換行,tab作為讀取單位
  2. cin存在buffer,必要時應使用ignore(max,delim)函式清空
  3. cin會有error flag機制,比如將字串餵給整數變數等錯誤格式發生時會啟動,整個函數會回傳false,並將0餵給整數變數,然後後續操作都會不成功,直到cin.clear()清除這個狀態