C语言编写课程管理系统
- 1 需求分析
- 2 需要查的知识点
- 3 数据结构和基础函数功能
- 3.1 课程数据结构
- 3.2 菜单和选择项
- 3.3 从文件中加载课程信息到内存
- 3.4 将内存中的课程信息保存到文件
- 3.5 将输入的字符串格式化为课程信息结构体
- 4 主要功能函数
- 4.1 录入课程信息函数
- 4.2 浏览课程信息函数
- 4.3 查询课程信息函数
- 4.4 修改课程信息函数
- 4.5 删除课程信息函数
- 4.6 排序课程信息函数
- !!!修改课程信息的函数有bug !!!
- 5 完整代码块
- 5.1 CourseManagement.h
- 5.2 CourseManagement.c
- 5.3 Test.c
着急交作业的同学可以直接跳跃到 5 完整代码块
1 需求分析
课程管理系统
某校对所开设课程进行管理,每门课程有:课程编号,课程名称,课程性质(公共课、必修课、选修课),总学时,授课学时,实验学时,学分,开课学期等信息。
试设计一课程管理系统,使之能提供以下功能:
(1)系统以菜单方式工作;
(2)课程信息录入功能;
(3)课程信息浏览功能;
(4)课程信息查询功能:
- 提供两种不同的查询方式:
- 按学分查询
- 按课程性质查询;
(5)将满足某种条件的课程停开并将其删除
- 按照课程编号删除
- 课程名称删除;
(6)按照开课学期进行排序(可用典型的冒泡排序);
可适当增加或删除功能
大一C语言小组作业的一道选题
结合需求,分析所学习的知识:
结构体 函数 指针 文件操作
编译环境:VS2019
使用C语言完成,不需要数据结构的知识
2 需要查的知识点
1 课程的数据结构全部设置为char类型。在后续编写程序%s
,不会那么容易写错。
2 strcmp函数是C语言中的字符串比较函数,用于比较两个字符串的大小。
3 课本上文件流操作的知识点
4 删除课程使用的C语言rename()函数:重命名文件或目录。使用临时文件temp.txt
使逻辑缜密
5 对字符串冒泡排序,使用atoi():int atoi(const char *str );功能:把字符串转换成整型数。str:要进行转换的字符串
3 数据结构和基础函数功能
3.1 课程数据结构
每门课程有:课程编号,课程名称,课程性质(公共课、必修课、选修课),总学时,授课学时,实验学时,学分,开课学期等信息。
// 定义课程结构体
// 为了测试方便,都设置char类型
struct Course{char number[20]; // 课程编号char name[50]; // 课程名称char type[10]; // 课程性质(如必修、选修)char totalHours[20]; // 总学时char experimentHours[20]; // 实验学时char lectureHours[20]; // 授课学时char credits[10]; // 学分char semester[20]; // 开课学期,开课学期中大一上为1,大一下为2,大二上为3依次递推
};
3.2 菜单和选择项
// 打印主菜单函数
void PrintMenu()
{printf(" *****课程管理系统***** \n");// 打印系统名称printf("* 1.录入课程信息 *\n");// 选项1:录入课程信息printf("* 2.课程信息浏览 *\n");// 选项2:浏览课程信息printf("* 3.课程信息查询 *\n");// 选项3:查询课程信息printf("* 4.课程信息修改 *\n");// 选项4:修改课程信息printf("* 5.删除课程信息 *\n");// 选项5:删除课程信息printf("* 6.课程信息排序 *\n");// 选项6:对课程信息进行排序printf("* 0.退出课程系统 *\n");// 选项0:退出系统printf("请选择操作:\n");// 提示用户选择操作
}// 根据用户选择执行不同的操作函数
void Menu(int choice)
{switch (choice) {case 1:AddCourses();// 执行录入课程信息操作break;case 2:BrowseCourses();// 执行浏览课程信息操作break;case 3:QueryCourses();// 执行查询课程信息操作break;case 4:ModifyCourses();// 执行修改课程信息操作break;case 5:DeleteCourses();// 执行删除课程信息操作break;case 6:SortCourses();// 执行对课程信息进行排序操作break;default:// 处理无效选择的情况,例如显示错误消息printf("无效的选择,请输入1到6之间的数字。\n");break;}
}
3.3 从文件中加载课程信息到内存
// 从文件中加载课程信息到内存
void LoadData(struct Course* courses, int* count)
{FILE* fp = fopen("./课程管理系统.txt", "r");// 打开名为课程管理系统.txt的文件以供读取if (fp == NULL) {printf("无法打开文件\n");// 如果文件打开失败,则输出错误信息return;}int i = 0;// 逐行读取文件中的课程信息,直到文件末尾// 将每行数据解析并存储到课程信息结构体数组中while (fscanf(fp, "%s %s %s %s %s %s %s %s", courses[i].number, courses[i].name,courses[i].type, courses[i].totalHours, courses[i].experimentHours,courses[i].lectureHours, courses[i].credits, courses[i].semester) == 8) {i++;// 每成功读取一行,课程数量加1}*count = i;// 更新课程数量fclose(fp);// 关闭文件
}
3.4 将内存中的课程信息保存到文件
// 将内存中的课程信息保存到文件
void SaveData(struct Course* courses, int count)
{FILE* fp = fopen("./课程管理系统.txt", "w");// 打开名为课程管理系统.txt的文件以供写入if (fp == NULL) {printf("无法打开文件以写入\n");// 如果文件打开失败,则输出错误信息return;}int i = 0;for (i = 0; i < count; i++) {fprintf(fp, "%s %s %s %s %s %s %s %s\n", courses[i].number, courses[i].name,courses[i].type, courses[i].totalHours, courses[i].experimentHours,courses[i].lectureHours, courses[i].credits, courses[i].semester);// 将每门课程的信息按指定格式写入文件}fclose(fp);// 关闭文件
}
3.5 将输入的字符串格式化为课程信息结构体
// 将输入的字符串格式化为课程信息结构体
void ChangeDataFormat(char* input, struct Course* course)
{sscanf(input, "%s %s %s %s %s %s %s %s",course->number, course->name, course->type,course->totalHours, course->experimentHours,course->lectureHours, course->credits, course->semester);}
4 主要功能函数
4.1 录入课程信息函数
// 录入课程信息函数
void AddCourses()
{int n;FILE* fp;printf("请输入要录入的课程数量:\n");scanf("%d", &n);printf("请输入课程信息:\n");printf("格式如下:001 c语言 必修 10 2 3 4.5 1\n");printf("编号、名称、性质、总学时、实验学时、授课学时、学分、开课学期\n");printf("(开课学期中大一上为1,大一下为2,大二上为3依次递推)\n");struct Course x;int i = 0;for (i = 0; i < n; i++) {getchar(); // 消耗掉输入缓冲中的换行符printf("请输入第 %d 门课程的信息:\n", i + 1);printf("课程编号: ");scanf("%s", x.number);printf("课程名称: ");scanf("%s", x.name);printf("课程性质: ");scanf("%s", x.type);printf("总学时: ");scanf("%s", x.totalHours);printf("实验学时: ");scanf("%s", x.experimentHours);printf("授课学时: ");scanf("%s", x.lectureHours);printf("学分: ");scanf("%s", x.credits);printf("开课学期: ");scanf("%s", x.semester);fp = fopen("./课程管理系统.txt", "a");fprintf(fp, "%s %s %s %s %s %s %s %s\n", x.number, x.name, x.type,x.totalHours, x.experimentHours, x.lectureHours, x.credits,x.semester);fclose(fp);printf("第 %d 门课程信息已录入\n", i + 1);}
}
4.2 浏览课程信息函数
// 浏览课程信息函数
void BrowseCourses()
{FILE* fp;struct Course course;fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}// 打印表头printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");// 逐行读取文件中的课程信息,并按指定格式打印输出while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 打印每门课程的信息}fclose(fp); // 关闭文件
}
4.3 查询课程信息函数
// 查询课程信息函数
void QueryCourses()
{int choice;printf("1.按学分查询\n"); // 显示按学分查询的选项printf("2.按课程性质查询\n"); // 显示按课程性质查询的选项printf("请选择查询方式:"); // 提示用户选择查询方式scanf("%d", &choice); // 读取用户选择的查询方式if (choice == 1) {char credits[10];printf("请输入要查询的学分数:"); // 提示用户输入要查询的学分数scanf("%s", credits); // 读取用户输入的学分数FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;bool found = false;while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.credits, credits) == 0) { // 如果课程的学分与用户输入的学分匹配if (!found) {printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");found = true;}printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 输出符合条件的课程信息}}if (!found) {printf("未找到符合条件的课程\n"); // 若未找到符合条件的课程,则提示用户未找到}fclose(fp); // 关闭文件}else if (choice == 2) {char type[10];printf("请输入要查询的课程性质:"); // 提示用户输入要查询的课程性质scanf("%s", type); // 读取用户输入的课程性质FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;bool found = false;while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.type, type) == 0) { // 如果课程的性质与用户输入的性质匹配if (!found) {printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");found = true;}// 输出符合条件的课程信息printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester);}}if (!found) {printf("未找到符合条件的课程\n"); // 若未找到符合条件的课程,则提示用户未找到}fclose(fp); // 关闭文件}else {printf("无效的选择,请选择1或2\n"); // 如果选择无效,则提示用户重新选择}
}
4.4 修改课程信息函数
void ModifyCourses()
{char cnt[20];printf("请输入要修改的课程编号: ");scanf("%s", cnt); // 读取用户输入的要修改的课程编号FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;long int position = 0;bool found = false;// 遍历文件中的课程信息,查找要修改的课程while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.number, cnt) == 0) { // 如果找到要修改的课程found = true;break;}position = ftell(fp); // 记录当前位置}fclose(fp); // 关闭文件if (found) {// 输出当前课程信息printf("当前课程信息:\n");printf("课程编号: %s\n", course.number);printf("课程名称: %s\n", course.name);printf("课程性质: %s\n", course.type);printf("总学时: %s\n", course.totalHours);printf("实验学时: %s\n", course.experimentHours);printf("授课学时: %s\n", course.lectureHours);printf("学分: %s\n", course.credits);printf("开课学期: %s\n", course.semester);// 读取新的课程信息struct Course newCourse;printf("请输入新的课程信息:\n");printf("课程名称: ");scanf("%s", newCourse.name);printf("课程性质: ");scanf("%s", newCourse.type);printf("总学时: ");scanf("%s", newCourse.totalHours);printf("实验学时: ");scanf("%s", newCourse.experimentHours);printf("授课学时: ");scanf("%s", newCourse.lectureHours);printf("学分: ");scanf("%s", newCourse.credits);printf("开课学期: ");scanf("%s", newCourse.semester);FILE* fp = fopen("./课程管理系统.txt", "r+"); // 以读写模式打开文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}// 定位到要修改的课程信息的位置,并将新的课程信息写入文件fseek(fp, position, SEEK_SET);fprintf(fp, "%s %s %s %s %s %s %s %s\n", newCourse.number, newCourse.name,newCourse.type, newCourse.totalHours, newCourse.experimentHours,newCourse.lectureHours, newCourse.credits, newCourse.semester);fclose(fp); // 关闭文件printf("课程信息已成功更新!\n"); // 输出课程信息已成功更新的消息}else {printf("未找到课程编号: %s\n", cnt); // 若未找到要修改的课程,则输出未找到的消息}BrowseCourses();
}
4.5 删除课程信息函数
// 删除课程信息函数
void DeleteCourses()
{int option;printf("1.删除相同课程编号的课程\n"); // 显示删除相同课程编号的选项printf("2.删除相同课程名称的课程\n"); // 显示删除相同课程名称的选项printf("请选择删除方式:"); // 提示用户选择删除方式scanf("%d", &option); // 读取用户选择的删除方式if (option == 1 || option == 2) {char key[20];printf("请输入要删除的课程标识:"); // 提示用户输入要删除的课程标识scanf("%s", key); // 读取用户输入的课程标识FILE* inputFile = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (inputFile == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}FILE* outputFile = fopen("temp.txt", "w"); // 以写入模式创建一个临时文件temp.txtif (outputFile == NULL) {printf("无法创建临时文件\n"); // 如果创建临时文件失败,则输出错误信息fclose(inputFile);return;}// 遍历文件并删除匹配的课程信息struct Course course;bool found = false;while (fscanf(inputFile, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if ((option == 1 && strcmp(course.number, key) == 0) ||(option == 2 && strcmp(course.name, key) == 0)) {found = true;continue; // 不写入到输出文件,相当于删除}fprintf(outputFile, "%s %s %s %s %s %s %s %s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 将未匹配的课程信息写入输出文件}fclose(inputFile); // 关闭输入文件fclose(outputFile); // 关闭输出文件if (found) {remove("课程管理系统.txt"); // 删除原文件rename("temp.txt", "课程管理系统.txt"); // 重命名临时文件为原文件名printf("课程信息已成功删除!\n"); // 输出课程信息已成功删除的消息}else {remove("temp.txt"); // 删除临时文件printf("未找到要删除的课程信息\n"); // 若未找到要删除的课程,则输出未找到的消息}}else {printf("无效的选择,请选择1或2\n"); // 如果选择无效,则输出提示消息}BrowseCourses();
}
4.6 排序课程信息函数
// 按开课学期对课程信息进行排序的函数
void SortCourses()
{struct Course courses[100];int count = 0;LoadData(courses, &count); // 从文件中加载课程信息// 使用冒泡排序按开课学期进行排序int i, j;for (i = 0; i < count - 1; i++) {for (j = 0; j < count - i - 1; j++) {// 将开课学期转换为整数进行比较int semester1 = atoi(courses[j].semester);int semester2 = atoi(courses[j + 1].semester);if (semester1 > semester2) {struct Course temp = courses[j];courses[j] = courses[j + 1];courses[j + 1] = temp;}}}// 保存排序后的课程信息到文件SaveData(courses, count);printf("课程信息已按开课学期排序!\n");BrowseCourses();
}
001 C 必修 10 2 3 4 1
002 数学 必修 45 3 3 3 3
010 高数 选修 6 6 6 6 6
!!!修改课程信息的函数有bug !!!
额,不知道怎么解决了,有点头疼。可以直接把这个功能注释掉。
或者不用管他,但是不使用4 修改课程信息,坦诚地对老师说这个功能没有实现。
需求分析里面是没写修改功能。
笔者写了也没有写出来。实在头疼。
老是错位一行,不知道如何处理。
目前这个bug十分严重,建议不使用这个函数,放置着做摆设。
但是修改第一行的数据没有问题。
5 完整代码块
5.1 CourseManagement.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdbool.h>// 定义课程结构体
// 为了测试方便,都设置char类型
struct Course{char number[20]; // 课程编号char name[50]; // 课程名称char type[10]; // 课程性质(如必修、选修)char totalHours[20]; // 总学时char experimentHours[20]; // 实验学时char lectureHours[20]; // 授课学时char credits[10]; // 学分char semester[20]; // 开课学期,开课学期中大一上为1,大一下为2,大二上为3依次递推
};// 打印主菜单函数
void PrintMenu();
// 根据用户选择执行不同的操作函数
void Menu(int choice);// 从文件中加载课程信息到内存
void LoadData(struct Course* courses, int* count);// 将内存中的课程信息保存到文件
void SaveData(struct Course* courses, int count);// 将输入的字符串格式化为课程信息结构体
void ChangeDataFormat(char* input, struct Course* course);
// 录入课程信息函数
void AddCourses();// 浏览课程信息函数
void BrowseCourses();// 查询课程信息函数
void QueryCourses();// 修改课程信息函数
void ModifyCourses();// 删除课程信息函数
void DeleteCourses();// 按课程编号对课程信息进行排序的函数
void SortCourses();
5.2 CourseManagement.c
#include "CourseManagement.h" // 打印主菜单函数
void PrintMenu()
{printf(" *****课程管理系统***** \n");// 打印系统名称printf("* 1.录入课程信息 *\n");// 选项1:录入课程信息printf("* 2.课程信息浏览 *\n");// 选项2:浏览课程信息printf("* 3.课程信息查询 *\n");// 选项3:查询课程信息printf("* 4.课程信息修改 *\n");// 选项4:修改课程信息printf("* 5.删除课程信息 *\n");// 选项5:删除课程信息printf("* 6.课程信息排序 *\n");// 选项6:对课程信息进行排序printf("* 0.退出课程系统 *\n");// 选项0:退出系统printf("请选择操作:\n");// 提示用户选择操作
}// 根据用户选择执行不同的操作函数
void Menu(int choice)
{switch (choice) {case 1:AddCourses();// 执行录入课程信息操作break;case 2:BrowseCourses();// 执行浏览课程信息操作break;case 3:QueryCourses();// 执行查询课程信息操作break;case 4:ModifyCourses();// 执行修改课程信息操作break;case 5:DeleteCourses();// 执行删除课程信息操作break;case 6:SortCourses();// 执行对课程信息进行排序操作break;default:// 处理无效选择的情况,例如显示错误消息printf("无效的选择,请输入1到6之间的数字。\n");break;}
}// 从文件中加载课程信息到内存
void LoadData(struct Course* courses, int* count)
{FILE* fp = fopen("./课程管理系统.txt", "r");// 打开名为课程管理系统.txt的文件以供读取if (fp == NULL) {printf("无法打开文件\n");// 如果文件打开失败,则输出错误信息return;}int i = 0;// 逐行读取文件中的课程信息,直到文件末尾// 将每行数据解析并存储到课程信息结构体数组中while (fscanf(fp, "%s %s %s %s %s %s %s %s", courses[i].number, courses[i].name,courses[i].type, courses[i].totalHours, courses[i].experimentHours,courses[i].lectureHours, courses[i].credits, courses[i].semester) == 8) {i++;// 每成功读取一行,课程数量加1}*count = i;// 更新课程数量fclose(fp);// 关闭文件
}// 将内存中的课程信息保存到文件
void SaveData(struct Course* courses, int count)
{FILE* fp = fopen("./课程管理系统.txt", "w");// 打开名为课程管理系统.txt的文件以供写入if (fp == NULL) {printf("无法打开文件以写入\n");// 如果文件打开失败,则输出错误信息return;}int i = 0;for (i = 0; i < count; i++) {fprintf(fp, "%s %s %s %s %s %s %s %s\n", courses[i].number, courses[i].name,courses[i].type, courses[i].totalHours, courses[i].experimentHours,courses[i].lectureHours, courses[i].credits, courses[i].semester);// 将每门课程的信息按指定格式写入文件}fclose(fp);// 关闭文件
}// 将输入的字符串格式化为课程信息结构体
void ChangeDataFormat(char* input, struct Course* course)
{sscanf(input, "%s %s %s %s %s %s %s %s",course->number, course->name, course->type,course->totalHours, course->experimentHours,course->lectureHours, course->credits, course->semester);}// 录入课程信息函数
void AddCourses()
{int n;FILE* fp;printf("请输入要录入的课程数量:\n");scanf("%d", &n);printf("请输入课程信息:\n");printf("格式如下:001 c语言 必修 10 2 3 4.5 1\n");printf("编号、名称、性质、总学时、实验学时、授课学时、学分、开课学期\n");printf("(开课学期中大一上为1,大一下为2,大二上为3依次递推)\n");struct Course x;int i = 0;for (i = 0; i < n; i++) {getchar(); // 消耗掉输入缓冲中的换行符printf("请输入第 %d 门课程的信息:\n", i + 1);printf("课程编号: ");scanf("%s", x.number);printf("课程名称: ");scanf("%s", x.name);printf("课程性质: ");scanf("%s", x.type);printf("总学时: ");scanf("%s", x.totalHours);printf("实验学时: ");scanf("%s", x.experimentHours);printf("授课学时: ");scanf("%s", x.lectureHours);printf("学分: ");scanf("%s", x.credits);printf("开课学期: ");scanf("%s", x.semester);fp = fopen("./课程管理系统.txt", "a");fprintf(fp, "%s %s %s %s %s %s %s %s\n", x.number, x.name, x.type,x.totalHours, x.experimentHours, x.lectureHours, x.credits,x.semester);fclose(fp);printf("第 %d 门课程信息已录入\n", i + 1);}
}// 浏览课程信息函数
void BrowseCourses()
{FILE* fp;struct Course course;fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}// 打印表头printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");// 逐行读取文件中的课程信息,并按指定格式打印输出while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 打印每门课程的信息}fclose(fp); // 关闭文件
}// 查询课程信息函数
void QueryCourses()
{int choice;printf("1.按学分查询\n"); // 显示按学分查询的选项printf("2.按课程性质查询\n"); // 显示按课程性质查询的选项printf("请选择查询方式:"); // 提示用户选择查询方式scanf("%d", &choice); // 读取用户选择的查询方式if (choice == 1) {char credits[10];printf("请输入要查询的学分数:"); // 提示用户输入要查询的学分数scanf("%s", credits); // 读取用户输入的学分数FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;bool found = false;while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.credits, credits) == 0) { // 如果课程的学分与用户输入的学分匹配if (!found) {printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");found = true;}printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 输出符合条件的课程信息}}if (!found) {printf("未找到符合条件的课程\n"); // 若未找到符合条件的课程,则提示用户未找到}fclose(fp); // 关闭文件}else if (choice == 2) {char type[10];printf("请输入要查询的课程性质:"); // 提示用户输入要查询的课程性质scanf("%s", type); // 读取用户输入的课程性质FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;bool found = false;while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.type, type) == 0) { // 如果课程的性质与用户输入的性质匹配if (!found) {printf("课程编号 课程名称 课程性质 总学时 实验学时 授课学时 学分 开课学期\n");found = true;}// 输出符合条件的课程信息printf("%-8s %-8s %-8s %-6s %-8s %-8s %-4s %-8s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester);}}if (!found) {printf("未找到符合条件的课程\n"); // 若未找到符合条件的课程,则提示用户未找到}fclose(fp); // 关闭文件}else {printf("无效的选择,请选择1或2\n"); // 如果选择无效,则提示用户重新选择}
}// 修改课程信息函数
void ModifyCourses()
{char cnt[20];printf("请输入要修改的课程编号: ");scanf("%s", cnt); // 读取用户输入的要修改的课程编号FILE* fp = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}struct Course course;long int position = 0;bool found = false;// 遍历文件中的课程信息,查找要修改的课程while (fscanf(fp, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if (strcmp(course.number, cnt) == 0) { // 如果找到要修改的课程found = true;break;}position = ftell(fp); // 记录当前位置}fclose(fp); // 关闭文件if (found) {// 输出当前课程信息printf("当前课程信息:\n");printf("课程编号: %s\n", course.number);printf("课程名称: %s\n", course.name);printf("课程性质: %s\n", course.type);printf("总学时: %s\n", course.totalHours);printf("实验学时: %s\n", course.experimentHours);printf("授课学时: %s\n", course.lectureHours);printf("学分: %s\n", course.credits);printf("开课学期: %s\n", course.semester);// 读取新的课程信息struct Course newCourse;printf("请输入新的课程信息:\n");printf("课程名称: ");scanf("%s", newCourse.name);printf("课程性质: ");scanf("%s", newCourse.type);printf("总学时: ");scanf("%s", newCourse.totalHours);printf("实验学时: ");scanf("%s", newCourse.experimentHours);printf("授课学时: ");scanf("%s", newCourse.lectureHours);printf("学分: ");scanf("%s", newCourse.credits);printf("开课学期: ");scanf("%s", newCourse.semester);FILE* fp = fopen("./课程管理系统.txt", "r+"); // 以读写模式打开文件if (fp == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}// 定位到要修改的课程信息的位置,并将新的课程信息写入文件fseek(fp, position, SEEK_SET);fprintf(fp, "%s %s %s %s %s %s %s %s\n", newCourse.number, newCourse.name,newCourse.type, newCourse.totalHours, newCourse.experimentHours,newCourse.lectureHours, newCourse.credits, newCourse.semester);fclose(fp); // 关闭文件printf("课程信息已成功更新!\n"); // 输出课程信息已成功更新的消息}else {printf("未找到课程编号: %s\n", cnt); // 若未找到要修改的课程,则输出未找到的消息}BrowseCourses();
}// 删除课程信息函数
void DeleteCourses()
{int option;printf("1.删除相同课程编号的课程\n"); // 显示删除相同课程编号的选项printf("2.删除相同课程名称的课程\n"); // 显示删除相同课程名称的选项printf("请选择删除方式:"); // 提示用户选择删除方式scanf("%d", &option); // 读取用户选择的删除方式if (option == 1 || option == 2) {char key[20];printf("请输入要删除的课程标识:"); // 提示用户输入要删除的课程标识scanf("%s", key); // 读取用户输入的课程标识FILE* inputFile = fopen("./课程管理系统.txt", "r"); // 以只读模式打开名为课程管理系统.txt的文件if (inputFile == NULL) {printf("无法打开文件\n"); // 如果文件打开失败,则输出错误信息return;}FILE* outputFile = fopen("temp.txt", "w"); // 以写入模式创建一个临时文件temp.txtif (outputFile == NULL) {printf("无法创建临时文件\n"); // 如果创建临时文件失败,则输出错误信息fclose(inputFile);return;}// 遍历文件并删除匹配的课程信息struct Course course;bool found = false;while (fscanf(inputFile, "%s %s %s %s %s %s %s %s", course.number, course.name,course.type, course.totalHours, course.experimentHours,course.lectureHours, course.credits, course.semester) == 8) {if ((option == 1 && strcmp(course.number, key) == 0) ||(option == 2 && strcmp(course.name, key) == 0)) {found = true;continue; // 不写入到输出文件,相当于删除}fprintf(outputFile, "%s %s %s %s %s %s %s %s\n", course.number, course.name,course.type, course.totalHours, course.experimentHours, course.lectureHours,course.credits, course.semester); // 将未匹配的课程信息写入输出文件}fclose(inputFile); // 关闭输入文件fclose(outputFile); // 关闭输出文件if (found) {remove("课程管理系统.txt"); // 删除原文件rename("temp.txt", "课程管理系统.txt"); // 重命名临时文件为原文件名printf("课程信息已成功删除!\n"); // 输出课程信息已成功删除的消息}else {remove("temp.txt"); // 删除临时文件printf("未找到要删除的课程信息\n"); // 若未找到要删除的课程,则输出未找到的消息}}else {printf("无效的选择,请选择1或2\n"); // 如果选择无效,则输出提示消息}BrowseCourses();
}// 按开课学期对课程信息进行排序的函数
void SortCourses()
{struct Course courses[100];int count = 0;LoadData(courses, &count); // 从文件中加载课程信息// 使用冒泡排序按开课学期进行排序int i, j;for (i = 0; i < count - 1; i++) {for (j = 0; j < count - i - 1; j++) {// 将开课学期转换为整数进行比较int semester1 = atoi(courses[j].semester);int semester2 = atoi(courses[j + 1].semester);if (semester1 > semester2) {struct Course temp = courses[j];courses[j] = courses[j + 1];courses[j + 1] = temp;}}}// 保存排序后的课程信息到文件SaveData(courses, count);printf("课程信息已按开课学期排序!\n");BrowseCourses();
}
5.3 Test.c
#include "CourseManagement.h"
int main() {int choice;do {PrintMenu();scanf("%d", &choice);if (choice >= 1 && choice <= 6) {Menu(choice);}else if (choice == 0) {printf("您已退出课程系统\n");break;}else {printf("输入错误,请重新输入一个在0到7之间的整数!\n");}} while (1);return 0;
}