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

C語言 scanf 讀取字符陷阱:為什麼第一種寫法無法判斷換行符?

     編輯:C 語言問答

兩種寫法對比

// 方法 1:直接拿 scanf 返回值比較
for (i = 0; i < 100; i++) {
    if ((scanf("%c", &a[i])) == '\n')  // ❌ 錯誤
        break;
}

// 方法 2:先讀取,再判斷數組元素
for (i = 0; i < 100; i++) {
    scanf("%c", &a[i]);                // ✅ 正確
    if (a[i] == '\n')
        break;
}

核心原因:scanf 返回值 ≠ 讀取的字符

scanf("%c", &a[i]) 的返回值是 成功匹配並賦值的項目數(此處為 1),不是 讀取到的字符本身。因此 (scanf(...)) == '\n' 實際是在比較 1 == 10(ASCII 換行符),永遠為假。

scanf 返回值規則速查

格式串成功返回失敗/EOF 返回
%d1EOF (-1)
%c1EOF
%d %c2EOF 或 0/1(部分匹配)
%s1EOF

正確處理「讀一行字符」的三種模式

模式 A:scanf + 手動判斷(最接近原題)

int i = 0;
while (i < 100) {
    scanf("%c", &a[i]);      // 讀取單字符(含空格、換行)
    if (a[i] == '\n') break; // 判斷數組內容
    i++;
}
a[i] = '\0'; // 可選:轉為 C 字符串

模式 B:fgets 一次讀整行(推薦)

char line[101];
if (fgets(line, sizeof(line), stdin)) {
    // line 包含換行符,長度 ≤ 100
    // 可直接處理 line[0..len-2]
}

✅ 避免逐字符 scanf 開銷,自動處理緩衝區,防溢出。

模式 C:scanf 掃描集讀非換行字符

char buf[101];
scanf("%100[^\n]", buf);  // 讀取最多 100 個非換行字符
getchar();                // 吞掉殘留的 \n
// buf 已是以 \0 結尾的字符串

⚠️ 若輸入首字符即換行,scanf 返回 0,需檢查返回值。

延伸陷阱:scanf 留下的換行符

int x; char c;
scanf("%d", &x);  // 用戶輸入 "42\n",scanf 吃掉 42,\n 留在緩衝區
scanf("%c", &c);  // 直接讀到 \n,c == '\n',看似「跳過」輸入

解決:scanf(" %c", &c) 格式串前加空格,跳過所有空白字符(含 \n、空格、Tab)。

總結

  • scanf 返回 賦值項目數,不是 讀取的數據值。
  • 逐字符讀取時,先存入變量,再判斷變量內容(方法 2)。
  • 實際工程中 優先用 fgets 讀行,再用 sscanf/手動解析,最穩健。
  • 混用 scanf 讀數值和讀字符時,注意 格式串前加空格 吃掉殘留換行。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved