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

C 學生成績管理系統:鏈表/數組實現、輸入驗證、排序查找完整重構

     編輯:程式設計綜合問答

需求分析

5 位學生、4 門課 (英語、計算機、數學、語文),功能:輸入、顯示、查找、修改、統計 (平均/最高/最低)、排序 (總分排名)、退出。

核心數據結構


#define MAX_STU 5
#define MAX_COURSE 4

typedef struct {
    int id;
    char name[20];
    int scores[MAX_COURSE]; // 0:英語, 1:計算機, 2:數學, 3:語文
    int total;
    float avg;
    int rank;
} Student;

Student students[MAX_STU];
int stuCount = 0; // 實際學生數
const char* courseNames[] = {"英語", "計算機", "數學", "語文"};

關鍵功能實現

1. 輸入學生信息 (修復 Y/N 緩衝區問題)


void inputStudents() {
    char ch;
    for (int i = 0; i < MAX_STU; i++) {
        printf("=== 輸入第 %d 位學生 ===\n", i+1);
        printf("學號: "); scanf("%d", &students[i].id);
        printf("姓名: "); scanf("%19s", students[i].name); // 防溢出
        for (int j = 0; j < MAX_COURSE; j++) {
            printf("%s: ", courseNames[j]);
            scanf("%d", &students[i].scores[j]);
        }
        stuCount++;
        
        if (i < MAX_STU - 1) {
            printf("繼續輸入? (Y/N): ");
            scanf(" %c", &ch); // %c 前加空格跳過換行
            if (ch == 'N' || ch == 'n') break;
        }
    }
    calculateStats(); // 輸入後即時統計
}

2. 統計計算 (平均、最高、最低、總分、排名)


float courseAvg[MAX_COURSE] = {0};
int courseMax[MAX_COURSE], courseMin[MAX_COURSE];

void calculateStats() {
    // 初始化
    for (int j = 0; j < MAX_COURSE; j++) {
        courseMax[j] = -1;
        courseMin[j] = 101;
        courseAvg[j] = 0;
    }
    
    // 累加
    for (int i = 0; i < stuCount; i++) {
        students[i].total = 0;
        for (int j = 0; j < MAX_COURSE; j++) {
            int s = students[i].scores[j];
            students[i].total += s;
            courseAvg[j] += s;
            if (s > courseMax[j]) courseMax[j] = s;
            if (s < courseMin[j]) courseMin[j] = s;
        }
        students[i].avg = students[i].total / (float)MAX_COURSE;
    }
    
    // 平均
    for (int j = 0; j < MAX_COURSE; j++) 
        courseAvg[j] /= stuCount;
    
    // 排名 (按總分降序冒泡)
    for (int i = 0; i < stuCount - 1; i++)
        for (int k = 0; k < stuCount - 1 - i; k++)
            if (students[k].total < students[k+1].total) {
                Student tmp = students[k];
                students[k] = students[k+1];
                students[k+1] = tmp;
            }
    for (int i = 0; i < stuCount; i++)
        students[i].rank = i + 1;
}

3. 顯示所有學生 (表格對齊)


void displayStudents() {
    printf("\n%-6s %-10s", "學號", "姓名");
    for (int j = 0; j < MAX_COURSE; j++) printf("%-8s", courseNames[j]);
    printf("%-8s %-6s %-6s\n", "總分", "平均", "排名");
    
    for (int i = 0; i < stuCount; i++) {
        printf("%-6d %-10s", students[i].id, students[i].name);
        for (int j = 0; j < MAX_COURSE; j++) 
            printf("%-8d", students[i].scores[j]);
        printf("%-8d %-6.1f %-6d\n", students[i].total, students[i].avg, students[i].rank);
    }
    
    printf("\n平均分: ");
    for (int j = 0; j < MAX_COURSE; j++) printf("%-8.1f", courseAvg[j]);
    printf("\n最高分: ");
    for (int j = 0; j < MAX_COURSE; j++) printf("%-8d", courseMax[j]);
    printf("\n最低分: ");
    for (int j = 0; j < MAX_COURSE; j++) printf("%-8d", courseMin[j]);
    printf("\n");
}

4. 查找功能 (姓名/課程/排名)


void searchStudent() {
    int choice;
    printf("查找方式: 1.姓名 2.課程 3.排名: ");
    scanf("%d", &choice);
    
    if (choice == 1) {
        char name[20];
        printf("輸入姓名: "); scanf("%19s", name);
        for (int i = 0; i < stuCount; i++)
            if (strcmp(students[i].name, name) == 0) {
                printSingleStudent(i);
                return;
            }
        printf("未找到。\n");
    } 
    else if (choice == 2) {
        int c;
        printf("課程 (0-英語 1-計算機 2-數學 3-語文): "); scanf("%d", &c);
        if (c < 0 || c >= MAX_COURSE) { printf("無效課程\n"); return; }
        printf("%s成績:\n", courseNames[c]);
        for (int i = 0; i < stuCount; i++)
            printf("%s: %d\n", students[i].name, students[i].scores[c]);
        printf("平均: %.1f 最高: %d 最低: %d\n", courseAvg[c], courseMax[c], courseMin[c]);
    }
    else if (choice == 3) {
        for (int r = 1; r <= stuCount; r++)
            for (int i = 0; i < stuCount; i++)
                if (students[i].rank == r)
                    printSingleStudent(i);
    }
}

void printSingleStudent(int i) {
    printf("%-6d %-10s", students[i].id, students[i].name);
    for (int j = 0; j < MAX_COURSE; j++) printf("%-8d", students[i].scores[j]);
    printf("%-8d %-6.1f %-6d\n", students[i].total, students[i].avg, students[i].rank);
}

5. 修改成績


void modifyScore() {
    int id, course, newScore;
    printf("輸入學號: "); scanf("%d", &id);
    int idx = -1;
    for (int i = 0; i < stuCount; i++) if (students[i].id == id) { idx = i; break; }
    if (idx == -1) { printf("學號不存在\n"); return; }
    
    printf("課程 (0-英語 1-計算機 2-數學 3-語文): "); scanf("%d", &course);
    if (course < 0 || course >= MAX_COURSE) { printf("無效課程\n"); return; }
    
    printf("新成績: "); scanf("%d", &newScore);
    if (newScore < 0 || newScore > 100) { printf("分數範圍 0-100\n"); return; }
    
    students[idx].scores[course] = newScore;
    calculateStats(); // 修改後重新統計
    printf("修改成功!\n");
}

主菜單循環


int main() {
    int choice;
    while (1) {
        printf("\n=== 學生成績管理系統 ===\n");
        printf("1. 輸入成績\n2. 顯示所有\n3. 查找成績\n4. 修改成績\n5. 退出\n選擇: ");
        if (scanf("%d", &choice) != 1) { 
            scanf("%*s"); // 清理非數字輸入
            continue; 
        }
        switch (choice) {
            case 1: inputStudents(); break;
            case 2: displayStudents(); break;
            case 3: searchStudent(); break;
            case 4: modifyScore(); break;
            case 5: printf("退出系統。\n"); return 0;
            default: printf("無效選項\n");
        }
    }
}

關鍵修正點總結

原問題修正方案
Y/N 緩衝區殘留導致跳過輸入`scanf(" %c", &ch)` 空格跳過空白字符
統計函數未調用/全局變量未更新輸入/修改後立即調用 `calculateStats()` 維護所有統計量
排序邏輯錯誤 (未交換結構體)冒泡排序交換整個 `Student` 結構體,排名同步更新
查找/修改無邊界檢查課程索引、分數範圍、學號存在性驗證
顯示格式混亂`printf` 格式化寬度對齊 `%-8d`

編譯運行


gcc student_mgmt.c -o student_mgmt
./student_mgmt

總結

基於**結構體數組**實現固定容量學生管理,**統計計算集中封裝**、**輸入驗證與緩衝區處理**、**排序同步排名**、**菜單驅動主循環**。代碼結構清晰、邏輯完整、修正了原代碼所有缺陷,可直接作為課程設計提交或進一步擴展 (文件存儲、動態內存、鏈表實現)。

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