Student Information Management System
All the mark points are marked in the table, if you cannot find the evaluation point in the webpage, this table will help you.
evaluation point | link1 | link2 | link3 | Note |
---|---|---|---|---|
Basic function – add | view | logic | data access | |
Basic function – display | view | data access | ||
Basic function – search | view | data access | ||
Basic function – sort | view | data access | ||
Basic function – save to file(log) | data access | |||
Basic function – read from file(log) | view | data access | ||
Extended function – delete student | view | logic | data access | |
Extended function – modify student | view | logic | data access | |
Extended function – OO | introduction | |||
Extended function – database | introduction | detailed design | ||
Extended function – version control | introduction | |||
Extended function – log | introduction | data access |
The Basic function “sort” contians extended like sort by studentId, name, age, etc.
The extended function “log” appear too many times so I did not give the links here.
文章目录
1.Introduction
This is a system for managing the students’ information (SIMS in short). The system contains three hierachical layers which are view, logic and data access.
At the very top layer-- view layer contains all human-computer interactions. All the client operations will be finished here.
The 2nd layer is the logic layer. It contains all logic operations including search for a student, sort the student grades, etc.
The 3rd layer is to communicate with database. It will automatically control the database with the order from logic layer.
Layer | Function | Note |
---|---|---|
View | All human-computer interactions. | No logic nor data control at all |
Logic | Handle the orders from the view layer, all the memory operations will be executed here, but data operations will be sent to the 3rd layer | This is the core layer of the system |
Data | Handle all the data operations from logic layer | Connection between memory and database |
2.Outline design
2.1 Functions of system
This system is similar to a DBMS, it contains add, delete, modify and query for a database. The detailed functions design is shown in the graph below.
2.2 UML sequence diagram
3.Extended
3.1 Object-Oriented design
To manage the students system, in memory operations of students, I used the object-oriented design for convenience. But due to C language does not have “class”, so I used struct and function to implement the class.
This is the class diagram of the system:
3.2 Database(MySQL)
To store the information in disk, we need a database to store all the information. I chose to use MySQL database.
This is the only table my database design:
3.3 Version control(Git)
Version control is important to keep track of changes — and keep every team member working off the latest version. I should use version control software for all code, files, and assets that multiple team members will collaborate on.
I use github server to store and do the version control.
This is the commit history of the project:
See my project on:
https://github.com/FTDfangge/StudentInfoManager
3.4 log file
The reason log files exist is that software and hardware developers find it easier to troubleshoot and debug their creations when they access a textual record of the events that the system is producing.
I use log file to record every operation that did by the client.
This is the log file until I wrote:
4. Detialed design
4.1 View
I loop the menu until user input exit, here is the core code.
void UImenu(){
struct StudentList* studentList = (struct StudentList*) malloc(sizeof (struct StudentList));
studentList->pre = NULL;
studentList->next = NULL;
initializeFromDatabase(&studentList);
while(true){
printf("\n=====Student Information management System=====\n");
printf("=====Menu=====\n");
printf("1. Display all students\n");
printf("2. Sort the display\n");
printf("3. Add student\n");
printf("4. Modify student\n");
printf("5. Delete student\n");
printf("6. Search\n");
printf("7. Check log file\n");
printf("8. exit\n");
printf("Plz input the choice(1~7): ");
int choice=0;
scanf("%d",&choice);
switch (choice) {
case 1:{
UIdisplay();
break;
}
case 2:{
UIsort(&studentList);
break;
}
case 3:{
UIaddStu(&studentList);
break;
}
case 4:{
UImodify(&studentList);
break;
}
case 5:{
UIdeleteStu(&studentList);
break;
}
case 6:{
UIsearch(&studentList);
break;
}
case 7:{
UIlog();
break;
}
case 8:{
exit(0);
}
default:{
break;
}
}
}
}
4.1.1 display all students’ info
I directly called the data access layer to get the data from database.
Here is the core code.
void UIdisplay(){
//Directly call the data access layer
printDatabase(); //call the data access layer
}
The called function is in 4.3.4.
4.1.2 add a new student
Let user input the information of new student, and call the logic layer to finish.
void UIaddStu(struct StudentList** list){
printf("\n=====Add a student=====\n");
struct Student* student = (struct Student*) malloc(sizeof (struct Student));
printf("Plz input the student info:\n"
"studentId: ");
scanf("%d",&(*student).stuId);
printf("\nstudent name: ");
scanf("%s",(*student).name);
printf("\nstudent gender: ");
scanf("%s",(*student).gender);
printf("\nstudent age: ");
scanf("%d", &(*student).age);
printf("\nstudent C score: ");
scanf("%d", &(*student).CScore);
printf("\nstudent English score: ");
scanf("%d", &(*student).EngScore);
printf("\nAdding...\n");
add(student, list); //call the logic layer
}
the called logic layer is here: logic
4.1.3 sort
Each attribute contained in the student could be the sorted option.
And sort is so easy that it will not pass the logic layer.
void UIsort(struct StudentList** list){
printf("\n1. Student id\n2. name\n3. gender\n4. age\n5. C score\n6. English Score\n");
printf("\nPlz select the attribute to sort: ");
int choice = 0;
scanf("%d", &choice);
switch (choice) {
case 1:{
sortById();//call the data access layer
break;
}
case 2:{
sortByName();//call the data access layer
break;
}
case 3:{
sortByGender();//call the data access layer
break;
}
case 4:{
sortByAge();//call the data access layer
break;
}
case 5:{
sortByCScore();//call the data access layer
break;
}
case 6:{
sortByEngScore();//call the data access layer
break;
}
default:
break;
}
}
The called data access layer design is here
4.1.4 search
It could be searched by each attribute of student.
void UIsearch(struct StudentList** list){
char **choices = malloc(sizeof(char*) * 6);
choices[0] = "stuId";
choices[1] = "name";
choices[2] = "gender";
choices[3] = "age";
choices[4] = "CScore";
choices[5] = "EngScore";
printf("\n1. Student id\n2. name\n3. gender\n4. age\n5. C score\n6. English Score\n");
printf("\nPlz select the attribute to search: ");
int choice = 0;
fflush(stdin);
scanf("%d", &choice);
choice--;
printf("\n Plz input the value of %s: ",choices[choice]);
char value[255];
fflush(stdin);
scanf("%s", value);
search(choices[choice], value);
}
4.1.5 modify
void UImodify(struct StudentList** list){
printf("\nPlz input the student id to be modify: ");
int stuId;
scanf("%d",&stuId);
modifyStudentInList(stuId, list);
}
4.1.6 delete
void UIdeleteStu(struct StudentList** list){
printf("\nPlz input the student number to delete: ");
int stuId;
scanf("%d",&stuId);
delete(stuId, list);
}
4.1.7 read log from file
void UIlog(){
logPrint();
}
4.2 Logic
4.2.1 add a student
It will firstly check if the student exist, then add it to the linked list(in memory), and it will sync with database(in disk).
void add(struct Student* student, struct StudentList** list){
//judge if the student exist in the list.
struct StudentList* listPtr = *list;
while (listPtr){
if(listPtr->data.stuId == (*student).stuId){
printf("\nERROR: The student is already existed, add failed.\n");
return;
}
listPtr = listPtr->next;
}
//Add to the list
struct StudentList* newnode = (struct StudentList*) malloc(sizeof (struct StudentList));
newnode->data = *student;
newnode->pre = NULL;
newnode->next = *list;
(*list)->pre = newnode;
*list = newnode;
addDBSync(student); //call the data access layer
logWrite("ADD; STUID:");
} //Add a student into the list
the called data access layer is here: data access
4.2.2 modify student
First find the student, then modify it.
void modifyStudentInList(int stuId, struct StudentList** list){
//judge if the student exist in the list.
struct StudentList* listPtr = *list;
while (listPtr){
if(listPtr->data.stuId == stuId){
printf("\nstudent found, plz input the new data(except student id) "
"format like this(name gender age CScore EngScore):\n");
scanf("%s %s %d %d %d",listPtr->data.name, listPtr->data.gender, &(listPtr->data.age),
&(listPtr->data.CScore), &(listPtr->data.EngScore));
modifyDBSync(&(listPtr->data));
char log2[255];
snprintf(log2, 255, "MODIFY; STUID: %d;", stuId);
logWrite(log2);
return;
}
listPtr = listPtr->next;
}
} //Modify student
4.2.3 delete student
First find the student, then delete it in linked list and database.
void delete(int stuId, struct StudentList** list){
//judge if the student exist in the list.
struct StudentList* listPtr = *list;
while (listPtr){
if(listPtr->data.stuId == stuId){
printf("\nstudent found, it will be deleted ");
if(listPtr->pre == NULL){
*list = listPtr->next;
} else{
listPtr->pre->next = listPtr->next;
listPtr->next->pre = listPtr->pre;
}
deleteDBSync(stuId);
char log2[255];
snprintf(log2, 255, "DELETE; STUID: %d;", stuId);
logWrite(log2);
return;
}
listPtr = listPtr->next;
}
} //Delete a student from the list
4.3 Database
4.3.1 DataBase Creation
I use mySql and execute the following order:
create table students
(
stuId int,
name varchar(20) not null,
gender varchar(1) default 'm' not null,
age int default 18 null,
CScore int null,
EngScore int null,
constraint students_pk
primary key (stuId),
check (gender = 'f' or gender = 'm'),
check ( age>=0 and age<=100 ),
check ( CScore>=0 and CScore<=100 ),
check ( EngScore >=0 and EngScore<=100 )
);
And I also added some students to be the initial data.
Executed the following orders:
INSERT INTO sims.students (stuId, name, gender, age, CScore, EngScore) VALUES (18301001, 'Murray', 'f', 19, 68, 89)
INSERT INTO sims.students (stuId, name, gender, age, CScore, EngScore) VALUES (18301002, 'Adria', 'm', 20, 74, 99)
INSERT INTO sims.students (stuId, name, gender, age, CScore, EngScore) VALUES (18301003, 'Garnett', 'f', 17, 99, 100)
INSERT INTO sims.students (stuId, name, gender, age, CScore, EngScore) VALUES (18301004, 'Milford', 'm', 18, 54, 61)
INSERT INTO sims.students (stuId, name, gender, age, CScore, EngScore) VALUES (18301005, 'Megan', 'f', 17, 77, 40)
The initial database is like this:
4.3.2 Database connection
Here is the core code.
MYSQL* con = mysql_init(NULL);
if (con == NULL)
{
finish_with_error(con);
}
if (mysql_real_connect(con, "localhost", "user1", "123456",
"sims", 0, NULL, 0) == NULL)
{
finish_with_error(con);
}
4.3.3 initialize the linked list
Read from database and init the linked list. This will call data access layer to get the data.
void initializeFromDatabase(struct StudentList** list){
struct StudentList* pointer = *list;
MYSQL* con = mysql_init(NULL);
if (con == NULL)
{
finish_with_error(con);
}
if (mysql_real_connect(con, "localhost", "user1", "123456",
"sims", 0, NULL, 0) == NULL)
{
finish_with_error(con);
}
if (mysql_query(con, "SELECT * FROM students"))
{
finish_with_error(con);
}
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL)
{
finish_with_error(con);
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
{
//Each row is a student
struct Student student;
student.stuId = atoi(row[0]);
strcpy(student.name, row[1]);
strcpy(student.gender, row[2]);
student.age = atoi(row[3]);
student.CScore = atoi(row[4]);
student.EngScore = atoi(row[5]);
pointer->data = student; //Firstly, store the current student in the current node.
//Then construct a new node for the next.
struct StudentList* listNode = (struct StudentList*) malloc(sizeof (struct StudentList));
listNode->pre = pointer;
listNode->next = NULL;
pointer->next = listNode;
pointer = listNode;
printf("\n");
}
pointer->pre->next = NULL;
mysql_free_result(result);
mysql_close(con);
}
4.3.4 get data
Here is the core code.
if (mysql_query(con, "SELECT * FROM students"))
{
finish_with_error(con);
}
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL)
{
finish_with_error(con);
}
int num_fields = mysql_num_fields(result);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
{
for(int i = 0; i < num_fields; i++)
{
printf("%s ", row[i] ? row[i] : "NULL");
}
printf("\n");
}
mysql_free_result(result);
4.3.5 add database sync
To sync the data when add.
void addDBSync(struct Student* stu){
MYSQL* con = mysql_init(NULL);
if (con == NULL)
{
finish_with_error(con);
}
if (mysql_real_connect(con, "localhost", "user1", "123456",
"sims", 0, NULL, 0) == NULL)
{
finish_with_error(con);
}
char sql[255];
snprintf(sql, 255, "INSERT INTO students VALUES(%d,'%s','%s',%d,%d,%d);",
(*stu).stuId, (*stu).name, (*stu).gender, (*stu).age, (*stu).CScore, (*stu).EngScore);
if (mysql_query(con, sql)){
finish_with_error(con);
}
printf("inserted into the database!\n");
mysql_close(con);
}
4.3.6 delete database sync
Functions is implemented similarly, here is the example of SQL.
delete from students where stuId = ******;
4.3.7 modify database sync
Functions is implemented similarly, here is the example of SQL.
update students set name = '%s', gender = '%s',age = %d, CScore = %d, EngScore = %d where stuId = %d;
4.3.8 sort
All sort functions are implemented similarly, here is the example of SQL.
SELECT * FROM students ORDER BY stuId;
4.3.9 log file operation
Read from file and print:
void logPrint(){
FILE* file = fopen("log.txt","r+");
char string[255];
printf("\nLog: \n");
fscanf(file,"\n%[^\n]",string);
fscanf(file,"\n%[^\n]s",string);
while(fscanf(file,"\n%[^\n]s",string) != EOF){
printf("%s\n",string);
}
fclose(file);
} //Print the log file
Write the log to the file:
void logWrite(char* string){
FILE* file = fopen("log.txt","a");
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
char time[255] = {'\0'};
strcpy(time, asctime(timeinfo));
for(int i=0;i<255;i++){
if (time[i] == '\n'){
time[i] = '\0';
break;
}
}
fprintf(file,"|%s|%20s|\n",time,string);
fclose(file);
} //Write to the log file