#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h>
#define MAX_STUDENTS 1000 #define MAX_NAME_LEN 50 #define MAX_COLLEGE_LEN 50 #define MAX_MAJOR_LEN 50 #define MAX_ID_LEN 20 #define MAX_SCORE_LEN 10 #define CSV_FILENAME "student_info.csv"
typedef struct { char id[MAX_ID_LEN]; char name[MAX_NAME_LEN]; char college[MAX_COLLEGE_LEN]; char major[MAX_MAJOR_LEN]; char chinese[MAX_SCORE_LEN]; char math[MAX_SCORE_LEN]; char english[MAX_SCORE_LEN]; char total[MAX_SCORE_LEN]; } Student;
typedef struct { Student* students; int size; int capacity; } StudentManager;
const char* HEADERS[] = {"学号", "姓名", "学院", "专业", "语文", "数学", "英语", "总分"};
void initStudentManager(StudentManager* manager); void freeStudentManager(StudentManager* manager); int isNumeric(const char* str); void loadFromCSV(StudentManager* manager); void autoSaveToCSV(StudentManager* manager); int validateScore(const char* score, const char* subject); void updateTotal(Student* s); int findById(StudentManager* manager, const char* id); int findByName(StudentManager* manager, const char* name); void addStudent(StudentManager* manager); void deleteStudent(StudentManager* manager); void modifyStudent(StudentManager* manager); void searchStudent(StudentManager* manager); void displayAll(StudentManager* manager); void displayHeader(); void displayStudent(Student* s); void sortById(StudentManager* manager); void sortByChinese(StudentManager* manager); void sortByMath(StudentManager* manager); void sortByEnglish(StudentManager* manager); void sortByTotal(StudentManager* manager); void calculateAverage(StudentManager* manager); void findExtremeValues(StudentManager* manager); void displayMenu(); void clearInputBuffer();
void initStudentManager(StudentManager* manager) { manager->capacity = 100; manager->size = 0; manager->students = (Student*)malloc(manager->capacity * sizeof(Student)); if (manager->students == NULL) { printf("内存分配失败!\n"); exit(1); } }
void freeStudentManager(StudentManager* manager) { free(manager->students); manager->students = NULL; manager->size = 0; manager->capacity = 0; }
int isNumeric(const char* str) { if (str == NULL || *str == '\0') return 0; int dotCount = 0; for (int i = 0; str[i] != '\0'; i++) { if (str[i] == '.') { dotCount++; if (dotCount > 1) return 0; } else if (!isdigit(str[i])) { return 0; } } return 1; }
void loadFromCSV(StudentManager* manager) { FILE* file = fopen(CSV_FILENAME, "r"); if (file == NULL) { printf("未找到CSV数据文件,将创建新文件。\n"); return; }
char line[1024]; fgets(line, sizeof(line), file);
while (fgets(line, sizeof(line), file)) { if (line[0] == '\0' || line[0] == '\n') continue;
char* tokens[8]; char* token = strtok(line, ","); int tokenCount = 0; while (token != NULL && tokenCount < 8) { tokens[tokenCount++] = token; token = strtok(NULL, ","); }
if (tokenCount >= 8) { if (manager->size >= manager->capacity) { manager->capacity *= 2; manager->students = (Student*)realloc(manager->students, manager->capacity * sizeof(Student)); if (manager->students == NULL) { printf("内存分配失败!\n"); fclose(file); return; } }
Student* s = &manager->students[manager->size]; strncpy(s->id, tokens[0], MAX_ID_LEN - 1); strncpy(s->name, tokens[1], MAX_NAME_LEN - 1); strncpy(s->college, tokens[2], MAX_COLLEGE_LEN - 1); strncpy(s->major, tokens[3], MAX_MAJOR_LEN - 1); strncpy(s->chinese, tokens[4], MAX_SCORE_LEN - 1); strncpy(s->math, tokens[5], MAX_SCORE_LEN - 1); strncpy(s->english, tokens[6], MAX_SCORE_LEN - 1); strncpy(s->total, tokens[7], MAX_SCORE_LEN - 1);
s->id[strcspn(s->id, "\n")] = 0; s->name[strcspn(s->name, "\n")] = 0; s->college[strcspn(s->college, "\n")] = 0; s->major[strcspn(s->major, "\n")] = 0; s->chinese[strcspn(s->chinese, "\n")] = 0; s->math[strcspn(s->math, "\n")] = 0; s->english[strcspn(s->english, "\n")] = 0; s->total[strcspn(s->total, "\n")] = 0;
if (!validateScore(s->chinese, "语文")) strcpy(s->chinese, "0.0"); if (!validateScore(s->math, "数学")) strcpy(s->math, "0.0"); if (!validateScore(s->english, "英语")) strcpy(s->english, "0.0"); updateTotal(s); manager->size++; } }
fclose(file); printf("CSV数据加载完成,共 %d 名学生。\n", manager->size); }
void autoSaveToCSV(StudentManager* manager) { FILE* file = fopen(CSV_FILENAME, "w"); if (file == NULL) { printf("CSV文件保存失败!\n"); return; }
for (int i = 0; i < 8; i++) { fprintf(file, "%s", HEADERS[i]); if (i < 7) fprintf(file, ","); } fprintf(file, "\n");
for (int i = 0; i < manager->size; i++) { Student* s = &manager->students[i]; fprintf(file, "%s,%s,%s,%s,%s,%s,%s,%s\n", s->id, s->name, s->college, s->major, s->chinese, s->math, s->english, s->total); }
fclose(file); }
int validateScore(const char* score, const char* subject) { if (!isNumeric(score)) { printf("错误:%s成绩必须是数字!请重新输入。\n", subject); return 0; } double scoreValue = atof(score); if (scoreValue < 0 || scoreValue > 100) { printf("错误:%s成绩必须在0-100之间!请重新输入。\n", subject); return 0; } return 1; }
void updateTotal(Student* s) { double chi = atof(s->chinese); double math = atof(s->math); double eng = atof(s->english); double total = chi + math + eng; snprintf(s->total, MAX_SCORE_LEN, "%.1f", total); }
int findById(StudentManager* manager, const char* id) { for (int i = 0; i < manager->size; i++) { if (strcmp(manager->students[i].id, id) == 0) { return i; } } return -1; }
int findByName(StudentManager* manager, const char* name) { for (int i = 0; i < manager->size; i++) { if (strcmp(manager->students[i].name, name) == 0) { return i; } } return -1; }
void addStudent(StudentManager* manager) { printf("\n===================== 添加学生 =====================\n"); if (manager->size >= manager->capacity) { manager->capacity *= 2; manager->students = (Student*)realloc(manager->students, manager->capacity * sizeof(Student)); if (manager->students == NULL) { printf("内存分配失败!\n"); return; } }
Student* s = &manager->students[manager->size]; while (1) { printf("请输入学号:"); scanf("%s", s->id); clearInputBuffer(); if (findById(manager, s->id) != -1) { printf("错误:该学号已存在!请重新输入。\n"); } else if (strlen(s->id) == 0) { printf("错误:学号不能为空!请重新输入。\n"); } else { break; } }
printf("请输入姓名:"); fgets(s->name, MAX_NAME_LEN, stdin); s->name[strcspn(s->name, "\n")] = 0; while (strlen(s->name) == 0) { printf("错误:姓名不能为空!请重新输入:"); fgets(s->name, MAX_NAME_LEN, stdin); s->name[strcspn(s->name, "\n")] = 0; }
printf("请输入学院:"); fgets(s->college, MAX_COLLEGE_LEN, stdin); s->college[strcspn(s->college, "\n")] = 0; while (strlen(s->college) == 0) { printf("错误:学院不能为空!请重新输入:"); fgets(s->college, MAX_COLLEGE_LEN, stdin); s->college[strcspn(s->college, "\n")] = 0; }
printf("请输入专业:"); fgets(s->major, MAX_MAJOR_LEN, stdin); s->major[strcspn(s->major, "\n")] = 0; while (strlen(s->major) == 0) { printf("错误:专业不能为空!请重新输入:"); fgets(s->major, MAX_MAJOR_LEN, stdin); s->major[strcspn(s->major, "\n")] = 0; }
while (1) { printf("请输入语文成绩:"); scanf("%s", s->chinese); clearInputBuffer(); if (validateScore(s->chinese, "语文")) break; }
while (1) { printf("请输入数学成绩:"); scanf("%s", s->math); clearInputBuffer(); if (validateScore(s->math, "数学")) break; }
while (1) { printf("请输入英语成绩:"); scanf("%s", s->english); clearInputBuffer(); if (validateScore(s->english, "英语")) break; }
updateTotal(s); manager->size++; autoSaveToCSV(manager); printf("\n✅ 学生添加成功!数据已保存到 %s\n", CSV_FILENAME); }
void deleteStudent(StudentManager* manager) { printf("\n===================== 删除学生 =====================\n"); if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
char input[100]; printf("请输入学号或姓名:"); scanf("%s", input); clearInputBuffer();
int index = isNumeric(input) ? findById(manager, input) : findByName(manager, input);
if (index == -1) { printf("错误:未找到该学生!\n"); return; }
printf("找到学生:\n"); displayHeader(); displayStudent(&manager->students[index]);
char confirm; printf("确定要删除吗?(y/n):"); scanf(" %c", &confirm); clearInputBuffer();
if (confirm == 'y' || confirm == 'Y') { for (int i = index; i < manager->size - 1; i++) { manager->students[i] = manager->students[i + 1]; } manager->size--; autoSaveToCSV(manager); printf("\n✅ 学生删除成功!数据已保存到 %s\n", CSV_FILENAME); } else { printf("❌ 删除操作已取消\n"); } }
void modifyStudent(StudentManager* manager) { printf("\n===================== 修改学生 =====================\n"); if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
char input[100]; printf("请输入学号或姓名:"); scanf("%s", input); clearInputBuffer();
int index = isNumeric(input) ? findById(manager, input) : findByName(manager, input);
if (index == -1) { printf("错误:未找到该学生!\n"); return; }
Student* s = &manager->students[index]; printf("当前学生信息:\n"); displayHeader(); displayStudent(s);
printf("\n请选择要修改的项目:\n"); printf("1. 学院\n"); printf("2. 专业\n"); printf("3. 语文成绩\n"); printf("4. 数学成绩\n"); printf("5. 英语成绩\n"); printf("6. 取消修改\n"); printf("请选择(1-6):");
int choice; scanf("%d", &choice); clearInputBuffer();
switch (choice) { case 1: printf("请输入新的学院:"); fgets(s->college, MAX_COLLEGE_LEN, stdin); s->college[strcspn(s->college, "\n")] = 0; while (strlen(s->college) == 0) { printf("错误:学院不能为空!请重新输入:"); fgets(s->college, MAX_COLLEGE_LEN, stdin); s->college[strcspn(s->college, "\n")] = 0; } break; case 2: printf("请输入新的专业:"); fgets(s->major, MAX_MAJOR_LEN, stdin); s->major[strcspn(s->major, "\n")] = 0; while (strlen(s->major) == 0) { printf("错误:专业不能为空!请重新输入:"); fgets(s->major, MAX_MAJOR_LEN, stdin); s->major[strcspn(s->major, "\n")] = 0; } break; case 3: while (1) { printf("请输入新的语文成绩:"); scanf("%s", s->chinese); clearInputBuffer(); if (validateScore(s->chinese, "语文")) { updateTotal(s); break; } } break; case 4: while (1) { printf("请输入新的数学成绩:"); scanf("%s", s->math); clearInputBuffer(); if (validateScore(s->math, "数学")) { updateTotal(s); break; } } break; case 5: while (1) { printf("请输入新的英语成绩:"); scanf("%s", s->english); clearInputBuffer(); if (validateScore(s->english, "英语")) { updateTotal(s); break; } } break; case 6: printf("❌ 修改操作已取消\n"); return; default: printf("错误:无效选择!\n"); return; }
autoSaveToCSV(manager); printf("\n✅ 学生信息修改成功!数据已保存到 %s\n", CSV_FILENAME); printf("修改后的信息:\n"); displayHeader(); displayStudent(s); }
void searchStudent(StudentManager* manager) { printf("\n===================== 查找学生 =====================\n"); if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
char input[100]; printf("请输入学号或姓名:"); scanf("%s", input); clearInputBuffer();
int index = isNumeric(input) ? findById(manager, input) : findByName(manager, input);
if (index == -1) { printf("错误:未找到该学生!\n"); return; }
printf("✅ 找到学生:\n"); displayHeader(); displayStudent(&manager->students[index]); }
void displayAll(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
printf("\n===================== 所有学生信息 (%d 名) =====================\n", manager->size); displayHeader(); for (int i = 0; i < manager->size; i++) { displayStudent(&manager->students[i]); } printf("==========================================================================\n"); }
void displayHeader() { printf("%-10s%-20s%-30s%-30s%-10s%-10s%-10s%-10s\n", HEADERS[0], HEADERS[1], HEADERS[2], HEADERS[3], HEADERS[4], HEADERS[5], HEADERS[6], HEADERS[7]); printf("----------------------------------------------------------------------------------------------------\n"); }
void displayStudent(Student* s) { printf("%-10s%-20s%-30s%-30s%-10s%-10s%-10s%-10s\n", s->id, s->name, s->college, s->major, s->chinese, s->math, s->english, s->total); }
int compareById(const void* a, const void* b) { const Student* s1 = (const Student*)a; const Student* s2 = (const Student*)b; int len1 = strlen(s1->id); int len2 = strlen(s2->id); if (len1 != len2) return len1 - len2; return strcmp(s1->id, s2->id); }
int compareByChinese(const void* a, const void* b) { const Student* s1 = (const Student*)a; const Student* s2 = (const Student*)b; double score1 = atof(s1->chinese); double score2 = atof(s2->chinese); return (score2 > score1) ? 1 : (score2 < score1) ? -1 : 0; }
int compareByMath(const void* a, const void* b) { const Student* s1 = (const Student*)a; const Student* s2 = (const Student*)b; double score1 = atof(s1->math); double score2 = atof(s2->math); return (score2 > score1) ? 1 : (score2 < score1) ? -1 : 0; }
int compareByEnglish(const void* a, const void* b) { const Student* s1 = (const Student*)a; const Student* s2 = (const Student*)b; double score1 = atof(s1->english); double score2 = atof(s2->english); return (score2 > score1) ? 1 : (score2 < score1) ? -1 : 0; }
int compareByTotal(const void* a, const void* b) { const Student* s1 = (const Student*)a; const Student* s2 = (const Student*)b; double score1 = atof(s1->total); double score2 = atof(s2->total); return (score2 > score1) ? 1 : (score2 < score1) ? -1 : 0; }
void sortById(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据可排序!\n"); return; } qsort(manager->students, manager->size, sizeof(Student), compareById); autoSaveToCSV(manager); printf("\n✅ 已按学号升序排序!数据已保存到 %s\n", CSV_FILENAME); }
void sortByChinese(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据可排序!\n"); return; } qsort(manager->students, manager->size, sizeof(Student), compareByChinese); autoSaveToCSV(manager); printf("\n✅ 已按语文成绩降序排序!数据已保存到 %s\n", CSV_FILENAME); }
void sortByMath(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据可排序!\n"); return; } qsort(manager->students, manager->size, sizeof(Student), compareByMath); autoSaveToCSV(manager); printf("\n✅ 已按数学成绩降序排序!数据已保存到 %s\n", CSV_FILENAME); }
void sortByEnglish(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据可排序!\n"); return; } qsort(manager->students, manager->size, sizeof(Student), compareByEnglish); autoSaveToCSV(manager); printf("\n✅ 已按英语成绩降序排序!数据已保存到 %s\n", CSV_FILENAME); }
void sortByTotal(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据可排序!\n"); return; } qsort(manager->students, manager->size, sizeof(Student), compareByTotal); autoSaveToCSV(manager); printf("\n✅ 已按总分降序排序!数据已保存到 %s\n", CSV_FILENAME); }
void calculateAverage(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
double chiTotal = 0.0, mathTotal = 0.0, engTotal = 0.0, totalTotal = 0.0; int validCount = 0;
for (int i = 0; i < manager->size; i++) { Student* s = &manager->students[i]; chiTotal += atof(s->chinese); mathTotal += atof(s->math); engTotal += atof(s->english); totalTotal += atof(s->total); validCount++; }
if (validCount == 0) { printf("错误:没有有效的成绩数据可计算!\n"); return; }
printf("\n===================== 成绩平均分 =====================\n"); printf("语文平均分:%.2f\n", chiTotal / validCount); printf("数学平均分:%.2f\n", mathTotal / validCount); printf("英语平均分:%.2f\n", engTotal / validCount); printf("总分平均分:%.2f\n", totalTotal / validCount); }
void findExtremeValues(StudentManager* manager) { if (manager->size == 0) { printf("提示:当前没有学生数据!\n"); return; }
int chiMinIndex = 0, chiMaxIndex = 0; int mathMinIndex = 0, mathMaxIndex = 0; int engMinIndex = 0, engMaxIndex = 0; int totalMinIndex = 0, totalMaxIndex = 0;
for (int i = 1; i < manager->size; i++) { Student* current = &manager->students[i]; if (atof(current->chinese) < atof(manager->students[chiMinIndex].chinese)) chiMinIndex = i; if (atof(current->chinese) > atof(manager->students[chiMaxIndex].chinese)) chiMaxIndex = i; if (atof(current->math) < atof(manager->students[mathMinIndex].math)) mathMinIndex = i; if (atof(current->math) > atof(manager->students[mathMaxIndex].math)) mathMaxIndex = i; if (atof(current->english) < atof(manager->students[engMinIndex].english)) engMinIndex = i; if (atof(current->english) > atof(manager->students[engMaxIndex].english)) engMaxIndex = i; if (atof(current->total) < atof(manager->students[totalMinIndex].total)) totalMinIndex = i; if (atof(current->total) > atof(manager->students[totalMaxIndex].total)) totalMaxIndex = i; }
printf("\n===================== 成绩极值 =====================\n"); printf("语文最低分:%s (学号:%s,姓名:%s)\n", manager->students[chiMinIndex].chinese, manager->students[chiMinIndex].id, manager->students[chiMinIndex].name); printf("语文最高分:%s (学号:%s,姓名:%s)\n", manager->students[chiMaxIndex].chinese, manager->students[chiMaxIndex].id, manager->students[chiMaxIndex].name); printf("数学最低分:%s (学号:%s,姓名:%s)\n", manager->students[mathMinIndex].math, manager->students[mathMinIndex].id, manager->students[mathMinIndex].name); printf("数学最高分:%s (学号:%s,姓名:%s)\n", manager->students[mathMaxIndex].math, manager->students[mathMaxIndex].id, manager->students[mathMaxIndex].name); printf("英语最低分:%s (学号:%s,姓名:%s)\n", manager->students[engMinIndex].english, manager->students[engMinIndex].id, manager->students[engMinIndex].name); printf("英语最高分:%s (学号:%s,姓名:%s)\n", manager->students[engMaxIndex].english, manager->students[engMaxIndex].id, manager->students[engMaxIndex].name); printf("总分最低分:%s (学号:%s,姓名:%s)\n", manager->students[totalMinIndex].total, manager->students[totalMinIndex].id, manager->students[totalMinIndex].name); printf("总分最高分:%s (学号:%s,姓名:%s)\n", manager->students[totalMaxIndex].total, manager->students[totalMaxIndex].id, manager->students[totalMaxIndex].name); }
void displayMenu() { printf("\n==========================================================\n"); printf(" 学生信息管理系统 \n"); printf("==========================================================\n"); printf("1. 添加学生 2. 删除学生 3. 修改学生\n"); printf("4. 查找学生 5. 显示所有 6. 按学号排序\n"); printf("7. 按语文排序 8. 按数学排序 9. 按英语排序\n"); printf("10. 按总分排序 11. 计算平均分 12. 查找极值\n"); printf(" 14. 退出系统 \n"); printf("==========================================================\n"); printf("提示:数据存储在 %s,支持Excel直接打开\n", CSV_FILENAME); printf("请选择功能(1-14):"); }
void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF); }
int main() { StudentManager manager; initStudentManager(&manager); printf("正在加载CSV学生数据...\n"); loadFromCSV(&manager);
int choice = 0; do { displayMenu();
if (scanf("%d", &choice) != 1) { clearInputBuffer(); printf("\n❌ 错误:输入无效!请输入数字1-14。\n"); continue; }
clearInputBuffer();
switch (choice) { case 1: addStudent(&manager); break; case 2: deleteStudent(&manager); break; case 3: modifyStudent(&manager); break; case 4: searchStudent(&manager); break; case 5: displayAll(&manager); break; case 6: sortById(&manager); break; case 7: sortByChinese(&manager); break; case 8: sortByMath(&manager); break; case 9: sortByEnglish(&manager); break; case 10: sortByTotal(&manager); break; case 11: calculateAverage(&manager); break; case 12: findExtremeValues(&manager); break; case 13: printf("\n✅ 感谢使用学生信息管理系统!数据已保存到 %s\n", CSV_FILENAME); break; default: printf("\n❌ 错误:选择无效!请输入1-14之间的数字。\n"); }
if (choice != 14) { printf("\n按Enter键继续..."); getchar(); }
} while (choice != 14);
freeStudentManager(&manager); return 0; }
|