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, "\n%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.txt
		if (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

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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, "\n%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.txt
		if (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;
}
  • 41
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值