首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 迴圈輸出陣列少首項多亂碼:getchar() 吞噬首字元與迴圈邊界 Off-by-one 雙重陷阱

     編輯:程式設計綜合問答

問題程式碼

for (i = 0; getchar() != '\n'; i++) {  // 陷阱 1
    cin >> a[i];
    // ...
}
for (i = 0; i <= k; i++) {  // 陷阱 2
    cout << a[i] << " ";
}

陷阱 1:getchar() 偷吃首個輸入字元

  • 使用者輸入 1.5 2.3 3.7\n,緩衝區內容:'1' '.' '5' ' ' '2' ... '\n'。
  • getchar() 讀取第一個字元 '1' 並判斷非 '\n',迴圈繼續。
  • cin >> a[0] 從緩衝區讀取剩餘 .5 2.3 3.7,解析失敗或數值錯誤。
  • 結果:第一個有效數字被丟棄,陣列從索引 1 開始存放有效值,索引 0 為未初始化亂碼。

陷阱 2:輸出迴圈條件 i <= k 多跑一次

  • k 為實際讀入個數 (假設 3),有效索引 0,1,2。
  • i <= k 會跑 0,1,2,3 四次,a[3] 為未初始化記憶體 → 輸出亂碼。

修正版本

// 方案 A:純 cin 讀取,利用 EOF 或特定哨兵值結束
int k = 0;
while (k < 100 && cin >> a[k]) {
    if (a[k] < 0) { /* 錯誤處理 */ }
    k++;
}

// 方案 B:讀整行再用 stringstream 解析 (最穩健)
string line;
getline(cin, line);
stringstream ss(line);
while (k < 100 && ss >> a[k]) k++;

// 輸出迴圈:嚴格 i < k
for (int i = 0; i < k; i++) cout << a[i] << " ";

核心原則

  1. 別混用 C (getchar/scanf) 與 C++ (cin/cout) I/O:緩衝區不同步,極易產生「字元被吞」Bug。
  2. 迴圈邊界永遠用 i < n:n 為元素個數,有效索引 0 ~ n-1。
  3. 輸入失敗處理:if (!(cin >> val)) { cin.clear(); cin.ignore(numeric_limits::max(), '\n'); }。

拒絕「C/C++ 混合 I/O」,堅守「迴圈邊界 < n」鐵律,即可消滅此類低級且隱蔽的陣列存取錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved