C language student achievement management system (Easy graphical interface)

Posted by theflea912 on Mon, 17 Jan 2022 02:33:14 +0100

My little station—— Half raw melon blog

Code file download link—— link


Student achievement management system

design sketch

Process & key points

  • The core part - EasyX displays the graphical interface, structure array and file operation, and is responsible for various operations on the data.
  • As soon as you go in, the program will read the file storing data. If there is data, read it directly into the student structure array, get the number of data (several people) in the current structure array, and print all the data to the screen.
  • Administrator user
    • Enter password verification - read the file - verify that the user input is correct.
    • Display all data - if the data is read through the file, it will be printed to the screen, and vice versa. If no data is read, the "current record is empty!" will be displayed on the screen before adding data.
      • Sorting in various ways - the data of members in the current structure array is reordered according to "sorting by xx", and bubble sorting is adopted. It is worth noting that it seems that the InputBox of EasyX can only save your input into the character array, so you need to convert the entered score data into floating-point type through atof function, The method I use here is: first convert everyone's grades of a subject into floating-point type and store them in a grade structure array according to the storage order of the data in the structure array (when writing this sentence, I think we can also directly store the grades of each subject in a structure array, and then compare them to reduce the amount of code), Then, the bubble loop is used to reorder the structure array storing grades. It should be noted that while the elements in the structure array storing grades exchange positions, the elements in various data structure arrays of students also exchange positions. The storage order of the two data is the same, That is, one structure array assists another structure array in sorting, and the two structures need to change at the same time.
    • Add / delete query / modify interface
      • Add - add data to distinguish different people by student number. The name can be the same, but each student number is a separate one. If the entered student number already exists, a pop-up prompt will pop up and re-enter it until the input passes the restrictive conditions. Check whether the entered student number is composed of pure numbers. If not, a pop-up prompt will pop up that the input format is wrong, Re enter until the format is correct. The student name is not limited by the input format, and the grade is the student number. After all inputs are completed, save the data, and the number of people in the current structure is + +. If the student number and name are empty when adding, it is judged as invalid input and the operation is invalid.
      • Search - search for data (both deleting and modifying data depend on the search for data. Only when this person is found in the structure can his data be operated). Search for a person by entering the student number or name, traverse in the structure array, and return the subscript corresponding to the student in the structure array, Then input the student's data into the screen. On the contrary, the pop-up window will prompt "no such person".
      • Delete - to delete data, first search, and when it is found, a window will pop up to prompt whether to confirm the deletion. After confirming the deletion, use the cycle, start from the subscript of the person to be deleted in the structure array, and successively overwrite the following data to the front. After completion, the number of members in the structure array is -. The pop-up prompt indicates that the deletion is successful.
      • Change - to modify the data, also search first. If it is found, InputBox prompts you to enter new data. Note: different from the data entered above, the newly entered student number here needs to be saved to a temporarily created character array, not directly to the corresponding data position of the student to be modified in the structure array, because if so, Next, when judging whether the student number already exists, it must exist. After judging whether it is repeated, if the data is not repeated, assign the newly entered student number to the variable to be modified. It should also be noted that if the new student number entered by the user is the same as the original, it is OK, so an additional judgment needs to be added here, Otherwise, you will not be able to proceed to the next step because you have detected duplicate data.
  • Ordinary users
    • Display all data and various sorts, and search as above.
    • It should be noted that the administrator user and ordinary users share a common interface, such as the input interface for displaying all data and searching. The jump after clicking the return key needs to be judged. A macro defines a global integer variable. The point from which it comes in is given a new value before this sentence, which is judged by the conditional judgment statement.
  • defect
    • The data display cannot be paged, and a maximum of 17 data can only be displayed in a limited interface.
    • The amount of code can also be optimized.

code implementation

#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<string.h>
#include<ctype. h> / / detect characters


#define RecordNums 15 / / number of structure arrays

int NowStudentNums = 0;//Number of people currently recorded


//Do not use data structures
//It is realized by structure array and file operation

//Definition of student structure
typedef struct Student
{
	char s_Num[64];//Student number
	char s_Name[64];//full name
	char s_Chinese[64];//language
	char s_Math[64];//number
	char s_English[64];//Britain
	double s_SumScore;//Total score
}Student;


//Create student structure array
Student StuArry[RecordNums];

//Create score structure
typedef struct Score
{
	double SuScore;//subject score
}Score;

//Create a grade structure - the size is the same as the student structure array
Score SoArry[RecordNums];

//Create administrator structure
typedef struct Admin
{
	char UserName[64];
	char PassWord[64];
}Admin;

//Create an administrator user
Admin AdminUser;

//Page Jump ID showing all data
int FlagAI = -1;
//Query and find page Jump ID
int FlagFPT = -1;
/*
			MainSteps
	1.Start with the general shape of the graphics window
	2.Gradually realize the contents
*/

/*
	Graphical interface implementation
*/

//Pre declaration - please jump to the following for specific instructions
void AdminPage();
void AdminSignIn();
void CommonUserPage();
void SaveInfor();
void ReadInfor();
void ShowAllInfor();
void InputInfor();
void S1mplePrint();
void AdDeSeMoPage();
void DeleteStuInfor();
int ReturnPosi();
void ModifyStudInfor();
void PrintFoudInfor();
void DeSomeStu();
void SortAcChinese();
void SortAcMath();
void SortAcEnglish();
void SortAcSumScore();
bool ScoreFormat(char PerSuSc[]);
//home page
void FirstPage()
{
	//Just enter the program and read the data -- get the current nowstudentnum
	ReadInfor();

	//Window size
	initgraph(760, 760);
	//Mouse operation 1
	MOUSEMSG m1;


	cleardevice();
	IMAGE picture1;
	loadimage(&picture1, "./firstbc.jpg", 760, 760);
	putimage(0, 0, &picture1);
	setbkmode(TRANSPARENT);


	

	setfillcolor(GREEN);


	//Headline
	char FirstTitle[20] = { "Student achievement management system" };
	settextstyle(60, 0, "Blackbody");
	outtextxy(150, 100, FirstTitle);

	//Background of three options
	fillrectangle(230, 445, 560, 490);
	fillrectangle(230, 505, 560, 550);
	fillrectangle(230, 565, 560, 610);

	setbkmode(TRANSPARENT);

	//Text for three options
	settextstyle(40, 0, "Blackbody");

	//Three options
	char FirstSelect1[20] = { "Administrator operation interface" };
	char FirstSelect2[20] = { "Common user interface" };
	char FirstSelect3[20] = { "Exit program" };
	outtextxy(240, 450, FirstSelect1);
	outtextxy(240, 510, FirstSelect2);
	outtextxy(240, 570, FirstSelect3);

	//Enter the main interface options operation interface
	while (1)
	{
		m1 = GetMouseMsg();//Get mouse action
		if (m1.x >= 230 && m1.x <= 560 && m1.y >= 445 && m1.y <= 490)//Administrator interface
		{
			setlinecolor(RED);
			rectangle(230, 445, 560, 490);
			if (m1.uMsg == WM_LBUTTONDOWN)
			{
				//Join administrator login
				AdminSignIn();
			}
		}
		else if (m1.x >= 230 && m1.x <= 560 && m1.y >= 505 && m1.y <= 550)//General user interface
		{
			setlinecolor(RED);
			rectangle(230, 505, 560, 550);
			if (m1.uMsg == WM_LBUTTONDOWN)
			{
				cleardevice();
				CommonUserPage();
			}
		}
		else if (m1.x >= 230 && m1.x <= 560 && m1.y >= 565 && m1.y <= 610)//sign out
		{
			setlinecolor(RED);
			rectangle(230, 565, 560, 610);
			if (m1.uMsg == WM_LBUTTONDOWN)
			{
				exit(0);
			}
		}
		//The mouse does not hover over it
		else
		{
			setlinecolor(WHITE);
			rectangle(230, 445, 560, 490);
			rectangle(230, 505, 560, 550);
			rectangle(230, 565, 560, 610);
		}
	}

}

//Administrator interface
void AdminPage()
{
	initgraph(760, 760);
	//Clear it first
	cleardevice();
	//Define the second mouse action
	MOUSEMSG m2;



	cleardevice();
	IMAGE picture1;
	loadimage(&picture1, "./firstbc.jpg", 760, 760);
	putimage(0, 0, &picture1);
	setfillcolor(GREEN);
	setbkmode(TRANSPARENT);

	char SecondTitle1[5] = { "Tube" };
	char SecondTitle2[5] = { "reason" };
	char SecondTitle3[5] = { "member" };
	char SecondTitle4[5] = { "exercise" };
	char SecondTitle5[5] = { "do" };
	char SecondTitle6[5] = { "circles" };
	char SecondTitle7[5] = { "noodles" };


	settextstyle(50, 0, "Blackbody");
	outtextxy(50, 150, SecondTitle1);
	outtextxy(50, 210, SecondTitle2);
	outtextxy(50, 270, SecondTitle3);
	outtextxy(50, 330, SecondTitle4);
	outtextxy(50, 390, SecondTitle5);
	outtextxy(50, 450, SecondTitle6);
	outtextxy(50, 510, SecondTitle7);


	setbkmode(TRANSPARENT);


	//Background of three options
	fillrectangle(230, 240, 560, 285);
	fillrectangle(230, 370, 560, 415);
	fillrectangle(230, 500, 560, 545);

	setbkmode(TRANSPARENT);

	//Text for three options
	settextstyle(40, 0, "Blackbody");

	//Three options
	char SecondSelect1[20] = { "Show all data" };
	char SecondSelect2[20] = { "Add, delete, query and modify data" };
	char SecondSelect3[20] = { "return" };


	outtextxy(270, 240, SecondSelect1);
	outtextxy(270, 370, SecondSelect2);
	outtextxy(350, 500, SecondSelect3);


	//Enter the main interface options operation interface
	while (1)
	{
		m2 = GetMouseMsg();//Get mouse action
		if (m2.x >= 230 && m2.x <= 560 && m2.y >= 240 && m2.y <= 285)
		{
			setlinecolor(RED);
			rectangle(230, 240, 560, 285);
			if (m2.uMsg == WM_LBUTTONDOWN)
			{
				//Show all data
				FlagAI = 1;
				cleardevice();
				ShowAllInfor();

			}
		}
		else if (m2.x >= 230 && m2.x <= 560 && m2.y >= 370 && m2.y <= 415)
		{
			setlinecolor(RED);
			rectangle(230, 370, 560, 415);
			if (m2.uMsg == WM_LBUTTONDOWN)
			{
				//Add / delete query / modify interface
				cleardevice();
				AdDeSeMoPage();
			}
		}
		else if (m2.x >= 230 && m2.x <= 560 && m2.y >= 500 && m2.y <= 545)
		{
			setlinecolor(RED);
			rectangle(230, 500, 560, 545);
			if (m2.uMsg == WM_LBUTTONDOWN)
			{
				//return
				cleardevice();
				FirstPage();
			}
		}
		//The mouse does not hover over it
		else
		{
			setlinecolor(WHITE);
			rectangle(230, 240, 560, 285);
			rectangle(230, 370, 560, 415);
			rectangle(230, 500, 560, 545);
		}
	}

}

//General user interface
void CommonUserPage()
{
	initgraph(760, 760);Remember to delete

	//Clear it first
	cleardevice();
	//Define the second mouse action
	MOUSEMSG m3;

	cleardevice();
	IMAGE picture1;
	loadimage(&picture1, "./firstbc.jpg", 760, 760);
	putimage(0, 0, &picture1);
	setbkmode(TRANSPARENT);



	setfillcolor(GREEN);


	char SecondTitle1[5] = { "universal" };
	char SecondTitle2[5] = { "through" };
	char SecondTitle3[5] = { "use" };
	char SecondTitle4[5] = { "household" };
	char SecondTitle5[5] = { "exercise" };
	char SecondTitle6[5] = { "do" };
	char SecondTitle7[5] = { "circles" };
	char SecondTitle8[5] = { "noodles" };


	settextstyle(50, 0, "Blackbody");
	outtextxy(50, 150, SecondTitle1);
	outtextxy(50, 210, SecondTitle2);
	outtextxy(50, 270, SecondTitle3);
	outtextxy(50, 330, SecondTitle4);
	outtextxy(50, 390, SecondTitle5);
	outtextxy(50, 450, SecondTitle6);
	outtextxy(50, 510, SecondTitle7);
	outtextxy(50, 570, SecondTitle8);


	setbkmode(TRANSPARENT);


	//Background of three options

	fillrectangle(230, 240, 560, 285);
	fillrectangle(230, 370, 560, 415);
	fillrectangle(230, 500, 560, 545);

	setbkmode(TRANSPARENT);

	//Text for three options
	settextstyle(40, 0, "Blackbody");

	//Three options
	char ThirdSelect1[20] = { "Show all data" };
	char ThirdSelect2[20] = { "Query data" };
	char ThirdSelect3[20] = { "return" };



	outtextxy(270, 240, ThirdSelect1);
	outtextxy(310, 370, ThirdSelect2);
	outtextxy(350, 500, ThirdSelect3);




	//Enter the main interface options operation interface
	while (1)
	{
		m3 = GetMouseMsg();//Get mouse action
		if (m3.x >= 230 && m3.x <= 560 && m3.y >= 240 && m3.y <= 285)//Option 1
		{
			setlinecolor(RED);
			rectangle(230, 240, 560, 285);
			if (m3.uMsg == WM_LBUTTONDOWN)
			{
				//Show all data
				FlagAI = -1;
				cleardevice();
				ShowAllInfor();
			}
		}
		else if (m3.x >= 230 && m3.x <= 560 && m3.y >= 370 && m3.y <= 415)//Option 2
		{
			setlinecolor(RED);
			rectangle(230, 370, 560, 415);
			if (m3.uMsg == WM_LBUTTONDOWN)
			{
				//Query data
				FlagFPT = -1;
				PrintFoudInfor();
				CommonUserPage();
			}
		}
		else if (m3.x >= 230 && m3.x <= 560 && m3.y >= 500 && m3.y <= 545)//Option 3 - return
		{
			setlinecolor(RED);
			rectangle(230, 500, 560, 545);
			if (m3.uMsg == WM_LBUTTONDOWN)
			{
				cleardevice();
				FirstPage();
			}
		}
		//The mouse does not hover over it
		else
		{
			setlinecolor(WHITE);
			rectangle(230, 240, 560, 285);
			rectangle(230, 370, 560, 415);
			rectangle(230, 500, 560, 545);
		}
	}
}

/*
	//Function realization//
*/


//Input information - input through the pop-up window & the system will automatically calculate the total score
void InputInfor()
{
	//Numeric parameter in InputBox -- limit the number of bits of input content


	//The name can be repeated, but the student number cannot be repeated
	//Check for duplicates by looping

	//Enter student number
	while (1)
	{
		TCHAR InputWindow0[] = _T("Please enter the student number of the student");
		InputBox(StuArry[NowStudentNums].s_Num, 9, InputWindow0);

		int FlagInput2 = 0;
		//Calculates the length of the input string
		int nums = strlen(StuArry[NowStudentNums].s_Num);
		//Judge whether the input is a pure number
		for (int i = 0; i < nums; i++)
		{
			if (StuArry[NowStudentNums].s_Num[i] >= '0' && StuArry[NowStudentNums].s_Num[i] <= '9')//If it's not a number
			{

			}
			else
			{
				FlagInput2 = 1;
				HWND hwndInput2 = GetHWnd();
				int isok = MessageBox(hwndInput2, "The input format is incorrect, please re-enter", "Tips", MB_OK);
				break;
			}
		}
		//Judge whether the input is a pure number
		for (int e = 0; e < nums; e++)
		{
			if (StuArry[NowStudentNums].s_Num[e] >= '0' && StuArry[NowStudentNums].s_Num[e] <= '9')//If it's not a number
			{

			}
			else
			{
				FlagInput2 = 1;
				HWND hwndInput2 = GetHWnd();
				break;
				int isok = MessageBox(hwndInput2, "The input format is incorrect, please re-enter", "Tips", MB_OK);
				
			}
		}

		if (FlagInput2 == 0)
		{
			//Determine whether the input is duplicate
			int FlagInput1 = 0;
			for (int i = 0; i < NowStudentNums; i++)
			{
				if (strcmp(StuArry[NowStudentNums].s_Num, StuArry[i].s_Num) == 0)
				{
					FlagInput1 = 1;
				}
			}
			if (FlagInput1 == 1)
			{
				HWND hwndInput1 = GetHWnd();
				int isok = MessageBox(hwndInput1, "This student already exists, please re-enter", "Tips", MB_OK);
			}
			if (FlagInput1 == 0)
			{
				break;
			}
		}
	}




	//Enter name
	TCHAR InputWindow1[] = _T("Please enter the student's name");
	InputBox(StuArry[NowStudentNums].s_Name, 10, InputWindow1);




	//Input Chinese score
	while (1)
	{
		TCHAR InputWindow2[] = _T("Please enter the student's language score");
		InputBox(StuArry[NowStudentNums].s_Chinese, 4, InputWindow2);

		if (ScoreFormat(StuArry[NowStudentNums].s_Chinese))//Jump out of loop for true
		{
			break;
		}
		
	}
	




	//Enter math scores
	while (1)
	{
		TCHAR InputWindow3[] = _T("Please enter the student's math score");
		InputBox(StuArry[NowStudentNums].s_Math, 4, InputWindow3);

		if (ScoreFormat(StuArry[NowStudentNums].s_Math))//Jump out of loop for true
		{
			break;
		}

	}
	

	//Enter English score
	while (1)
	{
		TCHAR InputWindow4[] = _T("Please enter the student's English score");
		InputBox(StuArry[NowStudentNums].s_English, 4, InputWindow4);

		if (ScoreFormat(StuArry[NowStudentNums].s_English))//Jump out of loop for true
		{
			break;
		}

	}




	//final scoring 
	StuArry[NowStudentNums].s_SumScore =
		atof(StuArry[NowStudentNums].s_Chinese) +
		atof(StuArry[NowStudentNums].s_Math) +
		atof(StuArry[NowStudentNums].s_English);

	//Save data
	SaveInfor();
}

//Judge whether the entered score format is correct
bool ScoreFormat(char PerSuSc[])
{
	//Judge whether the input is a pure number
	int nums = strlen(PerSuSc);
	//Judge whether the input is a pure number
	for (int i = 0; i < nums; i++)
	{
		if (PerSuSc[i] >= '0' && PerSuSc[i] <= '9')//If it's not a number
		{
		}
		else
		{
			HWND hwndInput5 = GetHWnd();
			int isok = MessageBox(hwndInput5, "The input format is incorrect, please re-enter", "Tips", MB_OK);
			return false;
		}
	}
	return true;
}

//Add / delete query / modify interface
void AdDeSeMoPage()
{


	//Mouse operation
	MOUSEMSG SL;

	//By default, it will be sorted according to the total score


	initgraph(860, 760);

	
	cleardevice();
	IMAGE picture2;
	loadimage(&picture2, "./secondbc.jpg", 860, 760);
	putimage(0, 0, &picture2);
	setbkmode(TRANSPARENT);




	setfillcolor(GREEN);
	fillrectangle(690, 90, 850, 140);//increase
	fillrectangle(690, 190, 850, 240);//Delete
	fillrectangle(690, 290, 850, 340);//check
	fillrectangle(690, 390, 850, 440);//change
	fillrectangle(690, 490, 850, 540);//empty
	fillrectangle(690, 590, 850, 640);//return

	//Header text
	setbkmode(TRANSPARENT);
	settextstyle(30, 0, "Blackbody");
	outtextxy(0, 0, "ranking");
	outtextxy(80, 0, "Student number");
	outtextxy(200, 0, "full name");
	outtextxy(300, 0, "language");
	outtextxy(400, 0, "mathematics");
	outtextxy(500, 0, "English");
	outtextxy(600, 0, "Total score");
	outtextxy(740, 0, "option");
	outtextxy(740, 100, "add to");
	outtextxy(740, 200, "delete");
	outtextxy(740, 300, "lookup");
	outtextxy(740, 400, "modify");
	outtextxy(740, 500, "empty");
	outtextxy(740, 600, "return");


	//Print the existing information - the prompt that the record is empty is also here
	S1mplePrint();

	//Enter the mouse operation link
	while (1)
	{
		SL = GetMouseMsg();
		if (SL.x >= 690 && SL.x <= 850 && SL.y >= 90 && SL.y <= 140)
		{

			setlinecolor(RED);
			rectangle(690, 90, 850, 140);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				//add to
				InputInfor();
				cleardevice();
				//Reload - refresh after operation is completed
				AdDeSeMoPage();
			}
		}
		else if (SL.x >= 690 && SL.x <= 850 && SL.y >= 190 && SL.y <= 240)
		{

			setlinecolor(RED);
			rectangle(690, 190, 850, 240);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				//delete
				DeSomeStu();
				//Reload - refresh after operation is completed
				AdDeSeMoPage();
			}
		}
		else if (SL.x >= 690 && SL.x <= 850 && SL.y >= 290 && SL.y <= 340)
		{

			setlinecolor(RED);
			rectangle(690, 290, 850, 340);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				FlagFPT = 1;
				//query
				PrintFoudInfor();
				//Reload - refresh after operation is completed
				AdDeSeMoPage();
			}
		}
		else if (SL.x >= 690 && SL.x <= 850 && SL.y >= 390 && SL.y <= 440)
		{
			setlinecolor(RED);
			rectangle(690, 390, 850, 440);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				//modify
				ModifyStudInfor();
				//Reload - refresh after operation is completed
				AdDeSeMoPage();
			}
		}
		else if (SL.x >= 690 && SL.x <= 850 && SL.y >= 490 && SL.y <= 540)
		{
			setlinecolor(RED);
			rectangle(690, 490, 850, 540);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				//Make sure to delete by mistake - pop up a window to prompt
				HWND hwndDel = GetHWnd();
				int isok = MessageBox(hwndDel, "Confirm emptying?", "Tips", MB_OKCANCEL);
				if (isok == IDOK)
				{
					//Call the empty function
					DeleteStuInfor();
					//Reload - refresh after operation is completed
					AdDeSeMoPage();
					//Pop up prompt
					int tips1 = MessageBox(hwndDel, "Empty successfully!", "Tips", MB_OK);
				}
				else if (isok == IDCANCEL)
				{
					//Click Cancel to make no response
				}
			}
		}
		else if (SL.x >= 690 && SL.x <= 850 && SL.y >= 590 && SL.y <= 640)
		{
			//return
			setlinecolor(RED);
			rectangle(690, 590, 850, 640);
			if (SL.uMsg == WM_LBUTTONDOWN)
			{
				cleardevice();
				//Reload - refresh after operation is completed
				AdminPage();


				//Auxiliary test - displays the current number of people
				/*char temptps[5];
				sprintf(temptps, "%d", NowStudentNums);


				HWND hwndTemp = GetHWnd();
				int tips2 = MessageBox(hwndTemp, temptps, "Prompt ", MB_OK);*/
			}
		}
		//Mouse does not hover
		else
		{
			setlinecolor(WHITE);
			rectangle(690, 90, 850, 140);//increase
			rectangle(690, 190, 850, 240);//Delete
			rectangle(690, 290, 850, 340);//check
			rectangle(690, 390, 850, 440);//change
			rectangle(690, 490, 850, 540);//empty
			rectangle(690, 590, 850, 640);//return

		}
	}
}

//Save data to file
void SaveInfor()
{


	//If the student number and name are not empty, they will be written to the file
	if (strlen(StuArry[NowStudentNums].s_Num) != 0 && strlen(StuArry[NowStudentNums].s_Name) != 0)
	{
		FILE* fp = fopen("StudentInforFile.txt", "a");
		if (fp == NULL)
		{
			return;
		}
		fprintf(fp, "%s\t%s\t%s\t%s\t%s\t%lf\n",
			StuArry[NowStudentNums].s_Num,
			StuArry[NowStudentNums].s_Name,
			StuArry[NowStudentNums].s_Chinese,
			StuArry[NowStudentNums].s_Math,
			StuArry[NowStudentNums].s_English,
			StuArry[NowStudentNums].s_SumScore);
		fclose(fp);
		//Number of people saved++
		NowStudentNums++;
	}



}

//Erase all data and then save - mainly used for modifying functions
void SaveInforModi()
{
	//Delete it first, but do not empty the number of people, so the previous deletion function cannot be called
	remove("StudentInforFile.txt");
	//If the student number and name are not empty, they will be written to the file
	FILE* fp = fopen("StudentInforFile.txt", "a");
	if (fp == NULL)
	{
		return;
	}
	for (int i = 0; i < NowStudentNums; i++)
	{
		if (strlen(StuArry[i].s_Num) != 0 && strlen(StuArry[i].s_Name) != 0)
		{

			fprintf(fp, "%s\t%s\t%s\t%s\t%s\t%lf\n",
				StuArry[i].s_Num,
				StuArry[i].s_Name,
				StuArry[i].s_Chinese,
				StuArry[i].s_Math,
				StuArry[i].s_English,
				StuArry[i].s_SumScore);
		}
	}

	fclose(fp);
}

//Read the information in the file - synchronize to the current structure array and get nowstudentnum
void ReadInfor()
{
	FILE* fp = fopen("StudentInforFile.txt", "r");
	if (fp == NULL)
	{
		return;
	}
	//Read the data in the file into the current structure array
	for (int i = 0; i < RecordNums; i++)
	{

		fscanf(fp, "%s\t%s\t%s\t%s\t%s\t%lf\t\n",
			StuArry[i].s_Num,
			StuArry[i].s_Name,
			StuArry[i].s_Chinese,
			StuArry[i].s_Math,
			StuArry[i].s_English,
			&StuArry[i].s_SumScore);
	}

	int FileStudentNums = 0;//The number of people in the auxiliary first get file

	//Number of people reading and fetching data from the file
	for (int k = 0; k < RecordNums; k++)
	{
		if (strlen(StuArry[k].s_Name) != 0)
		{
			//Current number of people - FileStudentNums cannot be set as a global variable, otherwise problems will occur when reading multiple times
			NowStudentNums = ++FileStudentNums;
		}
	}
	fclose(fp);
}

//Completely empty - delete files
void DeleteStuInfor()
{
	//Delete file
	remove("StudentInforFile.txt");
	//Empty current number
	NowStudentNums = 0;
}

//In general, each element in the structure is simply printed at the corresponding position on the screen
void S1mplePrint()
{
	//If it is blank, do not proceed
	if (NowStudentNums == 0)
	{

		settextstyle(50, 0, "Blackbody");
		outtextxy(200, 200, "Current record is empty!");
		return;
	}

	for (int q = 1; q <= NowStudentNums; q++)
	{


		//order
		settextstyle(30, 0, "Blackbody");
		char Nums[5];
		sprintf(Nums, "%d", q);

		//Zoom font
		settextstyle(25, 0, "Blackbody");
		//Student number

		outtextxy(80, 40 + 40 * q, StuArry[q - 1].s_Num);
		//full name
		outtextxy(200, 40 + 40 * q, StuArry[q - 1].s_Name);
		//grade scores of Chinese
		outtextxy(300, 40 + 40 * q, StuArry[q - 1].s_Chinese);
		//Mathematics achievement
		outtextxy(400, 40 + 40 * q, StuArry[q - 1].s_Math);
		//English achievement
		outtextxy(500, 40 + 40 * q, StuArry[q - 1].s_English);
		//Total output score
		if (strlen(StuArry[q - 1].s_Name) != 0)
		{
			outtextxy(0, 40 + 40 * q, Nums);
			char SuSo[20];
			sprintf(SuSo, "%.2f", StuArry[q - 1].s_SumScore);//Keep two digits after the decimal point
			outtextxy(600, 40 + 40 * q, SuSo);
		}
	}
}

//Show all data - General
void ShowAllInfor()
{

	//Mouse operation
	MOUSEMSG SA;
	initgraph(860, 760);
	//The default is to print data to the screen
	cleardevice();
	IMAGE picture2;
	loadimage(&picture2, "./secondbc.jpg", 860, 760);
	putimage(0, 0, &picture2);

	setfillcolor(GREEN);
	setbkmode(TRANSPARENT);




	fillrectangle(690, 90, 850, 140);
	fillrectangle(690, 190, 850, 240);
	fillrectangle(690, 290, 850, 340);
	fillrectangle(690, 390, 850, 440);
	fillrectangle(690, 590, 850, 640);



	//Header text
	setbkmode(TRANSPARENT);
	settextstyle(30, 0, "Blackbody");
	outtextxy(0, 0, "ranking");
	outtextxy(80, 0, "Student number");
	outtextxy(200, 0, "full name");
	outtextxy(300, 0, "language");
	outtextxy(400, 0, "mathematics");
	outtextxy(500, 0, "English");
	outtextxy(600, 0, "Total score");
	outtextxy(700, 0, "sort order");
	outtextxy(700, 100, "Sort by language");
	outtextxy(700, 200, "Sort by math");
	outtextxy(700, 300, "Sort by English");
	outtextxy(700, 400, "Sort by total score");

	outtextxy(740, 600, "return");

	S1mplePrint();//The default is simple printing

	while (1)
	{
		SA = GetMouseMsg();
		if (SA.x >= 690 && SA.x <= 850 && SA.y >= 90 && SA.y <= 140)
		{
			//By language
			setlinecolor(RED);
			rectangle(690, 90, 850, 140);
			if (SA.uMsg == WM_LBUTTONDOWN)
			{
				SortAcChinese();
				//Refresh reload
				ShowAllInfor();

			}
		}
		else if (SA.x >= 690 && SA.x <= 850 && SA.y >= 190 && SA.y <= 240)
		{
			//By math
			setlinecolor(RED);
			rectangle(690, 190, 850, 240);
			if (SA.uMsg == WM_LBUTTONDOWN)
			{
				SortAcMath();
				//Refresh reload
				ShowAllInfor();
			}
		}
		else if (SA.x >= 690 && SA.x <= 850 && SA.y >= 290 && SA.y <= 340)
		{
			//In English
			setlinecolor(RED);
			rectangle(690, 290, 850, 340);
			if (SA.uMsg == WM_LBUTTONDOWN)
			{
				SortAcEnglish();
				//Refresh reload
				ShowAllInfor();
			}
		}
		else if (SA.x >= 690 && SA.x <= 850 && SA.y >= 390 && SA.y <= 440)
		{
			//According to the total score
			setlinecolor(RED);
			rectangle(690, 390, 850, 440);
			if (SA.uMsg == WM_LBUTTONDOWN)
			{
				SortAcSumScore();
				//Refresh reload
				ShowAllInfor();
			}

		}
		else if (SA.x >= 690 && SA.x <= 850 && SA.y >= 590 && SA.y <= 640)
		{
			//return
			setlinecolor(RED);
			rectangle(690, 590, 850, 640);
			if (SA.uMsg == WM_LBUTTONDOWN)
			{
				cleardevice();
				//Judge which window you came in from
				if (FlagAI == 1)
				{
					AdminPage();
				}
				else if (FlagAI == -1)
				{
					CommonUserPage();
				}

			}
		}
		else
		{
			setlinecolor(WHITE);
			rectangle(690, 90, 850, 140);
			rectangle(690, 190, 850, 240);
			rectangle(690, 290, 850, 340);
			rectangle(690, 390, 850, 440);
			rectangle(690, 590, 850, 640);

		}

	}

}

//Returns the subscript of the structure where the person to be found / modified / deleted is located
int ReturnPosi()
{
	//Receive user input
	char ReceInput[64];
	TCHAR InputWindowFI[] = _T("Please enter your student number or name for registration(lookup)(modify)(delete)");
	InputBox(ReceInput, 10, InputWindowFI);

	//Perform a loop search, and jump out of the loop once it is the same
	for (int w = 0; w < NowStudentNums; w++)
	{
		if (strcmp(StuArry[w].s_Name, ReceInput) == 0 || strcmp(StuArry[w].s_Num, ReceInput) == 0)//Returning 0 means that the two strings are equal
		{
			return w;
		}
	}
	//If you don't find this person, return - 1
	return -1;
}


//Print information about people found
void PrintFoudInfor(int Position)
{
	//Mouse operation
	MOUSEMSG PFI;
	initgraph(860, 760);

	



	cleardevice();
	IMAGE picture2;
	loadimage(&picture2, "./secondbc.jpg", 860, 760);
	putimage(0, 0, &picture2);

	
	

	setfillcolor(GREEN);
	fillrectangle(690, 590, 850, 640);
	setbkmode(TRANSPARENT);

	//Header text
	settextstyle(30, 0, "Blackbody");
	outtextxy(40, 100, "Student number");
	outtextxy(200, 100, "full name");
	outtextxy(300, 100, "language");
	outtextxy(400, 100, "mathematics");
	outtextxy(500, 100, "English");
	outtextxy(600, 100, "Total score");
	outtextxy(740, 600, "return");

	//Print the information of the searched person


	//Student number
	outtextxy(40, 140, StuArry[Position].s_Num);
	//full name
	outtextxy(200, 140, StuArry[Position].s_Name);
	//grade scores of Chinese
	outtextxy(300, 140, StuArry[Position].s_Chinese);
	//Mathematics achievement
	outtextxy(400, 140, StuArry[Position].s_Math);
	//English achievement
	outtextxy(500, 140, StuArry[Position].s_English);
	//Total output score
	char SuSo[20];
	sprintf(SuSo, "%.2f", StuArry[Position].s_SumScore);//Keep two digits after the decimal point
	outtextxy(600, 140, SuSo);

	while (1)
	{
		PFI = GetMouseMsg();
		if (PFI.x >= 690 && PFI.x <= 850 && PFI.y >= 590 && PFI.y <= 640)
		{
			//return
			setlinecolor(RED);
			rectangle(690, 590, 850, 640);
			if (PFI.uMsg == WM_LBUTTONDOWN)
			{
				cleardevice();
				if (FlagFPT == 1)
				{
					AdDeSeMoPage();
				}
				else if (FlagFPT = -1)
				{
					CommonUserPage();
				}
			}
		}
		//Mouse not on Option
		else
		{
			setlinecolor(WHITE);
			rectangle(690, 590, 850, 640);
		}

	}
}


//Query - this is responsible for the final call
void PrintFoudInfor()
{
	//Define a variable to receive subscripts
	int TempPosi = ReturnPosi();
	if (TempPosi == -1)//Can't find
	{
		//Get window handle
		HWND hndtipsF = GetHWnd();
		//Summarize sentences with an array of characters
		int isok = MessageBox(hndtipsF, "No one was found!", "Tips", MB_OK);
	}
	else//Found - printout
	{
		cleardevice();
		PrintFoudInfor(TempPosi);
	}
}

//Modify the student information, find the return subscript, assign a new value to him, and save it. Otherwise, a window will pop up directly for warning
void ModifyStudInfor()
{
	//Directly apply the above search operation and add a line before modification
	//Because you need to get the position subscript of the person to be modified in the structure array, you can't take the function directly, you have to paste it
	//Define a variable to receive subscripts
	int TempModi = ReturnPosi();
	if (TempModi == -1)//Can't find
	{
		//Get window handle
		HWND hndtipsM = GetHWnd();
		//Summarize sentences with an array of characters
		int isok = MessageBox(hndtipsM, "No one was found!", "Tips", MB_OK);
	}
	else//Find the student and do the following
	{
		cleardevice();
		//Mouse operation
		MOUSEMSG Modi;
		initgraph(860, 760);



		IMAGE picture2;
		loadimage(&picture2, "./secondbc.jpg", 860, 760);
		putimage(0, 0, &picture2);


		setfillcolor(GREEN);
		fillrectangle(690, 590, 850, 640);

		//Header text
		setbkmode(TRANSPARENT);
		settextstyle(50, 0, "Blackbody");
		outtextxy(40, 40, "Before modification");
		outtextxy(40, 240, "After modification");
		settextstyle(30, 0, "Blackbody");
		outtextxy(40, 100, "Student number");
		outtextxy(200, 100, "full name");
		outtextxy(300, 100, "language");
		outtextxy(400, 100, "mathematics");
		outtextxy(500, 100, "English");
		outtextxy(600, 100, "Total score");
		outtextxy(740, 600, "return");

		outtextxy(40, 300, "Student number");
		outtextxy(200, 300, "full name");
		outtextxy(300, 300, "language");
		outtextxy(400, 300, "mathematics");
		outtextxy(500, 300, "English");
		outtextxy(600, 300, "Total score");

		//Print the information of the searched person
		//Student number
		outtextxy(40, 140, StuArry[TempModi].s_Num);
		//full name
		outtextxy(200, 140, StuArry[TempModi].s_Name);
		//grade scores of Chinese
		outtextxy(300, 140, StuArry[TempModi].s_Chinese);
		//Mathematics achievement
		outtextxy(400, 140, StuArry[TempModi].s_Math);
		//English achievement
		outtextxy(500, 140, StuArry[TempModi].s_English);
		//Total output score
		if (strlen(StuArry[TempModi].s_Name) != 0)
		{
			char SuSo1[20];
			sprintf(SuSo1, "%.2f", StuArry[TempModi].s_SumScore);//Keep two digits after the decimal point
			outtextxy(600, 140, SuSo1);
		}







		//Add input pop-up - rewrite content

		//Modify student number
		while (1)
		{
			//The student number used to receive the input is overwritten first
			char TempModiNums[64];

			TCHAR InputWindow0[] = _T("Please enter the student number of the student");
			InputBox(TempModiNums, 9, InputWindow0);

			if (strcmp(TempModiNums,StuArry[TempModi].s_Num)==0)//If the student number entered is the same as the student number in its own position
			{
				//Don't make changes, break directly
				break;
			}
			else//If the entered student number is different from the student number in its own position, you need to judge whether there is a duplicate with the whole structure
			{
				int FlagInput3 = 0;

				int nums = strlen(TempModiNums);

				//Judge whether the input is a pure number
				for (int i = 0; i < nums; i++)
				{
					if (TempModiNums[i] >= '0' && TempModiNums[i] <= '9')//If it's not a number
					{

					}
					else
					{
						FlagInput3 = 1;
						HWND hwndInput3 = GetHWnd();
						int isok = MessageBox(hwndInput3, "The input format is incorrect, please re-enter", "Tips", MB_OK);
						break;
					}
				}

				if (FlagInput3 == 0)
				{
					//Why does the newly entered student number appear in the structure array,
					//Because this is a modification function, the student number entered above has covered the position he should obtain,
					/*
					Train of thought 1 Don't overwrite the value you want, judge first
							Judge whether the completion meets the conditions, and then assign the value to it,
					Train of thought 2 Copy the original student structure array
							 Traverse the judgment in the new structure array


							 //Choose the first one here
					*/
					//Determine whether the input is duplicate
					int FlagInput4 = 0;
					for (int i = 0; i < NowStudentNums; i++)
					{
						if (strcmp(TempModiNums, StuArry[i].s_Num) == 0)
						{
							FlagInput4 = 1;
							break;
						}
					}
					if (FlagInput4 == 1)
					{
						HWND hwndInput4 = GetHWnd();
						int isok = MessageBox(hwndInput4, "This student already exists, please re-enter", "Tips", MB_OK);
					}
					else if (FlagInput4 == 0)
					{
						//cover
						memcpy(TempModiNums, StuArry[TempModi].s_Num, nums);
						break;
					}
				}
			}
		}

		//Modify name
		TCHAR InputWindow1[] = _T("Please enter the student's name");
		InputBox(StuArry[TempModi].s_Name, 10, InputWindow1);

		//Input Chinese score
		while (1)
		{
			TCHAR InputWindow2[] = _T("Please enter the student's language score");
			InputBox(StuArry[TempModi].s_Chinese, 4, InputWindow2);

			if (ScoreFormat(StuArry[TempModi].s_Chinese))//Jump out of loop for true
			{
				break;
			}

		}





		//Enter math scores
		while (1)
		{
			TCHAR InputWindow3[] = _T("Please enter the student's math score");
			InputBox(StuArry[TempModi].s_Math, 4, InputWindow3);

			if (ScoreFormat(StuArry[TempModi].s_Math))//Jump out of loop for true
			{
				break;
			}

		}


		//Enter English score
		while (1)
		{
			TCHAR InputWindow4[] = _T("Please enter the student's English score");
			InputBox(StuArry[TempModi].s_English, 4, InputWindow4);

			if (ScoreFormat(StuArry[TempModi].s_English))//Jump out of loop for true
			{
				break;
			}

		}

		//final scoring 
		StuArry[TempModi].s_SumScore =
			atof(StuArry[TempModi].s_Chinese) +
			atof(StuArry[TempModi].s_Math) +
			atof(StuArry[TempModi].s_English);

		//Print the information of the searched person
		//Student number
		outtextxy(40, 340, StuArry[TempModi].s_Num);
		//full name
		outtextxy(200, 340, StuArry[TempModi].s_Name);
		//grade scores of Chinese
		outtextxy(300, 340, StuArry[TempModi].s_Chinese);
		//Mathematics achievement
		outtextxy(400, 340, StuArry[TempModi].s_Math);
		//English achievement
		outtextxy(500, 340, StuArry[TempModi].s_English);
		//Total output score - add a constraint
		if (strlen(StuArry[TempModi].s_Name) != 0)
		{
			char SuSo2[20];
			sprintf(SuSo2, "%.2lf", StuArry[TempModi].s_SumScore);//Keep two digits after the decimal point
			outtextxy(600, 340, SuSo2);
		}

		//Save file
		SaveInforModi();





		while (1)
		{
			Modi = GetMouseMsg();
			if (Modi.x >= 690 && Modi.x <= 850 && Modi.y >= 590 && Modi.y <= 640)
			{
				//return
				setlinecolor(RED);
				setlinecolor(RED);

				rectangle(690, 590, 850, 640);
				if (Modi.uMsg == WM_LBUTTONDOWN)
				{
					cleardevice();
					//Return to the add, delete, query and modify interface
					AdDeSeMoPage();

					//Auxiliary test - displays the current number of people
					/*char temptps[5];
					sprintf(temptps, "%d", NowStudentNums);


					HWND hwndTemp = GetHWnd();
					int tips2 = MessageBox(hwndTemp, temptps, "Prompt ", MB_OK);*/
				}
			}
			//Mouse does not hover
			else
			{
				setlinecolor(WHITE);

				rectangle(690, 590, 850, 640);

			}
		}
	}
}

//Delete a student's information
void DeSomeStu()
{
	//First search, find the returned subscript, then push the data behind the subscript forward in turn, and finally find the number of people--
	//If you don't find him, you can't find him
	//lookup
	// 
	//Because the functions to be implemented are different, the lookup function cannot be called directly
	//Define a variable to receive subscripts
	int TempDelt = ReturnPosi();
	if (TempDelt == -1)//Can't find
	{
		//Get window handle
		HWND hndtipsD = GetHWnd();
		//Summarize sentences with an array of characters
		int isok = MessageBox(hndtipsD, "No one was found!", "Tips", MB_OK);
	}
	else//Found, confirm to delete
	{
		//If it is found, you will be prompted whether to delete it
		//Get window handle
		//delete sure?
		HWND hndtipsDS = GetHWnd();
		//Summarize sentences with an array of characters
		int isok = MessageBox(hndtipsDS, "Are you sure to delete?", "Tips", MB_OKCANCEL);
		if (isok == IDOK)
		{
			//Confirm delete operation
			//Migrate the next of this element in turn
			for (int d = TempDelt; d < NowStudentNums - 1; d++)
			{
				StuArry[d] = StuArry[d + 1];
			}
			//Current number - 1
			NowStudentNums--;
			//The deletion only clears the data in the current structure, but no changes are made in the file
			//Update to file
			SaveInforModi();//Use this all empty function to rewrite the file
		}
		else if (isok == IDCANCEL)
		{
			//Cancel delete without performing any action
		}
	}

}

//Sort according to Chinese scores
void SortAcChinese()
{
	//Use bubble sorting to sort students according to Chinese scores


	//Use a loop to save everyone's grades into the structural array of grades
	for (int i = 0; i < NowStudentNums; i++)
	{
		SoArry[i].SuScore = atof(StuArry[i].s_Chinese);
	}
	//Sort structures

	//Note: when sorting with two structures, that is, when one structure assists the other in sorting,
	//Note that the two needs change at the same time, and both structures need to change to accumulate experience

	for (int r = 0; r < NowStudentNums; r++)
	{
		Score TempScore;
		Student TempStudent;
		for (int j = 1; j < NowStudentNums - r; j++)
		{
			if (SoArry[j - 1].SuScore < SoArry[j].SuScore)
			{
				TempScore = SoArry[j];
				TempStudent = StuArry[j];

				SoArry[j] = SoArry[j - 1];
				StuArry[j] = StuArry[j - 1];

				SoArry[j - 1] = TempScore;
				StuArry[j - 1] = TempStudent;
			}
		}
	}
	//You don't need to save it. By default, it is sorted in the order of addition
}

//Sort according to math scores
void SortAcMath()
{
	//Each assignment to the score structure array will be overwritten

	//Use a loop to save everyone's grades into the structural array of grades
	for (int i = 0; i < NowStudentNums; i++)
	{
		SoArry[i].SuScore = atof(StuArry[i].s_Math);
	}
	//Sort structures

	//Note: when sorting with two structures, that is, when one structure assists the other in sorting,
	//Note that the two needs change at the same time, and both structures need to change to accumulate experience

	for (int t = 0; t < NowStudentNums; t++)
	{
		Score TempScore;
		Student TempStudent;
		for (int j = 1; j < NowStudentNums - t; j++)
		{
			if (SoArry[j - 1].SuScore < SoArry[j].SuScore)
			{
				TempScore = SoArry[j];
				TempStudent = StuArry[j];

				SoArry[j] = SoArry[j - 1];
				StuArry[j] = StuArry[j - 1];

				SoArry[j - 1] = TempScore;
				StuArry[j - 1] = TempStudent;
			}
		}
	}
	//You don't need to save it. By default, it is sorted in the order of addition
}

//Sort according to English scores
void SortAcEnglish()
{
	//Each assignment to the score structure array will be overwritten

	//Use a loop to save everyone's grades into the structural array of grades
	for (int i = 0; i < NowStudentNums; i++)
	{
		SoArry[i].SuScore = atof(StuArry[i].s_English);
	}
	//Sort structures

	//Note: when sorting with two structures, that is, when one structure assists the other in sorting,
	//Note that the two needs change at the same time, and both structures need to change to accumulate experience
	//Because the order is the same, you can think of two as one

	for (int y = 0; y < NowStudentNums; y++)
	{
		Score TempScore;
		Student TempStudent;
		for (int j = 1; j < NowStudentNums - y; j++)
		{
			if (SoArry[j - 1].SuScore < SoArry[j].SuScore)
			{
				TempScore = SoArry[j];
				TempStudent = StuArry[j];

				SoArry[j] = SoArry[j - 1];
				StuArry[j] = StuArry[j - 1];

				SoArry[j - 1] = TempScore;
				StuArry[j - 1] = TempStudent;
			}
		}
	}
	//You don't need to save it. By default, it is sorted in the order of addition
}

//Sort by total score
void SortAcSumScore()
{
	for (int i = 0; i < NowStudentNums; i++)
	{
		Student TempStudent;
		for (int j = 1; j < NowStudentNums - i; j++)
		{
			if (StuArry[j - 1].s_SumScore < StuArry[j].s_SumScore)
			{

				TempStudent = StuArry[j];


				StuArry[j] = StuArry[j - 1];


				StuArry[j - 1] = TempStudent;
			}
		}
	}
}


//Administrator login
void AdminSignIn()
{
	//Open the file and read the account and password
	FILE* fp = fopen("AdminSignIn.txt", "r");
	if (fp == NULL)
	{
		return;
	}
	//Read the corresponding administrator structure array
	fscanf(fp, "%s\t%s\t\n", AdminUser.UserName, AdminUser.PassWord);

	//Close file
	fclose(fp);




	char ReceAcctNumber[64];
	TCHAR InputAcct[] = _T("enter one user name");
	InputBox(ReceAcctNumber, 10, InputAcct);

	char ReceAcctPassWord[64];
	TCHAR InputPass[] = _T("Please input a password");
	InputBox(ReceAcctPassWord, 10, InputPass);

	//If the user name and password are correct, it will progress to the administrator interface
	//Otherwise, an error will pop up
	if (strcmp(AdminUser.UserName, ReceAcctNumber) == 0 && strcmp(AdminUser.PassWord, ReceAcctPassWord) == 0)
	{
		cleardevice();
		AdminPage();
	}
	else
	{
		HWND SignError = GetHWnd();
		int isok = MessageBox(SignError, "Wrong user name or password!", "Tips", MB_OK);
	}
}



int main(void)
{
	FirstPage();
	return 0;
}

Topics: C easyx