C++学生信息和考试成绩管理系统(四)

C++学生信息和考试成绩管理系统

第一章 工程介绍

第二章 用户登陆准备和登陆

第三章 用户的增删查改

第四章 考试创建&成绩的增改

第五章 成绩查询



一、考试创建

下面我们具体说一下,考试的创建和成绩查询、修改。我写了显示可以选择创建两个考试,实际上只能创建一种,另一种没写。看看下面这些代码,每一片代码的作用都写了,其实就是不停地输入、获取,最后调用自定义函数存储到文件中,再给配置文件的[record]增加记录即可。
当前位置:manage_admin.cpp

void print_menu_admin_exam_create_comprehensive_examination()
{
	while (true)
	{
		CLEAN;

		// ---------- Start ----------
		switch (input_judgment(true, true, "Do you want to create comprehensive examination? (Y/N) "))
		{
		case -1:
			continue;
		case 0:
			return;
		case 1:
		default:
			break;
		}
		// 创建考试类对象的操作类
		auto* operation = new operation_info<exam_info>;

		// 日期时间 (Date-time)
		operation->info_class->date_time = input_datetime();

		// 自动添加创建者 (Creator or administrator)
		char* tmp_admin = new char[strlen(g_vector_login_info[0]) + 1];
		strcpy_s(tmp_admin, strlen(g_vector_login_info[0]) + 1, g_vector_login_info[0]);
		operation->info_class->admin = tmp_admin;

		// 考生人数 (Count Students)
		while (true)
		{
			std::string tmp = input(3, true, "Please input amount of students: ");
			if (is_positive_integer(tmp.c_str()))
			{
				operation->info_class->count_student = strtol(tmp.c_str(), nullptr, 0L);
				break;
			}
			print_wait("Please input correctly.");
		}

		// 应考科目数 (Count majors)
		while (true)
		{
			std::string tmp = input(2, true, "Please input amounts of subject: ");
			if (is_positive_integer(tmp.c_str()))
			{
				operation->info_class->count_subject = strtol(tmp.c_str(), nullptr, 0L);
				break;
			}
			print_wait("Please input amounts of major.");
		}

		// 科目编号 (Major serial number)
		for (int i = 0; i < operation->info_class->count_subject; i++)
		{
			std::cout << "Please set the " << i + 1 << " serial id/name of subject: ";
			operation->info_class->vector_subject_serial_number.emplace_back(input(4));
		}

		// 考生记录 (Examination records of student)
		for (int i = 0; i < operation->info_class->count_student; i++)
		{
			auto* tmp_student_exam_record = new exam_record_info;
			while (true)
			{
				std::cout << "Please input the " << i + 1 << " student id: ";
				char* input_student_id = input(MAXSIZE_STUDENT_ID);
				auto* tmp_operation = user_select(input_student_id, 2);
				if (tmp_operation->info_flag)
				{
					tmp_student_exam_record->student_name = new char[strlen(tmp_operation->info_class->name) + 1];
					strcpy_s(tmp_student_exam_record->student_name, strlen(tmp_operation->info_class->name) + 1, tmp_operation->info_class->name);
					tmp_student_exam_record->student_id = input_student_id;
					tmp_student_exam_record->class_id = new char[strlen(tmp_operation->info_class->class_id) + 1];
					strcpy_s(tmp_student_exam_record->class_id, strlen(tmp_operation->info_class->class_id) + 1, tmp_operation->info_class->class_id);
					free_ptr(tmp_operation);
					break;
				}
				print_wait("Not found user. Please try input again.");
			}

			// 循环录入每科成绩 (Recycle entry of each subject score)
			for (int j = 0; j < operation->info_class->count_subject; j++)
			{
				std::cout << "Please input the score of \"" << operation->info_class->vector_subject_serial_number[j] << "\": ";
				double tmp_score = 0;
				while (true)
				{
					char* tmp = input(MAXSIZE_BUFF);
					if (std::regex_match(tmp, std::regex("^([1-9][0-9]*)+(\\.[0-9]{1,2})?$")))
					{
						tmp_score = strtod(tmp, nullptr);
						free_ptr(tmp, true);
						break;
					}
					print_wait("Please input correct number!");
				}
				tmp_student_exam_record->score_average += tmp_score;
				tmp_student_exam_record->vector_score_subject.emplace_back(tmp_score);
				if (0 == i)
				{
					operation->info_class->vector_subject_average_score.emplace_back(tmp_score);
				}
				else
				{
					operation->info_class->vector_subject_average_score[j] += tmp_score;
				}
			}

			if (0 != operation->info_class->count_student && 0 != operation->info_class->count_subject)
			{
				// 自动统计单个学生平均总分 (Calculate the average total score of each student)
				tmp_student_exam_record->score_average /= operation->info_class->count_subject;

				// 自动累加全部学生总分 (Add up the total score of all students)
				operation->info_class->average_score += tmp_student_exam_record->score_average;
			}
			
			// 存入考试记录对象 (Save the test record object)
			operation->info_class->vector_student_exam_record.emplace_back(tmp_student_exam_record);
		}

		// 自动计算全部考生总平均成绩 (Calculate the average score of all candidates)
		operation->info_class->average_score /= operation->info_class->count_student;

		// 自动计算每科平均成绩 (Calculate the average grade of each subject)
		for (int i = 0; i < operation->info_class->count_subject; i++)
		{
			operation->info_class->vector_subject_average_score[i] /= operation->info_class->count_student;
		}

		// 自动排名 (Rankings)
		std::sort(operation->info_class->vector_student_exam_record.begin(), operation->info_class->vector_student_exam_record.end(), sort_student_exam_record);
		for (int i = 0; i < operation->info_class->count_student; i++)
		{
			if (!operation->info_class->vector_student_exam_record.empty())
			{
				operation->info_class->vector_student_exam_record[i]->rankings = i + 1;
			}
		}
		
		// ---------- Reconfirm ----------
		switch (input_judgment(true, true, "Are you confirm finish? (Y/N) "))
		{
		case 0:
			print_wait("Cancelled.");
		case -1:
			return;
		case 1:
		default:
			break;
		}
		

		// ---------- Store ----------
		if (!exam_store(operation->info_class))	// 自定义函数:存储考试记录
		{
			free_ptr(operation);
			print_wait("Save exam record failed.");
			print_log("Failed to create exam. ", severity_code_error);
			continue;
		}

		// ---------- Finish ----------
		CLEAN;
		operation->info_class->print_exam();
		free_ptr(operation);
		print_wait("Create examination successfully!");
		print_log("Create comprehensive examination successfully.", severity_code_info);
	}
}

上面的代码中有个自定义的存储函数exam_store(),它的作用就是把新创建的考试类对象,按格式存储到./data/record/下,然后将init.ini里的[record]增加新的考试记录文件所在位置和文件名。
当前位置:process_file.cpp

bool exam_store(const exam_info* info, char* path)
{
	std::fstream f;
	std::string tmp_path = PATH_FOLDER_RECORD"exam_*****.csv";

	try
	{
		if (nullptr == path)
		{
			if (g_vector_file_path_record.empty())
			{
				print_log("Create an record file, because not record files exist", severity_code_info);
				f.open(PATH_FOLDER_RECORD"exam_0.csv", std::ios::out | std::ios::trunc | std::ios::binary);
			}
			else
			{
				std::vector<int> tmp_vector_index;
				for (const auto& tmp_exam_path : g_vector_file_path_record)
				{
					auto tmp_trim_path = trim(tmp_exam_path);
					const std::string::size_type idx_head = tmp_trim_path.find("exam_");
					const std::string::size_type idx_tail = tmp_trim_path.find(".csv");
					if (idx_head == std::string::npos || idx_tail == std::string::npos) {
						std::cout << "None" << std::endl;
						continue;;
					}
					const unsigned int length = static_cast<const unsigned int>(idx_tail) - static_cast<const unsigned int>(idx_head) - 4;
					tmp_vector_index.emplace_back(strtol(tmp_trim_path.substr(idx_head + 5, length - 1).c_str(), nullptr, 0L));
					
				}
				if (!tmp_vector_index.empty())
				{
					std::sort(tmp_vector_index.begin(), tmp_vector_index.end(), std::less<>());
					const std::string::size_type idx_head = tmp_path.find("exam_");
					const std::string::size_type idx_tail = tmp_path.find(".csv");
					const unsigned int length = static_cast<const unsigned int>(idx_tail) - static_cast<const unsigned int>(idx_head) - 4;
					char tmp_digits[255];
					sprintf_s(tmp_digits, sizeof(tmp_digits), "%d", tmp_vector_index[tmp_vector_index.size() - 1] + 1);
					tmp_path.replace(idx_head + 5, length - 1, tmp_digits);
				}
				f.open(tmp_path.c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
			}
		}
		else
		{
			f.open(path, std::ios::out | std::ios::trunc | std::ios::binary);
		}

		if (!f.is_open())
		{
			return false;
		}

		f << info->date_time << "," << info->admin << "," << info->count_student << "," << info->average_score << "," << info->count_subject << "\r\n";
		if (!info->vector_subject_serial_number.empty())
		{
			for (const auto* tmp : info->vector_subject_serial_number)
			{
				f << tmp;
				if (0 != strcmp(tmp, info->vector_subject_serial_number.back()))
				{
					f << ",";
				}
				else
				{
					f << "\r\n";
				}
			}
		}

		if (!info->vector_subject_average_score.empty())
		{
			for (unsigned int i = 0; i < info->vector_subject_average_score.size(); i++)
			{
				f << info->vector_subject_average_score[i];
				if (i != info->vector_subject_average_score.size() - 1)
				{
					f << ",";
				}
				else
				{
					f << "\r\n";
				}
			}
		}

		if (!info->vector_student_exam_record.empty())
		{
			for (const auto& tmp : info->vector_student_exam_record)
			{
				f << tmp->rankings << ",";
				f << tmp->student_name << ",";
				f << tmp->class_id << ",";
				f << tmp->student_id << ",";
				f << tmp->score_average << ",";

				for (unsigned int i = 0; i < tmp->vector_score_subject.size(); i++)
				{
					f << tmp->vector_score_subject[i];
					if (i != tmp->vector_score_subject.size() - 1)
					{
						f << ",";
					}
					else
					{
						f << "\r\n";
					}
				}
			}
		}
		f.close();

		if (!properties_update(3, tmp_path.c_str()))
		{
			return false;
		}
	}
	catch (const std::exception& e)
	{
		print_log(e.what(), severity_code_error);
		return false;
	}

	return true;
}

二、更改成绩

至此,考试的创建代码已经完成了,下面简要说一下更改成绩,本质上也是遍历全部考试成绩记录,逐行读取学生类对象,找到对应学号,将这个页面文件装到容器里,修改值,再清空这个文件,并将这个容器写回文件,完成成绩的修改。

下面这个是交互界面,也就是选择更新成绩后跳转到的页面代码。
当前位置:manage_admin.cpp

void print_menu_admin_exam_update(menu& menus)
{
	while (true)
	{
		CLEAN;

		// ---------- Start ----------
		switch (input_judgment(true, true, "Do you want to update scores of student? (Y/N)"))
		{
		case -1:
			continue;
		case 0:
			return;
		case 1:
		default:
			break;
		}

		char* student_id;

		char* datetime_start;

		char* datetime_end;

		operation_info<exam_info*>* operation;
		
		while (true)
		{
			// ---------- Input Student Id ----------
			while (true)
			{
				student_id = input(MAXSIZE_STUDENT_ID, true, "Please input Student Id: ");
				if (std::regex_match(student_id, std::regex("^[0-9]\\d*$")))
				{
					break;
				}
				print_wait("Illegally student id input!");
				free_ptr(student_id, true);
			}

			// ---------- Input start datetime of exam ----------
			while (true)
			{
				datetime_start = input(MAXSIZE_DATETIME_LENGTH, true, "Please input start datetime: ");
				if (0 == strcmp(trim(datetime_start).c_str(), "all"))
				{
					break;
				}
				if (MAXSIZE_DATETIME_LENGTH == strlen(datetime_start) && std::regex_match(datetime_start, std::regex("^[1-9]\\d*$")))
				{
					break;
				}
				print_wait("Illegally start datetime input!");
				free_ptr(datetime_start, true);
			}

			// ---------- Input end datetime of exam ----------
			while (true)
			{
				datetime_end = input(MAXSIZE_DATETIME_LENGTH, true, "Please input end datetime: ");
				if (0 == strcmp(trim(datetime_end).c_str(), "all"))
				{
					break;
				}
				if (MAXSIZE_DATETIME_LENGTH == strlen(datetime_end) && std::regex_match(datetime_end, std::regex("^[1-9]\\d*$")))
				{
					break;
				}
				print_wait("Illegally end datetime input!");
				free_ptr(datetime_end, true);
			}

			// ---------- Select ----------
			operation = exam_select(const_cast<const char*>(student_id), datetime_start, datetime_end);

			if (!operation->info_vector_class.empty())
			{
				break;
			}

			free_ptr(datetime_end, true);
			free_ptr(datetime_start, true);
			free_ptr(student_id, true);
			free_ptr(operation);
			std::cout << "Not found user." << std::endl;
			
			switch (input_judgment(true, true, "Do you want to try again? (Y/N)"))
			{
			case -1:
				print_wait("Illegally input, cancelled.");
				return;
			case 0:
				print_wait("Cancelled.");
				return;
			case 1:
			default:
				break;
			}
		}

		// ---------- Print Old Exam ----------
		if (1 == input_judgment(true, true, "Print out all exam? (Y/N)"))
		{
			for (const auto& tmp : operation->info_vector_class)
			{
				tmp->print_exam();
				printf_s("\n\n");
			}
		}

		char* subject_serial_id;
		char* student_new_score;
		
		while (true)
		{
			// ---------- Input Subject Name ----------
			subject_serial_id = input(6, true, "Please input subject serial id: ");

			// ---------- Input New Score ----------
			
			while (true)
			{
				student_new_score = input(6, true, "Please input new score: ");
				if (std::regex_match(student_new_score, std::regex("^[0-9]+(\\.[0-9]{2})?$")))
				{
					break;
				}
				print_wait("Illegally input!");
				free_ptr(student_new_score, true);
			}

			operation = exam_update(operation, student_id, subject_serial_id, strtod(student_new_score, nullptr));
			if (operation->info_flag)
			{
				break;
			}
			print_wait("Not found or Cannot update score.");
			free_ptr(student_new_score, true);
			free_ptr(subject_serial_id, true);
		}

		int count_alter_success_file = 0;
		// ---------- Store ----------
		for (unsigned int i = 0; i < operation->info_vector_class.size(); i++)
		{
			try
			{
				if (exam_store(operation->info_vector_class[i], operation->info_vector_path[i]))
				{
					count_alter_success_file++;
				}
			}
			catch (...)
			{
				print_log("Error to save alter file.");
			}

		}

		// ---------- Print New Exam ----------
		if (1 == input_judgment(true, true, "Print out all exam? (Y/N)"))
		{
			for (const auto& tmp : operation->info_vector_class)
			{
				tmp->print_exam();
				printf_s("\n\n");
			}
		}

		std::cout << "Student ID: " << student_id << std::endl;
		std::cout << "Subject: " << subject_serial_id << std::endl;
		std::cout << "New Score: " << student_new_score << std::endl;

		std::cout << "All files: " << operation->info_vector_class.size() << std::endl;
		std::cout << "Success: " << count_alter_success_file << "\t" << "Failed: " << operation->info_vector_class.size() - count_alter_success_file << std::endl;

		print_wait("Operation success!");
		free_ptr(student_id, true);
		free_ptr(student_new_score, true);
		free_ptr(subject_serial_id, true);
		free_ptr(datetime_start, true);
		free_ptr(datetime_end, true);
		free_ptr(operation);
	}
}

要讲的其实并不多,主旨也就那样,函数也都介绍了。注意下写的注释,根据注释猜测应该能猜出来个大概,这个区域要做什么,再根据变量名去猜测,这个变量是做什么的,英文可不能白学。至于常量,我基本是定义在头文件里,根据名字去猜它是做什么的。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该系统用于管理某高校的本科生、研究生2类人员信息: 本科生信息:学号、姓名、性别、专业、年级、班级、高数成绩、英语成绩、C语言、总成绩、班级排名、年级排名 研究生信息:学号、姓名、性别、专业、年级、班级、课程综合成绩、论文成绩、总成绩、班级排名、年级排名。 1. 专业管理:包括专业基本信息的添加、修改、删除、查询功能。学生必须归属于某个专业。 2. 班级管理:包括班级基本信息的添加、修改、删除、查询功能。学生必须归属于某个班级。 3. 添加功能:分本科生和研究生两类人员,实现下列添加功能。 A.本科生:根据学号来修改任意学生的除学号外的信息。如果高数成绩、英语成绩、c语言成绩都存在,则系统自动计算总成绩。 B.研究生:根据学号来修改任意学生的除学号外的信息。如果课程综合成绩、论文成绩都存在,则系统自动计算总成绩 5. 删除功能:分本科生和研究生两类人员,能够根据学号删除一个学生。 6. 排名功能:分本科生和研究生两类人员,实现下列排名功能。 说明:排名包括班级排名和年级排名,排名规则按体育竞赛规则处理,若出现两个并列第1名,下个名次为第3名,依此类推。 A:班级排名:分本科生和研究生两类学生,计算每个学生总成绩在班级中的名次。 B:年级排名:分本科生和研究生两类学生,计算每个学生总成绩在本专业、本年级中的名次。 7. 查询功能:分本科生和研究生两类人员,实现下列查询功能。 1) 能够按班级显示本班全部学生信息。 2) 能够根据学号或者姓名查询学生信息。 3) 能够在某个班级中查询某门课成绩不及格学生信息。 8. 排序功能:分本科生和研究生两类人员,实现下列排序功能。 1) 所有学生信息按学号从低到高排序并显示。 2) 某个班学生信息按总成绩从高到低排序并显示。 9. 统计功能:分本科生和研究生两类人员,实现下列统计与显示功能。 1) 统计某班级某课程的平均成绩、最高成绩、最低成绩。如果学生该门课没有成绩,统计平均成绩时忽略该生。 2) 统计某班级某课程超过课程平均成绩的学生名单及人数。 3) 统计某班级某课程不及格学生名单及人数。 4) 统计某班级某课程不同等级的学生人数。 有需求分析,系统设计、编码、运行结果等
关于c语言和c++的课程成绩信息管理系统,共有将近6000行代码,建议使用vs2012或2010便于管理也可使用VC6.0++环境修改运行但查找麻烦,所有的语言没有脱离c和c++,主要采用模块思想,也可以转换成面向对象型的语言,只要将模块函数写进类中。同时学c语言的也可以使用,除了使用cout,cin一些很容易上手的c++代码,相当于printf,scanf,主要为了方便输入输出,不用写%d%c... 详细细节也可以访问,百度文库网址 使用注意事项 有着强大的报错功能。 1 全部采用鼠标点击功能,可以看百度网址图片。 2 录用学生信息的细节选项中,如果点击错误信息,再次点击将会取消。 3 附加功能中的高级打印功能中,如果想改变选项,只需要点击另一个即可,当前的状态就会消失。 4 输入学号为53120101--531215**(其中不包括****00,例如53120700)。(可以设置) 5 所有成绩范围为0--99。(可以设置) 6 如果想去掉钢琴曲,直接删除MP3,或者改成其他名字即可。 7 打印直方图可以根据班级的不同,向后移动。 7 如果打印不规范,可能窗口较小,可通过调节窗口大小来打印排名...... 8 请包含student.txt默认文件(文件中至少一名学生信息),否则将会程序在进行实质功能作用时意外退出(已在包中)。 头文件student.h #ifndef _STUDENT_H_ #define _STUDENT_H_ #include #include HWND hWnd; //来自msdn #define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s \ on line %d\n", __FILE__, GetLastError(), api, __LINE__);} void cls( HANDLE hConsole ) { COORD coordScreen = { 0, 0 }; /* here's where we'll home thecursor */ BOOL bSuccess; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ DWORD dwConSize; /* number of character cells inthe current buffer *//* get the number of character cells in the current buffer */ bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); PERR( bSuccess, "GetConsoleScreenBufferInfo" ); dwConSize = csbi.dwSize.X * csbi.dwSize.Y;/* fill the entire screen with blanks */ bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten ); PERR( bSuccess, "FillConsoleOutputCharacter" );/* get the current text attribute */ bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); PERR( bSuccess, "ConsoleScreenBufferInfo" );/* now set the buffer's attributes accordingly */ bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ); PERR( bSuccess, "FillConsoleOutputAttribute" );/* put the cursor at (0, 0) */ bSuccess = SetConsoleCursorPosition( hConsole, coordScreen ); PERR( bSuccess, "SetConsoleCursorPosition" ); return; } HANDLE hOut; HANDLE hIn; void enter(); void ReadFile(char*str="student.txt"); typedef enum grade{you=95,liang=85,zhong=75,pass=65,nopass=0 } Grade; Grade g1=you; Grade g2=liang; Grade g3=zhong; Grade g4=pass; Grade g5=nopass; void DelClass(); //学生类结构 typedef struct student{ int studentid; char name[20]; char sex[5]; char nation[20]; int biryear; int birmonth; char post[10]; int cyu; int cyushe; int cshe; int cdui; int cduishe; struct student* next; double ave; double wave; } Student; Student *stubegin=NULL; Student* stulast=NULL; int total=0; //课程类结构 typedef struct course{ char obj[30]; int time; int xuefen; int mark; Grade rank; } Course; Course c1; Course c2; Course c3; Course c4; Course c5; void InitCourse(); void AddData(Student*); void AltData(); void AddShuju(int *,Student*); void IntEro(int& ,int,int,int,int); //功能介绍 /*****************************************Loading页面*******************************************/ void input();//输入信息功能 void output();//输出信息功能 void addition();//附加功能 /*****************************************输入信息功能*******************************************/ void AddStudent(); void DelStudent(int); void AltStudent(int); void SaveMessage(); void readfile(); /*****************************************输出信息功能*******************************************/ void CalRankAve(int); void CalRankWave(int); void PrintStudent(int); void PrintCourse(int); void PrintWell(); /*****************************************打印总成绩*******************************************/ void PrintTotal(); void PrintStudentID(); void PrintAve(); void PrintWave(); /*****************************************打印科目成绩*******************************************/ void PrintObj(); void PrintCyu(); void PrintCyushe(); void PrintCshe(); void PrintCdui(); void PrintCuishe(); /*****************************************打印优秀职务单科成绩*******************************************/ void PrintObjYou(); void PrintCyuYou(); void PrintCyusheYou(); void PrintCsheYou(); void PrintCduiYou(); void PrintCuisheYou(); /*********************辅助函数**********************/ void printmark(Student *); void AddStudent1(); void SortAve(); void SortWave(); void SortId(); void SortCyu(); void SortCyushe(); void SortCshe(); void SortCdui(); void SortCduishe(); int GetInt(char* ); int Search(int); void PrintGrade(int); int GetXuefen(int,int); /****计算平均成绩和加权成绩**/ void CalAve(Student*); void CalWave(Student*); /*****************************************附加功能*******************************************/ void PrintHistogram(); void PrintTotalHistogram();

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值