👉博__主👈:米碼收割機
👉技__能👈:C++/Python語言
👉專__注👈:專注主流機器人、人工智能等相關領域的開發、測試技術。
系C語言 實踐課題選題系統(源碼+報告+數據文件)【獨一無二】
目錄
- 系C語言 實踐課題選題系統(源碼+報告+數據文件)【獨一無二】
- 一、設計要求
- 二、設計思路
- 三、可視化分析
一、設計要求
設計一個實踐課題選題系統,完成學生選題功能。教師可以添加、管理、發布自己的課題題目,并查看選擇題目的學生情況。學生登陸后,可以查看教師題目 ,并進行選題。
實踐課題題目包括:題目編號、題目名稱、人員數(由幾個人來完成)、指導教師等信息。
學生信息包括:學號、姓名、性別、年齡、班級、專業等信息。
(1)添加功能:程序能夠添加學生的記錄和實踐課題題目記錄,提供選擇界面供用戶選擇所要添加的類別。添加記錄時,要求學號和編號要唯一。如果添加了重復記錄,則提示數據添加重復并取消添加。
(2)查詢功能:可根據學號、姓名、編號、名稱等信息對已添加的學生和實踐課題題目進行查詢,如果未找到,給出相應的提示信息,如果找到,則顯示相應的記錄信息。
(3)顯示功能:可顯示當前系統中所有學生的信息和實踐課題題目信息,每條記錄占據一行。
(4)編輯功能:可根據查詢結果對相應的記錄進行修改,修改時注意學號的唯一性。
(5)刪除功能:主要實現對已添加的學生和實踐課題題目記錄進行刪除。如果當前系統中沒有相應的記錄,則提示“記錄為空!”并返回操作。
(6)統計功能:能根據多種參數進行統計。能按實踐課題題目名稱統計出學生選擇該題目的人員的信息。
(7)保存功能:可將當前系統中各類記錄存入文件中,存入方式任意。
(8)讀取功能:可將保存在文件中的信息讀入到當前系統中,供用戶進行使用。
二、設計思路
為實現高效的數據管理和操作,系統采用結構體數組的形式管理學生和課題信息:
- 學生結構體(Student):包括學號、姓名、性別、年齡、班級、專業以及已選課題編號等字段。學號作為唯一標識,用于檢索和操作學生信息。
- 課題結構體(Topic):包括課題編號、課題名稱、預計人數和指導教師等字段。課題編號作為唯一標識,用于查詢和分配課題。
兩個結構體均以全局數組形式存儲,設置了學生和課題的最大數量上限(MAX_STUDENTS 和 MAX_TOPICS)。通過全局變量記錄當前學生和課題的數量,便于動態管理數據。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_STUDENTS 100
#define MAX_TOPICS 100// 學生結構體
typedef struct {char id[20]; // 學號 (唯一)char name[20]; // 姓名char sex[10]; // 性別int age; // 年齡char className[20]; // 班級char major[20]; // 專業char chosenTopicId[20]; // 已選課題編號(可為空字符串)
} Student;// 課題結構體
typedef struct {char id[20]; // 課題編號 (唯一)char name[50]; // 課題名稱int personCount; // 人員數char teacher[20]; // 指導教師
} Topic;// 全局數組存儲
Student g_students[MAX_STUDENTS];
Topic g_topics[MAX_TOPICS];// 當前學生和課題的數量
int g_studentCount = 0;
int g_topicCount = 0;
每個功能模塊均通過一個獨立的函數實現,確保代碼結構的清晰和可維護性。主要功能的實現邏輯如下:
- 添加功能:檢查數據唯一性(學號或課題編號)后,將新數據添加至對應數組,并更新計數器。
- 查詢功能:支持按學號、姓名(學生)或編號、名稱(課題)進行查詢,并展示匹配結果。
- 顯示功能:依次遍歷學生和課題數組,輸出所有記錄的信息,方便用戶查看。
- 編輯功能:通過唯一標識找到對應數據,更新其字段值并重新保存。
- 刪除功能:通過唯一標識找到記錄,并將最后一條記錄覆蓋到刪除位置,減少數據移動操作的開銷。
- 統計功能:根據課題名稱找到對應課題編號,并輸出選擇該課題的所有學生信息。
- 文件操作:通過文件讀寫功能實現數據的持久化存儲,將學生和課題信息分別保存到兩個文件中,支持系統重啟后數據恢復。
- 選題功能:學生輸入學號后,系統驗證其身份,并允許其從可選課題中選擇一個,將課題編號保存到學生記錄中。
int main(void) {int choice;do {printf("\n================= 實踐課題選題管理系統 =================\n");printf("1. 添加記錄 (學生 / 課題)\n");printf("2. 查詢記錄 (學生 / 課題)\n");printf("3. 顯示所有記錄 (學生 & 課題)\n");printf("4. 編輯記錄 (學生 / 課題)\n");printf("5. 刪除記錄 (學生 / 課題)\n");printf("6. 統計 (按課題名稱查看選課學生)\n");printf("7. 保存記錄到文件\n");printf("8. 從文件讀取記錄\n");printf("9. 學生選題\n");printf("0. 退出系統\n");printf("=======================================================\n");printf("請輸入你的選擇: ");scanf("%d", &choice);getchar();switch(choice) {case 1: addRecord(); break;case 2: searchRecord(); break;case 3: displayRecords(); break;case 4: editRecord(); break;case 5: deleteRecord(); break;case 6: statisticsInfo(); break;case 7: saveToFile(); break;case 8: readFromFile(); break;case 9: chooseTopic(); break;case 0: printf("已退出系統。\n"); break;default: printf("無效的選擇,請重新輸入。\n"); break;}} while(choice != 0);return 0;
}
void addRecord() {int subChoice;printf("\n--- 添加記錄 ---\n");printf("1. 添加學生\n");printf("2. 添加課題\n");printf("請輸入選擇: ");scanf("%d", &subChoice);getchar();if (subChoice == 1) {if (g_studentCount >= MAX_STUDENTS) {printf("學生數量已達上限,無法添加。\n");return;}Student temp;printf("請輸入學號: ");scanf("%s", temp.id);getchar();if (isStudentIdExist(temp.id)) {printf("該學號已存在,添加失敗。\n");return;}printf("請輸入姓名: ");scanf("%s", temp.name);getchar();printf("請輸入性別: ");scanf("%s", temp.sex);getchar();printf("請輸入年齡: ");scanf("%d", &temp.age);getchar();printf("請輸入班級: ");scanf("%s", temp.className);getchar();printf("請輸入專業: ");scanf("%s", temp.major);getchar();strcpy(temp.chosenTopicId, "");g_students[g_studentCount++] = temp;printf("學生信息添加成功!\n");} else if (subChoice == 2) {if (g_topicCount >= MAX_TOPICS) {printf("課題數量已達上限,無法添加。\n");return;}Topic temp;//此處略去至少10行代碼printf("請輸入指導教師姓名: ");scanf("%s", temp.teacher);getchar();g_topics[g_topicCount++] = temp;printf("課題信息添加成功!\n");} else {printf("無效選擇。\n");}
}
void searchRecord() {int subChoice;printf("\n--- 查詢記錄 ---\n");printf("1. 查詢學生\n");printf("2. 查詢課題\n");printf("請輸入選擇: ");scanf("%d", &subChoice);getchar();if (subChoice == 1) {printf("查詢學生: 1. 按學號 2. 按姓名\n");int mode;scanf("%d", &mode);getchar();//此處略去至少10行代碼}}}
}
void saveToFile() {FILE *fpStu = fopen("students.txt", "w");if (!fpStu) {printf("無法保存學生信息。\n");return;}for (int i = 0; i < g_studentCount; i++) {fprintf(fpStu, "%s %s %s %d %s %s %s\n", g_students[i].id, g_students[i].name,g_students[i].sex, g_students[i].age, g_students[i].className,g_students[i].major, g_students[i].chosenTopicId);}fclose(fpStu);
}
統計信息代碼
void statisticsInfo() {if (g_topicCount == 0) {printf("當前無課題信息,無法統計。\n");return;}char tName[50];printf("請輸入要統計的課題名稱: ");scanf("%s", tName);getchar();// 找到課題編號int topicIndex = -1;for (int i = 0; i < g_topicCount; i++) {if (strcmp(g_topics[i].name, tName) == 0) {topicIndex = i;break;}}if (topicIndex == -1) {printf("未找到名稱為 [%s] 的課題。\n", tName);return;}// 根據課題編號統計選課學生//此處略去至少10行代碼if (!found) {printf("目前沒有學生選擇該課題。\n");}
}
統計信息模塊的設計旨在按課題名稱統計選課學生的詳細信息。通過輸入課題名稱,系統首先在課題列表中檢索匹配的課題編號,然后遍歷學生信息,篩選出已選擇該課題的學生并輸出詳細信息。如果未找到匹配的課題或沒有學生選擇該課題,系統會提示用戶,確保結果的明確性和友好性。
此模塊結合課題與學生數據,實現了兩者間的聯動統計,滿足了教務管理對選題分布信息的分析需求。代碼邏輯清晰,模塊化程度高,便于擴展,例如可以進一步加入統計選題人數限制或分析選題分布趨勢等功能,提升管理效率和數據洞察能力。
編輯信息代碼
void editRecord() {int subChoice;printf("\n--- 編輯記錄 ---\n");printf("1. 編輯學生\n");printf("2. 編輯課題\n");printf("請輸入選擇: ");scanf("%d", &subChoice);getchar();if (subChoice == 1) {// 編輯學生char sId[20];printf("請輸入要編輯的學生學號: ");scanf("%s", sId);getchar();int idx = findStudentIndexById(sId);if (idx == -1) {printf("未找到該學號的學生。\n");return;}// 顯示原信息并開始編輯Student *ps = &g_students[idx];printf("原信息: 學號:%s 姓名:%s 性別:%s 年齡:%d 班級:%s 專業:%s 選題編號:%s\n",ps->id, ps->name, ps->sex, ps->age, ps->className, ps->major, ps->chosenTopicId);printf("請輸入新的姓名: ");scanf("%s", ps->name);getchar();printf("請輸入新的性別: ");scanf("%s", ps->sex);getchar();printf("請輸入新的年齡: ");scanf("%d", &ps->age);getchar();printf("請輸入新的班級: ");scanf("%s", ps->className);getchar();printf("請輸入新的專業: ");scanf("%s", ps->major);getchar();printf("學生信息更新成功!\n");} else if (subChoice == 2) {// 編輯課題char tId[20];printf("請輸入要編輯的課題編號: ");scanf("%s", tId);getchar();int idx = findTopicIndexById(tId);if (idx == -1) {printf("未找到該編號的課題。\n");return;}
}
編輯信息模塊允許用戶更新學生或課題的相關信息,確保系統中的數據始終準確且與實際需求一致。該模塊通過唯一標識符(學生的學號或課題編號)檢索目標記錄,避免了對無關數據的誤操作。
功能邏輯設計分為兩部分:一是更新學生信息,包括姓名、性別、年齡、班級和專業;二是更新課題信息,包括課題名稱、預計人員數和指導教師。編輯功能在顯示原有信息的基礎上逐項更新,直觀地提示用戶輸入修改項,同時避免無意覆蓋。代碼清晰簡潔,便于擴展,如可增加對輸入數據的格式校驗或對特定字段的編輯權限控制,以進一步提升系統的安全性與魯棒性。
void saveToFile() {// 保存學生信息FILE *fpStu = fopen("students.txt", "w");if (fpStu == NULL) {printf("無法打開文件 students.txt 進行保存。\n");return;}for (int i = 0; i < g_studentCount; i++) {fprintf(fpStu, "%s %s %s %d %s %s %s\n",g_students[i].id, g_students[i].name, g_students[i].sex,g_students[i].age, g_students[i].className, g_students[i].major,g_students[i].chosenTopicId);}fclose(fpStu);// 保存課題信息//此處略去至少10行代碼printf("數據保存成功!\n");
}
保存信息模塊的主要作用是將內存中的學生和課題數據寫入到外部文件 (students.txt 和 topics.txt),以實現數據的持久化存儲。模塊通過文件流操作,將結構化數據逐行格式化輸出到文本文件中,每條記錄的字段按照固定順序排列,方便后續讀取和解析。
此功能確保系統在退出后仍能保留當前數據,便于下次啟動時加載,避免數據丟失。設計中對文件打開失敗進行了檢查,以防止文件系統錯誤引發的程序崩潰。同時,通過分別保存學生和課題信息,簡化了數據管理邏輯。未來可以進一步優化文件存儲格式,例如采用二進制文件以提高效率,或引入加密機制以保護敏感數據的安全性。
刪除信息代碼
void deleteRecord() {int subChoice;printf("\n--- 刪除記錄 ---\n");printf("1. 刪除學生\n");printf("2. 刪除課題\n");printf("請輸入選擇: ");scanf("%d", &subChoice);getchar();if (subChoice == 1) {// 刪除學生if (g_studentCount == 0) {printf("當前沒有學生記錄可刪除!\n");return;}char sId[20];printf("請輸入要刪除的學生學號: ");scanf("%s", sId);getchar();int idx = findStudentIndexById(sId);if (idx == -1) {printf("未找到該學號的學生。\n");return;}
}
刪除信息模塊實現了從系統中移除指定學生或課題記錄的功能。通過輸入學號或課題編號,系統定位到需要刪除的記錄,并采用覆蓋替換法刪除數據:將數組中最后一條記錄復制到目標位置,并減少記錄計數。這種方法避免了在數組中移動大量數據,提高了刪除操作的效率。
模塊設計簡潔且高效,適合小型數據管理需求。然而,刪除操作并未檢查學生與課題的關聯性,例如刪除課題前未驗證是否有學生選了該課題。未來可進一步優化邏輯,例如提示用戶刪除的潛在影響或通過鏈式存儲實現動態數據管理,提升系統的安全性和可維護性。
學生選題代碼
void chooseTopic() {// 輸入學生學號char sId[20];printf("請輸入學生學號: ");scanf("%s", sId);getchar();int studentIdx = findStudentIndexById(sId);if (studentIdx == -1) {printf("未找到該學號的學生。\n");return;}// 顯示當前可選課題printf("\n--- 可選課題列表 ---\n");for (int i = 0; i < g_topicCount; i++) {Topic t = g_topics[i];printf("編號:%s 名稱:%s 人數:%d 教師:%s\n", t.id, t.name, t.personCount, t.teacher);}// 輸入課題編號// ...................// 更新學生選題信息strcpy(g_students[studentIdx].chosenTopicId, tId);printf("學生 [%s] 成功選擇課題 [%s]。\n", g_students[studentIdx].name, tId);
}
學生選題模塊是系統中學生與課題之間的核心交互功能,允許學生通過輸入學號登錄并選擇課題。實現流程包括驗證學生身份、顯示當前可選課題、驗證課題編號有效性,并最終記錄學生的選題信息。系統還檢查學生是否已選課題,避免重復選題。
此模塊的設計簡單明了,易于擴展。例如,可進一步添加人數限制檢查,防止某一課題超額選題;也可以實現選題的撤銷或修改功能,增強用戶靈活性。選題模塊與學生和課題數據關聯密切,增強了系統功能的實用性和數據的可追溯性。
三、可視化分析