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

C語言 scanf 讀取結構體成員時字串溢位問題解析

     編輯:程式設計疑難解答

問題現象

在編寫學生成績管理系統時,使用 scanf("%s %s %c", name, stunum, &sex); 直接讀取到普通變數,輸入 Xiaoming 2015000000 F 後,stunum 正確為 2015000000,sex 為 F。但若改為直接讀取結構體成員:

scanf("%s %s %c", student[0].name, student[0].stunum, &student[0].sex);

相同輸入下,stunum 卻變成了 2015000000F,而 sex 仍為 F。這讓初學者感到困惑:結構體裡的字串與普通字串到底有何不同?

根本原因:緩衝區溢位

最佳回答指出:stunum 陣列分配的長度不足,導致寫入時溢位,覆蓋了緊隨其後的 sex 成員。

當 scanf 以 %s 格式讀取字串時,會在字串末尾自動加上結束符 \0。若 stunum 定義為 char stunum[11](僅能容納 10 位數字),輸入 2015000000 (10 位) 加上 \0 剛好填滿。但若定義為 char stunum[10],則 \0 會寫入下一個記憶體位置——即 sex 的位置。由於 sex 是 char 型別,佔 1 位元組,剛好被 \0 覆蓋。隨後 scanf 繼續讀取 %c 到 sex,將 F 寫入,導致 stunum 印出時因缺少結束符而一直讀到 sex 的 F,顯示為 2015000000F。

解決方案

  1. 確保字串陣列長度 ≥ 最大可能長度 + 1(留空間給 \0)。例如學號最長 10 位,應定義 char stunum[11] 或更大。
  2. 使用寬度限制:scanf("%10s", stunum) 防止讀入超過陣列容量。
  3. 改用較安全的輸入函數(如 fgets 配合 sscanf),並自行移除換行符。

舉例修正

struct Student {
    char name[20];
    char stunum[11];  // 至少 11,容納 10 位數字 + '\0'
    char sex;
};

int main() {
    struct Student student[1];
    // 加上寬度限制,更安全
    scanf("%19s %10s %c", student[0].name, student[0].stunum, &student[0].sex);
    printf("Name: %s\nStuNum: %s\nSex: %c\n", student[0].name, student[0].stunum, student[0].sex);
    return 0;
}

總結

結構體成員在記憶體中是連續排列的。字串讀取若未預留結束符空間,極易造成鄰近成員被覆蓋,產生難以察覺的錯誤。良好的習慣是:定義足夠大的緩衝區、使用寬度限制、檢查輸入長度。

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