Student achievement management system
1, Design task analysis
The main purpose of this topic is to manage students' grades. You can enter scores, query scores, delete score records, and rank scores. Facilitate the unified processing of students' scores after the examination.
2, Design of the overall scheme of student achievement management system
2.1 system database
The system uses a text document (. txt) to store data. The data items of the database mainly include: student number, name, grade, major, grade 1, grade 2, grade 3, average score and total score.
Each data is separated by a tab to facilitate subsequent writing and reading of data. Because there are many data items, I designed two classes to store these data items: grade class and student class.
2.2 class description
- Score: including five data items: score 1, score 2, score 3, average score and total score.
- Student: including five data items: student number, name, grade, major and grade.
- Administrator class (Manager): there are two attributes: the path of the file storing records and the students of vector < student * > type, as well as various operations such as adding, deleting and querying grades. Students store the address of the object encapsulated by the records in the database file, manager CPP contains the main() function.
2.3 procedure flow
At the beginning of the program, the data in the text document is loaded into the variable length array students for later operation. Display the main page, let the user input and select, and then perform the corresponding functions.
The procedure flow chart is as follows:
2.4 function module
The system mainly has six functions: add function, delete function, modify function, search function, display function and sorting function.
2.4.1. Add function (add)
- Execution process: first enter the student number and call read_ The number() function judges the input. If the student number is reasonable, call the checkId() function to check the student number. If it has been occupied and needs to be modified, call the update() function to modify it. If it is not occupied, start to input other data items and still call read_ The number () function checks these data items to see if they are reasonable. If all data items are reasonable, they are encapsulated, added to the variable length array students, and stored in the text document; If it is unreasonable, let the user re-enter. All input items are input errors for three times, which directly ends the function.
The procedure flow chart is as follows:
2.4.2 delete function (delete_)
- Execution process: first call * * isEmpty() function to determine whether there is data. If there is data, let the user input the student number corresponding to the record to be deleted and call read_ The number() function determines whether the input is reasonable. Call findById() to find the location of the item to be deleted. The search is deleted in the variable length array students, and then called saveAll() * to save the deleted students to the file. If the search fails, the function ends.
The procedure flow chart is as follows:
2.4.3. Modify function (update)
-
Execution process: first call * * isEmpty() function to determine whether there is data. If there is data, enter the student number corresponding to the record to be modified and call read_ The number() function determines whether the input is reasonable. Call findById() to find the location of the item to be modified. The search is modified in the variable length array students, and then calls saveAll() * to save the modified students to the file. If the search fails, the function ends.
-
Modify operation: enter the number corresponding to the data item to be modified to modify. After modification, ask whether to continue to modify the record. If yes, continue to modify; Otherwise, the function ends.
The procedure flow chart is as follows:
2.4.4. Search function (query())
-
The search function can query findByName(), findByScore(), and findById() by student number. When searching by name, it is to search in order. First judge whether the length of the name is consistent, and then compare the name string by character. Comparing one character can narrow the range of possible results, find the final result set through layer by layer filtering, and return an array. When searching by score, half search is used to find all qualified results through recursion. When searching with the student number, the half search is also used, but because the student number is unique, there is no need for recursion.
-
Execution process: first call * * isEmpty() * * function to determine whether there is data. If there is data, the function page is displayed to allow the user to enter the number of the corresponding search method. Before performing the corresponding search operation, the data shall be sorted accordingly. If the query is successful, the query result will be returned and displayed, and the user will be asked whether to save it to the file, and the corresponding operation will be performed according to the input. If the query fails, the function ends.
The procedure flow chart is as follows:
2.4.5 display function
-
Execution process: first call * * isEmpty() * * function to determine whether there is data. If there is data, traverse the record array students loaded at the beginning of the program and print the records. Due to the large amount of data, the operation of pagination display is adopted.
-
Paging operation: only 10 records are displayed on a page by operating the subscript recorded in the array.
The procedure flow chart is as follows:
2.4.6 sorting function (order)
-
There are two sorting methods: sorting by student number and sorting by grade. You can select the sorting method by entering the corresponding number. Bubble sorting is used here, because when sorting by grade, other grades will be basically ordered after sorting once.
-
Execution process: first call isEmpty() function to determine whether there is data. If there is data, sort the loaded array of records at the beginning of the program. After sorting, call the **saveAll() * function to overwrite the original data into the file students.
The procedure flow chart is as follows:
2.5 core algorithm
2.5.1,getAll(),isEmpty()
- getAll(): get the data, use the fstream file stream to read the data according to the defined file, and save it to the variable length array students.
while (fs >> id >> name >> grade >> pf >> score_1 >> score_2 >> score_3 >> avg >> sum) { Score score(score_1, score_2, score_3); students.push_back(new Student(id, name, grade, pf, score)); i++; }
- isEmpty(): judge whether there is data. Yes, return 1; On the contrary, ask if you want to add a record and return 0.
if (students.empty()) { //No record cout << "There is no record yet. Do you want to add a record? "; if (ch == "y" || ch == "Y") { add(); //Perform the add operation } }
2.5.2,getFileName(),save(),saveAll()
- getFilename(): get the file name to assist the function of searching by name. Provide a file name when the search results need to be saved. The file name needs char * type, and the name type is string type, so use * * getFilename() to convert the name of string type into char array type, and then use the sprintf() * * function to format the string and splice a file name.
for (int i = 0; i < name.length(); i++) name_c[i] = name[i]; //Convert string type to char array type name_c[name.length()] = '\0'; sprintf(filename, "name=%s.txt", name_c);
- save(): save a single record. According to the stu passed in, it is written to the file with file stream.
fs << stu->getId() << "\t" << stu->getName() << "\t" << stu->getGrade() << "\t" << stu->getPf() << "\t" << stu->getScore().getScore_m() << "\t" << stu->getScore().getScore_c() << "\t" << stu->getScore().getScore_e() << "\t" << stu->getScore().getAvg() << "\t" << stu->getScore().getSum() << endl;
- saveAll(): save multiple pieces of data. According to the variable length array stus and file name passed in, call the save() function to save one by one. The save() function uses the fsstream file stream to write the passed in content to the corresponding file.
for (int i = 0; i < stus.size(); i++) { save(stus.at(i), filename)
2.5.3 verify input read_choose(),read_Number(),checkId()
Because the program needs to input data in many places, it is necessary to check the rationality of the data. Regular expressions are mainly used here. When the * * scanf() * * function reads data, match the data to judge whether it is reasonable.
-
Regular expression:% [] means reading in a character set, and "[" followed by "^" means taking non; * means not saving the data, that is, skipping the qualified string.
-
read_choose(): check whether the number entered when selecting the corresponding function is reasonable:
int ret1 = scanf("%d", &choose); //Get the number and return 1; Otherwise, return 0 if (!ret1) //If the number cannot be read, all the input contents will be read and filtered out scanf("%*[^'\n']"); scanf("%*[' ']"); //Read all the spaces int ret2 = scanf("%[^'\n']", temp); //^Indicates non. Gets all non newline characters scanf("%*c"); //Read a character, * means it is not saved to the variable. That is, get a newline character
- read_Number(): check whether the input data is reasonable. The data here includes students' grades and student numbers. It is mainly used to check the corresponding input when adding records and finding records.
if (!flag) //When flag==0, read the student number; Otherwise, read the score ret1 = scanf("%ld", &id); else ret1 = scanf("%lf", &score); if (!ret1) { scanf("%*[^'\n']"); } scanf("%*[' ']"); int ret2 = scanf("%[^\n]", temp); scanf("%*c");
- checkId(): check whether the student number has been occupied. Call the * * findById() * * function to find it. If the search is successful, it indicates that the student number has been occupied. Ask whether you want to modify the information of the student number. If the lookup fails, - 1 is returned.
findById(id, index); //Find with this student number if (index != -1) { //If the search is successful, the student number has been occupied cout << "The student of this student number has records. Do you want to modify it?\n input'y'Modify, enter other and return."; string choose; cin >> choose; if (choose == "y" || choose == "Y") { system("cls"); update(id); //Modify record } } return index;
2.5.4 pagination display
Traverse the variable length array students and control the subscript so that only 10 records are displayed per page. According to 10 records per page and the subscript of the current record in the array, the current page number and total pages are displayed at the bottom of each page. Enter the corresponding instruction to view the previous page, the next page and jump to the specified page. i is the subscript of the lowest record of the currently displayed page in the variable length array students.
-
When viewing the previous page, you need to judge whether there will be a previous page, that is, whether it is the first page (there is no previous page). If there is a previous page, make I = I - (I% 10) - 11, that is, find the subscript of the first record on the previous page in the variable length array students minus 1, because it will be followed by 1.
-
When viewing the next page, you need to judge whether there will be a next page, that is, whether it is the last page (there is no next page).
-
To jump to the page of the corresponding page number, the * * atoi() * * function in the string library is used, which converts the input string into a number, and then assigns it to the variable representing the subscript of the record, so that you can directly jump to the corresponding page.
page= atoi(cho.c_str()); //Convert string to number if (page >= 1 && page <= ((count - 1) / 10 + 1)) i = (page - 1) * 10 - 1; //Skip to the corresponding page number else if (cho == "n" || cho == "N") { //Enter n or n for the next page if (i == count - 1) { cout << "It is the last page at present. There is no next page!\n"; //Count starts from 1 and i starts from 0, so count starts with - 1 i = (count - 1) - ((count - 1) % 10) - 1; } } else if (cho == "s" || cho == "S") { //Enter s or s for the previous page i = i - (i % 10) - 11; //Subscript-1 of the first record on the previous page if (i < -1) { cout << "It is the first page at present. There is no previous page!\n"; i = -1; //Reassign to the subscript-1 of the first record on the first page } } else //Enter another to exit directly break;
2.5.5 sorting
Since the results are sorted once, other results become basically orderly, so bubble sorting is used here. Sorting is divided into sorting by grades and sorting by student number, and its implementation method is the same.
for (int i = 0; i < count - 1; i++) {//Sort by grade (from large to small) int flag_break = true; for (int j = 0; j < count - 1 - i; j++) { if (students.at(j + 1)->getScore(ch) > students.at(j)->getScore(ch)) { swap(j, j + 1); //Swap two objects flag_break = false; } } if (flag_break) break; }
2.5.6 search
When searching by name, we use sequential search, and when searching by score or student number, we use half search.
- Search by name findByName(): len is the length of the name string. When searching in order, first compare whether the lengths of the two names are consistent, and then compare the first character. If they are the same, they will be added to the result array. Then compare the second character of the possible result in the result array with the parameter name. If it is the same, add it to the emptied result array and compare all the characters of the name string in turn. The final result array is the final result.
while (ct < len) { //ct is the subscript of the name string, and len is the length of the name string temp = result; result = temp_null; for (int i = 0; i < temp.size(); i++) { string name_ = temp.at(i)->getName(); if (name_.length() == len) { //Compare the same length if (name_[ct] == name[ct]) result.push_back(temp.at(i)); } } ct++; }
- Find findById() by student number: it is unique when the student number is specified, so you can directly use half search.
while (left <= right) { mid = (left + right) / 2; if (students.at(mid)->getId() == id) { index = mid; return students.at(mid); } else if (id < students.at(mid)->getId()) right = mid - 1; else left = mid + 1; } index = -1; //-1 means query failed
- Find findByScore(): because the score is not unique, there may be multiple results, so the recursion of half search is used here. First find a result, and then half search the left and right parts to find all qualified results.
while (left <= right) { mid = (left + right) / 2; if (students.at(mid)->getScore(flag) == score) { //index=mid; temp.push_back(students.at(mid)); Search_bin(temp, flag, score, low, mid - 1); //Recursive left half Search_bin(temp, flag, score, mid + 1, high); //Recursive right half break; //Exit loop } else if (score > students.at(mid)->getScore(flag)) right = mid - 1; else left = mid + 1; }
source code
include.h
#pragma once #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<fstream> // File stream #include<cstdlib> //atoi,system #include<vector> // Variable length array #include<iomanip> // Control cout output format #include<windows. h> // Sleep() and color settings using namespace std;
score.h
#pragma once #include "include.h" class Score { private: double score_m; //Mathematics achievement double score_c; //grade scores of Chinese double score_e; //English achievement double avg; //Average score double sum; //Total score public: Score(); //Nonparametric structure Score(double m, double c, double e); void setScore_m(double score_m); double getScore_m(); void setScore_c(double score_c); double getScore_c(); void setScore_e(double score_e); double getScore_e(); double getAvg(); //Get average score double getSum(); //Get total score void show_score(); //Show score };
score.cpp
#include"score.h" Score::Score() { //non-parameter constructor } //Constructor Score::Score(double m, double c, double e) { this->score_m = m; this->score_c = c; this->score_e = e; this->avg = 1; //getAvg(); this->sum = 1;//getSum(); } void Score::setScore_m(double score_m) { this->score_m = score_m; } double Score::getScore_m() { return this->score_m; } void Score::setScore_c(double score_c) { this->score_c = score_c; } double Score::getScore_c() { return this->score_c; } void Score::setScore_e(double score_e) { this->score_e = score_e; } double Score::getScore_e() { return this->score_e; } //Show score information void Score::show_score() { cout << "Math scores:" << this->score_m << endl; cout << "Language achievement:" << this->score_c << endl; cout << "English score:" << this->score_e << endl; printf("Average score:%.2lf\n", getAvg()); printf("Total score:%.2lf\n", getSum()); } //Calculate average score double Score::getAvg() { double avg = (score_m + score_c + score_e) / 3; return avg; } //Calculate total score double Score::getSum() { double sum = score_m + score_c + score_e; return sum; }
student.h
#pragma once #include "score.h" class Student { private: long id; //Student number string name; //full name string grade; //grade string pf; //major Score score; //achievement public: Student(); Student(long id, string name, string grade, string pf, Score score); void setId(long id); long getId(); void setName(string name); string getName(); void setGrade(string grade); string getGrade(); void setPf(string pf); string getPf(); void setScore(Score score); void setScore(double score1, double score2, double score3); Score getScore(); //Get score object double getScore(int num); //Get the score of the corresponding serial number };
student.cpp
#include "student.h" //non-parameter constructor Student::Student() { } //Parameterized constructor Student::Student(long id, string name, string grade, string pf, Score score) { this->id = id; this->name = name; this->grade = grade; this->pf = pf; this->score = score; } void Student::setId(long id) { this->id = id; } long Student::getId() { return this->id; } void Student::setName(string name) { this->name = name; } string Student::getName() { return this->name; } void Student::setGrade(string grade) { this->grade = grade; } string Student::getGrade() { return this->grade; } void Student::setPf(string pf) { this->pf = pf; } string Student::getPf() { return this->pf; } void Student::setScore(Score score) { this->score = score; } void Student::setScore(double score1, double score2, double score3) { if (score1 > 0) this->score.setScore_m(score1); if (score2 > 0) this->score.setScore_c(score2); if (score3 > 0) this->score.setScore_e(score3); } Score Student::getScore() { return this->score; } double Student::getScore(int num) { switch (num) { case 1: //Total score return getScore().getSum(); case 2: //Mathematics achievement return getScore().getScore_m(); case 3: //grade scores of Chinese return getScore().getScore_c(); case 4: //English achievement return getScore().getScore_e(); } }
SMS.h
#pragma once #include "student.h" #define _CRT_SECURE_NO_WARNINGS class Manager { public: static const char* getPath(); //Gets the file path where the record is stored vector<Student*> getStudents(); //Get all records void clear(); //Clear screen void show_back(int flag = 0); //Show return information void show_to(); //Display entry information int checkId(long id); //Check whether the student number is the same double read_Number(long& id); //Read the score and check whether the score is reasonable void add(); //Add record void delete_(); //Delete record int read_choose(int left, int right); //Read selection int update(long id = -1); //Modify record int update(Student* stu); //Modify record int isEmpty(); //Judge whether the record is empty void getFilename(string name, char filename[]); //Get file name void Search_bin(vector<Student*>& temp, int flag, double score, int left, int right); //Half search Student* findById(long id, int& index); //find record vector<Student*> findByScore(double score, int& index, int flag); vector<Student*> findByName(string name, int& index); void query(int cho); //Query function void show(Student* stu); //Show single record void color(int i); void showHeader(); //Display header void display(vector<Student*> stus, int flag = 0);//Show all records void swap(int i, int j); //exchange void order(int ch, int flag = 0); //Sorting function string isSave(); //Do you want to save void save(Student* stu, int flag, const char* filename = "stu_score.txt"); //Save a single record void saveAll(vector<Student*> stus, const char* filename = "stu_score.txt"); //Save multiple records int getAll(); //Get all records private: static const char* path; //The path to the file where the record is stored vector<Student*> students; //Keep all the records };
SMS.cpp
#include "SMS.h" //Global variable. The whole program has only one Manager object Manager manager; //Initialize class static member variables. Save path of all records const char* Manager::path = "stu_score.txt"; //Gets the file path where the record is stored const char* Manager::getPath() { return path; } //Get all records vector<Student*> Manager::getStudents() { return students; } //Clear screen void Manager::clear() { system("pause"); system("cls"); } //Get all records, encapsulate them, and return the total number of records int Manager::getAll() { long id; string name, grade, pf; double score_1, score_2, score_3, avg, sum; //achievement int i = 0; fstream fs; fs.open(getPath(), ios::in); //The first parameter requires a char * type, not a string type while (fs >> id >> name >> grade >> pf >> score_1 >> score_2 >> score_3 >> avg >> sum) { Score score(score_1, score_2, score_3); students.push_back(new Student(id, name, grade, pf, score)); i++; } fs.close(); return students.size(); //Returns the total number of records } //Check whether the student number has been used int Manager::checkId(long id) { order(5, 1); //Sort by student number first int count = students.size(); int index; findById(id, index); //Find with this student number if (index != -1) { //If the search is successful, the student number has been occupied cout << "The student of this student number has records. Do you want to modify it?\n input'y'Modify, enter other and return."; string choose; cin >> choose; if (choose == "y" || choose == "Y") { system("cls"); update(id); //Modify record } } return index; } //Use regular expressions to determine whether the input is correct //When id==0, read the student number; Otherwise, read the score double Manager::read_Number(long& id) { long flag = id; //0: student number; 1: Achievements; 2: Total score double score = 101; int ct = 3; while (true) { char temp[32]; //Save non numeric characters //Get the number and return 1; Otherwise, return 0 int ret1; if (!flag) ret1 = scanf("%ld", &id); else ret1 = scanf("%lf", &score); if (!ret1) { //If no number is read, all the input contents are obtained and filtered out scanf("%*[^'\n']"); } scanf("%*[' ']"); //Read the space //^Indicates non. That is, get all characters that are not newline characters //Get, return 1; Otherwise, return 0 int ret2 = scanf("%[^\n]", temp); scanf("%*c"); //Read a character, * means it is not saved to the variable. That is, get a newline character //A number is read and there are no non newline characters after the number if (ret1 && !ret2 && flag == 0 && (id >= 1000000 && id <= 9999999)) return score; //Student number else if (ret1 && !ret2 && flag == 1 && (score >= 0 && score <= 100)) return score; //achievement else if (ret1 && !ret2 && flag == 2 && (score >= 0 && score <= 300)) return score; //Total score else if (ct == 0) { return -1; //Input error three times, return 1 } else { cout << "Input error, please re-enter(also" << ct-- << "Second chance): "; } } } //Add record void Manager::add() { Student* stu = new Student; //Student object long id = 0; //Student number long temp = 1; //Temporary variable string name; //full name string grade; //grade string pf; //major double score1; //Mathematics achievement double score2; //grade scores of Chinese double score3; //English achievement cout << "Please enter 7 digits of student ID (e.g. 2021000):"; if (read_Number(id) == -1) { clear(); return; } if (checkId(id) == -1) { //The student number is not occupied stu->setId(id); cout << "Please enter the student's name, grade and major respectively: \n"; cin >> name >> grade >> pf; stu->setName(name); stu->setGrade(grade); stu->setPf(pf); cout << "Please enter the student's math score:"; score1 = read_Number(temp); if (score1 == -1) { cout << "Failed to add!\n"; clear(); return; } cout << "Please enter the student's language score:"; score2 = read_Number(temp); if (score2 == -1) { cout << "Failed to add!\n"; clear(); return; } cout << "Please enter the student's English score:"; score3 = read_Number(temp); if (score3 == -1) { cout << "Failed to add!\n"; clear(); return; } Score score(score1, score2, score3); //Achievement object stu->setScore(score); students.push_back(stu); //Add to the global variable students save(stu, 1); //Keep records cout << "\n The information of the added record is as follows:\n"; show(stu); //Display record clear(); } else system("cls"); } //Show single record void Manager::show(Student* stu) { cout << "Student No.:" << stu->getId() << endl; cout << "full name:" << stu->getName() << endl; cout << "Grade:" << stu->getGrade() << endl; cout << "Major:" << stu->getPf() << endl; stu->getScore().show_score(); } //Save a single record //flag==1, for additional saving, flag==0, for overwriting the previous record void Manager::save(Student* stu, int flag, const char* filename) { fstream fs; if (flag == 1) { //Append write. Add ios::app to the original ios::out fs.open(filename, ios::out | ios::app); } else { //The existing records will be overwritten fs.open(filename, ios::out); } //Write to file fs << stu->getId() << "\t" << stu->getName() << "\t" << stu->getGrade() << "\t" << stu->getPf() << "\t" << stu->getScore().getScore_m() << "\t" << stu->getScore().getScore_c() << "\t" << stu->getScore().getScore_e() << "\t" << stu->getScore().getAvg() << "\t" << stu->getScore().getSum() << endl; fs.close(); } //Save multiple records void Manager::saveAll(vector<Student*> stus, const char* filename) { for (int i = 0; i < stus.size(); i++) { if (i == 0) save(stus.at(i), 0, filename); //Overwrite the original record first else save(stus.at(i), 1, filename); //Append record } } //Judge whether the record is empty //Null: returns 0; Otherwise, return 1 int Manager::isEmpty() { if (students.empty()) { //No record cout << "There is no record yet. Do you want to add a record?(input y Add, enter other (return)"; string ch; cin >> ch; if (ch == "y" || ch == "Y") { add(); //Perform the add operation } return 0; } return 1; } //Display header void Manager::showHeader() { cout << left; //Left aligned, right aligned by default cout << "-----------+---------+---------+---------------+-----------+-----------+-----------+---------+---------+\n"; cout << "| "; color(14); cout << setw(9) << "Student number"; color(3); cout << "| "; color(14); cout << setw(8) << "full name"; color(3); cout << "| "; color(14); cout << setw(8) << "grade"; color(3); cout << "| "; color(14); cout << setw(14) << "major"; color(3); cout << "| "; color(14); cout << setw(10) << "Mathematics achievement"; color(3); cout << "| "; color(14); cout << setw(10) << "grade scores of Chinese"; color(3); cout << "| "; color(14); cout << setw(10) << "English achievement"; color(3); cout << "| "; color(14); cout << setw(8) << "average"; color(3); cout << "| "; color(14); cout << setw(8) << "Total score"; color(3); cout << "| \n"; } //Set color void Manager::color(int i) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), i); } //Show multiple records //flag defaults to 0 //When flag==1, the query result is displayed, and the screen is not clear when returning void Manager::display(vector<Student*> stus, int flag) { if (!isEmpty()) //Determine whether there are records return; system("cls"); showHeader(); //Display header int count = stus.size(); //Total records int i = 0; //paging operation while (i < count) { cout << "-----------+---------+---------+---------------+-----------+-----------+-----------+---------+---------+\n"; cout << left; //Left aligned, right aligned by default cout << "| " << setw(9) << stus.at(i)->getId() << "| " << setw(8) << stus.at(i)->getName() << "| " << setw(8) << stus.at(i)->getGrade() << "| " << setw(14) << stus.at(i)->getPf() << "| "; printf("%-10.1lf| ", stus.at(i)->getScore().getScore_m()); printf("%-10.1lf| ", stus.at(i)->getScore().getScore_c()); printf("%-10.1lf| ", stus.at(i)->getScore().getScore_e()); printf("%-8.1lf| %-8.1lf|\n", stus.at(i)->getScore().getAvg(), stus.at(i)->getScore().getSum()); Sleep(25); //Output the page number and check whether the input is correct if ((i + 1) % 10 == 0 || i == count - 1) { cout << "-----------+---------+---------+---------------+-----------+-----------+-----------+---------+---------+\n"; cout << right << setw(41) << "The first" << i / 10 + 1 << "page/common" << (count - 1) / 10 + 1 << "page\n"; cout << "\n input's'View the previous page and enter'n'To view the next page, enter 1-" << (count - 1) / 10 + 1 << "Turn the page and enter other information to return."; string cho; cin >> cho; if (atoi(cho.c_str()) >= 1 && atoi(cho.c_str()) <= ((count - 1) / 10 + 1)) { i = (atoi(cho.c_str()) - 1) * 10 - 1; //Convert a string to a number and skip to the corresponding page number } else if (cho == "n" || cho == "N") { //Enter n or n for the next page if (i == count - 1) { cout << "It is the last page at present. There is no next page!\n"; //Count starts from 1 and i starts from 0, so count starts with - 1 i = (count - 1) - ((count - 1) % 10) - 1; system("pause"); } } else if (cho == "s" || cho == "S") { //Enter s or s for the previous page i = i - (i % 10) - 11; //Subscript-1 of the first record on the previous page if (i < -1) { cout << "It is the first page at present. There is no previous page!\n"; i = -1; //Reassign to the subscript-1 of the first record on the first page system("pause"); } } else { //Enter another to exit directly if (!flag) //When flag==1, the query result is displayed, and the screen is not clear when returning show_back(); break; } system("cls"); showHeader(); //If the loop is not exited, the next page is displayed. Here is the display header } i++; } } //Search records (query by student number) Student* Manager::findById(long id, int& index) { //Before finding records, first arrange the records according to the student number. The second parameter is 1, which means that after sorting, you need to query order(5, 1); int count = students.size(); //total //Binary query int left = 0; int right = count - 1; int mid = 0; while (left <= right) { mid = (left + right) / 2; if (students.at(mid)->getId() == id) { index = mid; return students.at(mid); } else if (id < students.at(mid)->getId()) right = mid - 1; else left = mid + 1; } index = -1; //-1 means query failed return NULL; } //Half search //temp: an array that holds search results //flag: flag search method (search by total score, math score, etc.) //Score: the score to find //Left: find the left boundary of the interval //Right: find the right boundary of the interval void Manager::Search_bin(vector<Student*>& temp, int flag, double score, int left, int right) { int low = left; //Save rightmost subscript int high = right; //Save leftmost subscript int mid; while (left <= right) { mid = (left + right) / 2; if (students.at(mid)->getScore(flag) == score) { //index=mid; temp.push_back(students.at(mid)); Search_bin(temp, flag, score, low, mid - 1); //Recursive left half Search_bin(temp, flag, score, mid + 1, high); //Recursive right half break; //Exit loop } else if (score > students.at(mid)->getScore(flag)) right = mid - 1; else left = mid + 1; } } //Find records (query by score) //The parameter flag represents the sorting method: //1: Sort by total score //2: Sort by math score //3: Sort by Chinese score //4: Sort by English score vector<Student*> Manager::findByScore(double score, int& index, int flag) { vector<Student*> temp; //Before finding records, first arrange them according to their grades. The second parameter is 1, which means that after sorting, you need to query order(flag - 1, 1); int count = students.size(); //total Search_bin(temp, flag - 1, score, 0, count - 1); //Binary search if (temp.size() == 0) index = -1; //Search failed return temp; } //Query by name vector<Student*> Manager::findByName(string name, int& index) { cout << "Please wait"; Sleep(200); cout << "."; Sleep(200); cout << "."; Sleep(200); cout << ".\n"; vector<Student*> result; int len = name.length(); result = students; vector<Student*> temp, temp_null; //temp temporarily saves all possible results int ct = 0; //Subscript of first name string while (ct < len) { temp = result; result = temp_null; for (int i = 0; i < temp.size(); i++) { string name_ = temp.at(i)->getName(); if (name_.length() == len) { //Compare the same length if (name_[ct] == name[ct]) result.push_back(temp.at(i)); } } ct++; } if (result.size() == 0) index = -1; //Search failed return result; } //Ask if you want to save string Manager::isSave() { cout << "Do you want to save the query results to a file?\n input y Save, enter other and return."; string cho; cin >> cho; return cho; } //Get file name void Manager::getFilename(string name, char filename[]) { char name_c[16]; for (int i = 0; i < name.length(); i++) //Convert string type to char array type name_c[i] = name[i]; name_c[name.length()] = '\0'; sprintf(filename, "name=%s.txt", name_c); } //Query function void Manager::query(int cho) { if (cho == 0) { system("cls"); return; //Direct return } long id = 0; //Student number double score; //fraction string name; //name Student* stu = new Student; //Student object vector<Student*> stus; char* filename = (char*)malloc(sizeof(char) * 64); //file name int index; //Return subscript, - 1 means query failed switch (cho) { case 1: cout << "Please enter your first name:"; cin >> name; stus = findByName(name, index); break; case 2: //Total score cout << "Please enter your grade:"; id = 2; score = read_Number(id); if (score == -1) { system("cls"); return; } stus = findByScore(score, index, cho); break; case 3: //achievement case 4: case 5: cout << "Please enter your grade:"; id = 1; score = read_Number(id); if (score == -1) { system("cls"); return; } stus = findByScore(score, index, cho); break; case 6: cout << "Please enter the 7 digits of the student number to be queried (e.g. 2021000):"; if (read_Number(id) == -1) { system("cls"); return; } stu = findById(id, index); break; } if (index == -1) { cout << "Query failed, there is no student!" << endl; } else if (cho == 6) { cout << "Query succeeded! The student's grade information is as follows:\n\n"; show(stu); sprintf(filename, "id=%.2ld.txt", id); string ret = isSave(); if (ret == "y" || ret == "Y") { save(stu, 0, filename); //Parameter 0 is to overwrite the original data cout << "Data saved to file: " << filename << endl; } } else { cout << "Query succeeded!" << endl; system("pause"); //Pause first display(stus, 1); if (cho == 1) { getFilename(name, filename); } else sprintf(filename, "score=%.2lf.txt", score); string ret = isSave(); if (ret == "y" || ret == "Y") { saveAll(stus, filename); cout << "Data saved to file: " << filename << endl; } } clear(); } //Delete record void Manager::delete_() { if (!isEmpty()) { //Determine whether there are records system("cls"); return; } int count = students.size(); //total long temp = 0; cout << "Please enter 7 digits of the student number of the record to be deleted (e.g. 2021000):"; if (read_Number(temp) == -1) { //Student ID reading failed system("cls"); return; } cout << "Please wait"; cout << "."; Sleep(200); cout << "."; Sleep(200); cout << ".\n"; Sleep(200); int index; //Subscript of record to be deleted findById(temp, index); if (index == -1) { cout << "Record deletion failed! There are no students with the student number.\n"; clear(); return; } vector<Student*>::iterator it; //Get iterator it = students.begin(); while (index > 0) { //Find the location of the iterator it++; index--; } students.erase(it); //Delete record in array saveAll(students); //Keep all records string cho; cout << "Record deleted successfully!\n To view all records, please enter y,Please enter other characters when returning:"; cin >> cho; if (cho == "y" || cho == "Y") display(students); //Display deleted records system("cls"); } //Use regular expressions to determine whether the input is correct int Manager::read_choose(int left, int right) { int ct = 3; int choose = -1; cout << "Please select the number of the corresponding function(" << left << " - " << right << "): "; while (true) { char temp[32]; //Save non numeric characters //Get the number and return 1; Otherwise, return 0 int ret1 = scanf("%d", &choose); if (!ret1) //If the number cannot be read, all the input contents will be read and filtered out scanf("%*[^'\n']"); scanf("%*[' ']"); //Read the space //^Indicates non. That is, get all characters that are not newline characters //Get, return 1; Otherwise, return 0 int ret2 = scanf("%[^'\n']", temp); scanf("%*c"); //Read a character, * means it is not saved to the variable. That is, get a newline character //A number is read and there are no non newline characters after the number if (ret1 && !ret2 && choose >= left && choose <= right) { return choose; } else if (ct == 0) return -1; //Input error three times, return - 1 else { cout << "Input error, please re-enter(also" << ct-- << "Second chance): "; } } } //Modify record int Manager::update(Student* stu) { cout << "The student's information is as follows:\n\n"; show(stu); int choose; cout << "\n=======================================================" << endl; //Cout < < ----------------- welcome to the modification function ---------------------- < < endl; cout << " @ [1]Modify name @ " << endl; cout << " @ [2]Modify grade @ " << endl; cout << " @ [3]Modify specialty @ " << endl; cout << " @ [4]Modify math scores @ " << endl; cout << " @ [5]Revise Chinese scores @ " << endl; cout << " @ [6]Revise English scores @ " << endl; cout << " @ [0]Return to management system @ " << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; choose = read_choose(0, 6); if (choose == 0 || choose == -1) { manager.show_back(); return -2; } string name, grade, pf; //Name, grade, major long temp = 1; //Temporary variable. 1 indicates the reading result double score1, score2, score3; //achievement switch (choose) { case 0: return -2; case 1: cout << "\n Please enter the student's new name: "; cin >> name; stu->setName(name); break; case 2: cout << "\n Please enter the student's new grade: "; cin >> grade; stu->setGrade(grade); break; case 3: cout << "\n Please enter the student's new major: "; cin >> pf; stu->setPf(pf); break; case 4: cout << "Please enter the student's new math score:"; score1 = read_Number(temp); if (score1 == -1) return -1; stu->setScore(score1, -1, -1); break; case 5: cout << "Please enter the student's new language score:"; score2 = read_Number(temp); if (score2 == -1) return -1; stu->setScore(-1, score2, -1); break; case 6: cout << "Please enter the student's new English score:"; score3 = read_Number(temp); if (score3 == -1) return -1; stu->setScore(-1, -1, score3); break; } return 0; } //Modify record function. id is - 1 by default. If there are other student numbers passed in, other student numbers will be used int Manager::update(long id) { if (!isEmpty()) { system("cls"); return 0; } long temp; if (id == -1) { temp = 0; //0 means reading the student number cout << "Please enter the 7-digit student number of the record to be modified (e.g. 2021000):"; if (read_Number(temp) == -1) { system("cls"); return 0; } } else temp = id; int index; findById(temp, index); if (index != -1) { string choose; do { int ret = update(students.at(index)); //Return value if (ret == -1) { cout << "Modification failed!\n"; clear(); return 0; } else if (ret == -2) { system("cls"); return 0; } saveAll(students); //Keep all records system("cls"); cout << "\n Modification succeeded! The new information is as follows:\n\n"; show(students.at(index)); //Displays the modified record cout << "Do you want to continue modifying?\n input y Continue, enter another return."; cin >> choose; system("cls"); } while (choose == "y" || choose == "Y"); } else { cout << "Modification failed, there are no students with this student number!\n"; system("pause"); } system("cls"); return 1; } //Swap two objects void Manager::swap(int i, int j) { Student* stu = students.at(i); students.at(i) = students.at(j); students.at(j) = stu; } //Sorting function (select sorting) returns an array for easy search //If the parameter ch is the specified sorting method and the parameter flag is 1, the next step is to query or add void Manager::order(int ch, int flag) { //flag is 0 by default (the default parameter should be put later) if (ch == 0) { system("cls"); return; //Direct return } //Bubble sorting int count = students.size(); //total if (ch != 5) { //Sort by grade (from large to small) for (int i = 0; i < count - 1; i++) { int flag_break = true; for (int j = 0; j < count - 1 - i; j++) { if (students.at(j + 1)->getScore(ch) > students.at(j)->getScore(ch)) { swap(j, j + 1); //Swap two objects flag_break = false; } } if (flag_break) break; } } else { //Sort by student number (from small to large) for (int i = 0; i < count - 1; i++) { int flag_break = true; for (int j = 0; j < count - 1 - i; j++) { if (students.at(j + 1)->getId() < students.at(j)->getId()) { swap(j, j + 1); //Swap two objects flag_break = false; } } if (flag_break) break; } } if (!flag) { cout << "Please wait"; Sleep(200); cout << "."; Sleep(200); cout << "."; Sleep(200); cout << ".\n"; } saveAll(students); //Keep records if (!flag) { //If the sorted operation is not a query, all the sorted contents will be displayed display(students); system("cls"); } } //Show return information void Manager::show_back(int flag) { flag == 1 ? cout << "About to exit the management system" : cout << "About to return"; cout << "."; Sleep(300); cout << "."; Sleep(300); cout << "."; Sleep(300); system("cls"); } //Display entry information void Manager::show_to() { system("cls"); cout << "Please wait"; cout << "."; Sleep(200); cout << "."; Sleep(200); cout << "."; Sleep(200); system("cls"); } //Select how to sort int order_ch() { if (!manager.isEmpty()) return 0; int choose; cout << "=======================================================" << endl; cout << "----------------Welcome to the sorting function-----------------------" << endl; cout << " @ [1]Sort by total score @ " << endl; cout << " @ [2]Sort by math score @ " << endl; cout << " @ [3]Sort by Chinese score @ " << endl; cout << " @ [4]Sort by English score @ " << endl; cout << " @ [5]Sort by student number @ " << endl; cout << " @ [0]Return to management system @ " << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; choose = manager.read_choose(0, 5); if (choose == 0 || choose == -1) { manager.show_back(); return 0; } return choose; } //Select query method int query_ch() { if (!manager.isEmpty()) return 0; int choose; cout << "=======================================================" << endl; cout << "----------------Welcome to the query function-----------------------" << endl; cout << " @ [1]Query by name @ " << endl; cout << " @ [2]Query by total score @ " << endl; cout << " @ [3]Query by math score @ " << endl; cout << " @ [4]Query by language score @ " << endl; cout << " @ [5]Query by English score @ " << endl; cout << " @ [6]Query by student number @ " << endl; cout << " @ [0]Return to management system @ " << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; choose = manager.read_choose(0, 6); if (choose == 0 || choose == -1) { manager.show_back(); return 0; } return choose; } int menu() { int choose; cout << "=======================================================" << endl; cout << "----------------Welcome to the student achievement management system---------------" << endl; cout << " @ [1]Add grade record @ " << endl; cout << " @ [2]Delete grade record @ " << endl; cout << " @ [3]Modify grade record @ " << endl; cout << " @ [4]Query score record @ " << endl; cout << " @ [5]Show all score records @ " << endl; cout << " @ [6]Rank @ " << endl; cout << " @ [0]Exit management system @ " << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; choose = manager.read_choose(0, 6); if (choose == -1 || choose == 0) { manager.show_back(1); cout << "Thanks for using, bye!"; Sleep(700); exit(0); } system("cls"); return choose; } void start() { manager.getAll(); //Get all records first while (true) { switch (menu()) { case 1: manager.show_to(); manager.add(); break; case 2: manager.show_to(); manager.delete_(); break; case 3: manager.show_to(); manager.update(); break; case 4: manager.show_to(); manager.query(query_ch()); break; case 5: manager.show_to(); manager.display(manager.getStudents()); manager.clear(); break; case 6: manager.show_to(); manager.order(order_ch()); break; } } } int main() { manager.color(3); start(); return 0; }
---------------Welcome to the student achievement management system ------------ "< endl;
Cout < < "@ [1] add score record @" < < endl;
Cout < < "@ [2] delete the score record @" < < endl;
Cout < < "@ [3] modify score record @" < < endl;
Cout < < "@ [4] query score record @" < < endl;
Cout < < "@ [5] display all score records @" < < endl;
Cout < < "@ [6] ranking @" < < endl;
Cout < < "@ [0] exit the management system @" < < endl;
cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
choose = manager.read_choose(0, 6);
if (choose == -1 || choose == 0) { manager.show_back(1); cout << "Thanks for using, bye!"; Sleep(700); exit(0); } system("cls"); return choose;
}
void start() {
manager.getAll(); // Get all records first
while (true) {
switch (menu()) {
case 1:
manager.show_to();
manager.add();
break;
case 2:
manager.show_to();
manager.delete_();
break;
case 3:
manager.show_to();
manager.update();
break;
case 4:
manager.show_to();
manager.query(query_ch());
break;
case 5:
manager.show_to();
manager.display(manager.getStudents());
manager.clear();
break;
case 6:
manager.show_to();
manager.order(order_ch());
break;
}
}
}
int main() {
manager.color(3);
start();
return 0;
}