首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 輸入流 cin 詳解:緩衝區機制與常見陷阱

     編輯:關於C++

cin 的工作原理

程序輸入建立一個輸入緩衝區。鍵盤輸入結束(按 Enter)時,數據存入緩衝區;cin 直接從緩衝區取數據。關鍵點:若緩衝區有殘留數據,cin 會直接讀取而不再請求鍵盤輸入,這是許多「輸入失效」Bug 的根源。

cin 讀取結束條件

  • 遇到 空格、Tab、換行符
  • 這些分隔符會被丟棄(不存入變量)

常見場景實測

場景 1:基本整數輸入

int m, n;
cin >> m >> n;
cout << m << n << endl;

正常輸入 10 20 或 10\n20 均可;但若輸入非數字,流進入錯誤狀態。

場景 2:string 輸入與 getline 交互

string str1;
cin >> str1;        // 遇到空格停止,從第一個非空格字符開始讀取
cin.get();          // 關鍵:吞掉殘留的換行符
getline(cin, str1); // 讀取整行(含空格),遇到換行停止,換行符被丟棄
  • cin >> str:跳過前導空白,遇空白停止
  • getline:從當前位置讀起(含空白),遇換行停止並丟棄換行
  • 必須在兩者之間用 cin.get() 或 cin.ignore() 清理換行符

場景 3:cin.getline 固定長度讀取

char str[8];
cin.getline(str, 5); // 最多讀 4 字符 + '\0'
cout << str << endl;
cin.getline(str, 5);
cout << str << endl;
  • 輸入 abcd\nabcd:正常輸出兩行
  • 輸入 abcdefgh\n:第一次讀 abcd,第二次直接讀取殘留的 efgh,不再等待輸入

cin.get() 逐字符讀取

char c1 = cin.get(); // 讀取首字符,從緩衝區移除
char c2 = cin.get(); // 讀取下一字符
// 輸入 "abcd" → 輸出 'a' 'b'

空調用 cin.get() 相當於丟棄一個字符。cin.get() 不丟棄 分隔符(換行/空格),這與 operator>> 不同。

cin.get(char&) 讀取單字符到變量

char c1, c2;
cin.get(c1);  // 輸入 'a\n' → c1='a', 緩衝區剩 '\n'
cin.get(c2);  // c2='\n' (ASCII 10)!

這正是換行符殘留導致後續輸入「失效」的典型案例。

cin.getline vs cin.get(array, size)

特性cin.getlinecin.get(arr, size)
結束符換行符換行符
接受空格是是
丟棄換行符是否(留在緩衝區)
輸入超長行為設置 failbit,後續操作失效不設置 failbit,後續操作繼續從緩衝區讀取

流狀態標誌與異常處理

ios 定義四個狀態位:

  • goodbit (0):正常
  • eofbit (1):到達文件末尾
  • failbit (2):非致命錯誤(如類型不匹配),可恢復
  • badbit (4):致命錯誤,不可恢復

標準錯誤恢復模式

int a;
while (true) {
    cin >> a;
    if (!cin) {  // 等價於 cin.fail()
        cout << "輸入類型錯誤,請重新輸入!" << endl;
        cin.clear();   // 重置錯誤標誌
        cin.sync();    // 清空緩衝區(或用 cin.ignore(1024, '\n'))
    } else {
        cout << a << endl;
        break;
    }
}

關鍵:cin.clear() 恢復流狀態,cin.sync()/cin.ignore() 清理髒數據,否則進入死循環。

cin.ignore() 靈活丟棄

  • cin.ignore():丟棄 1 字符(默認參數 1, EOF)
  • cin.ignore(n, delim):丟棄最多 n 字符,或遇到 delim 停止(含 delim)
  • 常用模式:cin.ignore(1024, '\n') 清空整行殘留

最佳實踐總結

  1. 混用 >> 和 getline 時,中間必須 cin.ignore() 清理換行符
  2. 讀取可能包含空格的字符串,優先用 getline
  3. 輸入驗證:檢查流狀態,用 clear() + ignore() 恢復
  4. 固定長度讀取用 getline(arr, size) 避免超長導致流錯誤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved