2020-08-02 11:02:12 +07:00
|
|
|
|
#include "stdio.h"
|
|
|
|
|
#include "stdlib.h"
|
|
|
|
|
|
2020-08-02 17:55:14 +07:00
|
|
|
|
#define BUFFER_SIZE 128
|
2020-08-02 19:29:14 +07:00
|
|
|
|
#define MAX_NO_OF_UNITS 4
|
2020-08-02 17:55:14 +07:00
|
|
|
|
|
2020-08-02 18:30:52 +07:00
|
|
|
|
const char *FILE_STUDENT_DATA_PATH = "./data/students.test.txt";
|
2020-08-02 17:55:14 +07:00
|
|
|
|
|
2020-08-02 11:43:28 +07:00
|
|
|
|
struct person_tag
|
|
|
|
|
{
|
2020-08-02 11:27:05 +07:00
|
|
|
|
char name[20];
|
|
|
|
|
char id[10];
|
|
|
|
|
};
|
|
|
|
|
|
2020-08-02 11:43:28 +07:00
|
|
|
|
struct course_tag
|
|
|
|
|
{
|
2020-08-02 11:27:05 +07:00
|
|
|
|
char course_name[20];
|
|
|
|
|
int no_of_units;
|
2020-08-02 19:29:14 +07:00
|
|
|
|
int marks[MAX_NO_OF_UNITS];
|
2020-08-02 11:27:05 +07:00
|
|
|
|
float avg;
|
|
|
|
|
};
|
|
|
|
|
|
2020-08-02 11:43:28 +07:00
|
|
|
|
struct student_tag
|
|
|
|
|
{
|
2020-08-02 11:30:13 +07:00
|
|
|
|
struct person_tag student_info;
|
|
|
|
|
struct course_tag course_info;
|
|
|
|
|
struct student_tag *next;
|
2020-08-02 17:55:14 +07:00
|
|
|
|
} * head;
|
|
|
|
|
|
|
|
|
|
// typedef for declared to use as data type
|
|
|
|
|
typedef struct person_tag PERSON;
|
|
|
|
|
typedef struct course_tag COURSE;
|
|
|
|
|
typedef struct student_tag STUDENT;
|
2020-08-02 11:30:13 +07:00
|
|
|
|
|
2020-08-02 19:36:32 +07:00
|
|
|
|
// util functions
|
|
|
|
|
void display_menu();
|
|
|
|
|
void print_welcome();
|
|
|
|
|
void print_student(STUDENT *student);
|
|
|
|
|
|
2020-08-02 11:35:29 +07:00
|
|
|
|
// core functions
|
|
|
|
|
void display_students();
|
|
|
|
|
void search_student();
|
|
|
|
|
void find_maximum();
|
|
|
|
|
void find_failed();
|
2020-08-02 11:27:05 +07:00
|
|
|
|
void update_file();
|
|
|
|
|
void read_file();
|
|
|
|
|
void quite();
|
|
|
|
|
|
2020-08-02 17:55:14 +07:00
|
|
|
|
// Linked list functions
|
2020-08-02 19:29:14 +07:00
|
|
|
|
void add_student(char student_name[20], char student_id[10], char course_name[20], int no_of_units, int marks[MAX_NO_OF_UNITS]);
|
2020-08-02 17:55:14 +07:00
|
|
|
|
int count();
|
|
|
|
|
|
2020-08-02 11:43:28 +07:00
|
|
|
|
int main(void)
|
|
|
|
|
{
|
2020-08-02 17:55:14 +07:00
|
|
|
|
// variable use for menu selected
|
2020-08-02 11:43:28 +07:00
|
|
|
|
int selected;
|
2020-08-02 11:27:05 +07:00
|
|
|
|
|
2020-08-02 17:55:14 +07:00
|
|
|
|
print_welcome();
|
2020-08-02 11:43:28 +07:00
|
|
|
|
|
2020-08-02 19:36:32 +07:00
|
|
|
|
// init the read data from the file
|
|
|
|
|
read_file();
|
|
|
|
|
|
2020-08-02 18:10:37 +07:00
|
|
|
|
while (1)
|
2020-08-02 18:02:35 +07:00
|
|
|
|
{
|
2020-08-02 18:30:52 +07:00
|
|
|
|
display_menu();
|
2020-08-02 18:10:37 +07:00
|
|
|
|
printf("Enter your option: ");
|
|
|
|
|
scanf("%d", &selected);
|
2020-08-02 18:30:52 +07:00
|
|
|
|
|
2020-08-02 18:10:37 +07:00
|
|
|
|
switch (selected)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
display_students();
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
search_student();
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
find_maximum();
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
find_failed();
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
update_file();
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
quite();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printf("cannot find your option!");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-02 18:02:35 +07:00
|
|
|
|
}
|
2020-08-02 11:35:29 +07:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:55:14 +07:00
|
|
|
|
void print_welcome()
|
|
|
|
|
{
|
|
|
|
|
printf("Welcome!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void display_students()
|
|
|
|
|
{
|
2020-08-02 18:10:37 +07:00
|
|
|
|
printf("\n");
|
2020-08-02 19:20:50 +07:00
|
|
|
|
|
2020-08-02 19:36:32 +07:00
|
|
|
|
read_file();
|
2020-08-02 19:20:50 +07:00
|
|
|
|
|
|
|
|
|
STUDENT *student;
|
|
|
|
|
|
|
|
|
|
student = head;
|
|
|
|
|
|
|
|
|
|
if (student == NULL)
|
|
|
|
|
{
|
|
|
|
|
printf("No student!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 19:29:14 +07:00
|
|
|
|
printf("\n================ Student Details ================\n");
|
|
|
|
|
|
2020-08-02 19:20:50 +07:00
|
|
|
|
print_student(student);
|
|
|
|
|
|
|
|
|
|
while (student->next != NULL)
|
|
|
|
|
{
|
2020-08-02 19:29:14 +07:00
|
|
|
|
printf("\n");
|
2020-08-02 19:20:50 +07:00
|
|
|
|
student = student->next;
|
|
|
|
|
print_student(student);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void print_student(STUDENT *student)
|
|
|
|
|
{
|
|
|
|
|
printf("Student Name: %s\n", student->student_info.name);
|
|
|
|
|
printf("Student ID: %s\n", student->student_info.id);
|
|
|
|
|
printf("Course Name: %s\n", student->course_info.course_name);
|
|
|
|
|
printf("No of units: %d\n", student->course_info.no_of_units);
|
|
|
|
|
|
|
|
|
|
printf("Marks: [ ");
|
|
|
|
|
for (int i = 0; i < student->course_info.no_of_units; i++)
|
|
|
|
|
{
|
|
|
|
|
printf("%d ", student->course_info.marks[i]);
|
|
|
|
|
}
|
|
|
|
|
printf("]\n");
|
|
|
|
|
printf("Avg: %.2f\n", student->course_info.avg);
|
2020-08-02 17:55:14 +07:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 11:43:28 +07:00
|
|
|
|
void display_menu()
|
|
|
|
|
{
|
2020-08-02 17:55:14 +07:00
|
|
|
|
printf("\n(1) Display students’ details\n");
|
2020-08-02 11:35:29 +07:00
|
|
|
|
printf("(2) Search for a student’s mark\n");
|
|
|
|
|
printf("(3) Find the details of student with the largest average\n");
|
|
|
|
|
printf("(4) Find the details of failed students\n");
|
|
|
|
|
printf("(5) Add new student to the record\n");
|
2020-08-02 17:55:14 +07:00
|
|
|
|
printf("(6) Quit program\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 19:29:14 +07:00
|
|
|
|
void add_student(char student_name[20], char student_id[10], char course_name[20], int no_of_units, int marks[MAX_NO_OF_UNITS])
|
2020-08-02 17:55:14 +07:00
|
|
|
|
{
|
|
|
|
|
STUDENT *temp, *iterator;
|
|
|
|
|
temp = (struct student_tag *)malloc(sizeof(struct student_tag));
|
2020-08-02 19:20:50 +07:00
|
|
|
|
PERSON info;
|
|
|
|
|
strncpy(info.name, student_name, 20);
|
|
|
|
|
strncpy(info.id, student_id, 10);
|
|
|
|
|
|
|
|
|
|
COURSE course;
|
|
|
|
|
strncpy(course.course_name, course_name, 20);
|
|
|
|
|
course.no_of_units = no_of_units;
|
|
|
|
|
// memcpy(course.marks, marks);
|
|
|
|
|
|
|
|
|
|
float sum = 0;
|
2020-08-02 17:55:14 +07:00
|
|
|
|
for (int i = 0; i < no_of_units; i++)
|
|
|
|
|
{
|
2020-08-02 19:20:50 +07:00
|
|
|
|
course.marks[i] = marks[i];
|
2020-08-02 17:55:14 +07:00
|
|
|
|
sum += marks[i];
|
|
|
|
|
}
|
|
|
|
|
course.avg = sum / no_of_units;
|
|
|
|
|
temp->student_info = info;
|
|
|
|
|
temp->course_info = course;
|
2020-08-02 19:20:50 +07:00
|
|
|
|
|
2020-08-02 17:55:14 +07:00
|
|
|
|
// reference in head
|
|
|
|
|
iterator = head;
|
|
|
|
|
|
|
|
|
|
if (head == NULL)
|
|
|
|
|
{
|
|
|
|
|
head = temp;
|
|
|
|
|
head->next = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (iterator->next != NULL)
|
|
|
|
|
{
|
|
|
|
|
iterator = iterator->next;
|
|
|
|
|
}
|
|
|
|
|
temp->next = NULL;
|
|
|
|
|
iterator->next = temp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count()
|
|
|
|
|
{
|
|
|
|
|
int n = 1;
|
|
|
|
|
STUDENT *temp;
|
|
|
|
|
temp = head;
|
|
|
|
|
if (head == NULL)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (temp->next != NULL)
|
|
|
|
|
{
|
|
|
|
|
n++;
|
|
|
|
|
temp = temp->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return n;
|
2020-08-02 18:02:35 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void search_student()
|
|
|
|
|
{
|
|
|
|
|
printf("\nNot implement yet!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void find_maximum()
|
|
|
|
|
{
|
|
|
|
|
printf("\nNot implement yet!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void find_failed()
|
|
|
|
|
{
|
|
|
|
|
printf("\nNot implement yet!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update_file()
|
|
|
|
|
{
|
|
|
|
|
FILE *file;
|
|
|
|
|
file = fopen(FILE_STUDENT_DATA_PATH, "a");
|
2020-08-02 18:30:52 +07:00
|
|
|
|
|
|
|
|
|
char name[20];
|
|
|
|
|
char id[10];
|
|
|
|
|
char course_name[20];
|
|
|
|
|
int no_of_units;
|
2020-08-02 19:29:14 +07:00
|
|
|
|
int marks[MAX_NO_OF_UNITS];
|
2020-08-02 18:30:52 +07:00
|
|
|
|
|
|
|
|
|
printf("Enter student name: ");
|
|
|
|
|
scanf("%s", &name);
|
|
|
|
|
|
|
|
|
|
printf("Enter student id: ");
|
|
|
|
|
scanf("%s", &id);
|
|
|
|
|
|
|
|
|
|
printf("Enter course name: ");
|
|
|
|
|
scanf("%s", &course_name);
|
|
|
|
|
|
2020-08-02 19:36:32 +07:00
|
|
|
|
again:
|
2020-08-02 18:30:52 +07:00
|
|
|
|
printf("Enter no of units: ");
|
|
|
|
|
scanf("%d", &no_of_units);
|
|
|
|
|
|
2020-08-02 19:36:32 +07:00
|
|
|
|
if (no_of_units > MAX_NO_OF_UNITS)
|
|
|
|
|
{
|
2020-08-02 19:29:14 +07:00
|
|
|
|
printf("you cannot input the units bigger than %d\n", MAX_NO_OF_UNITS);
|
|
|
|
|
getchar();
|
|
|
|
|
goto again;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 18:30:52 +07:00
|
|
|
|
for (int i = 0; i < no_of_units; i++)
|
|
|
|
|
{
|
|
|
|
|
printf("Enter mark[%d]: ", i + 1);
|
|
|
|
|
scanf("%d", &marks[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count() > 0)
|
|
|
|
|
{
|
|
|
|
|
fputs("\n", file);
|
|
|
|
|
}
|
2020-08-02 19:20:50 +07:00
|
|
|
|
|
2020-08-02 18:30:52 +07:00
|
|
|
|
fputs(name, file);
|
|
|
|
|
fputs("\n", file);
|
|
|
|
|
fputs(id, file);
|
|
|
|
|
fputs("\n", file);
|
|
|
|
|
fputs(course_name, file);
|
|
|
|
|
fputs("\n", file);
|
|
|
|
|
fprintf(file, "%d", no_of_units);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < no_of_units; i++)
|
|
|
|
|
{
|
|
|
|
|
fputs("\n", file);
|
|
|
|
|
fprintf(file, "%d", marks[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
|
|
|
|
|
|
printf("\nSaved");
|
2020-08-02 19:42:42 +07:00
|
|
|
|
|
|
|
|
|
// reload data into linked list again
|
|
|
|
|
read_file();
|
2020-08-02 18:02:35 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void read_file()
|
|
|
|
|
{
|
2020-08-02 19:42:42 +07:00
|
|
|
|
// free the nodes
|
|
|
|
|
// because it can be use in memory
|
|
|
|
|
// we need to clear it first
|
|
|
|
|
// before we re-initailize the new data
|
|
|
|
|
STUDENT *temp;
|
|
|
|
|
while (head != NULL) {
|
|
|
|
|
temp = head;
|
|
|
|
|
head = head->next;
|
|
|
|
|
free(temp);
|
|
|
|
|
}
|
2020-08-02 19:36:32 +07:00
|
|
|
|
|
|
|
|
|
FILE *file;
|
|
|
|
|
file = fopen(FILE_STUDENT_DATA_PATH, "r");
|
|
|
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
|
{
|
|
|
|
|
printf("cannot read file: %s", FILE_STUDENT_DATA_PATH);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char student_name[20];
|
|
|
|
|
char student_id[10];
|
|
|
|
|
char course_name[20];
|
|
|
|
|
int no_of_units;
|
|
|
|
|
int marks[4];
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
while (!feof(file))
|
|
|
|
|
{
|
|
|
|
|
char no[BUFFER_SIZE];
|
|
|
|
|
|
|
|
|
|
fgets(student_name, sizeof student_name, file);
|
|
|
|
|
fgets(student_id, sizeof student_id, file);
|
|
|
|
|
fgets(course_name, sizeof course_name, file);
|
|
|
|
|
fgets(no, sizeof no, file);
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (student_name[i] != '\n')
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
student_name[i] = '\0';
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (student_id[i] != '\n')
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
student_id[i] = '\0';
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (course_name[i] != '\n')
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
course_name[i] = '\0';
|
|
|
|
|
|
|
|
|
|
no_of_units = atoi(no);
|
|
|
|
|
for (int j = 0; j < no_of_units; j++)
|
|
|
|
|
{
|
|
|
|
|
char mark[BUFFER_SIZE];
|
|
|
|
|
|
|
|
|
|
fgets(mark, sizeof mark, file);
|
|
|
|
|
sscanf(mark, "%d", &marks[j]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add into linked list
|
|
|
|
|
add_student(student_name, student_id, course_name, no_of_units, marks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(file);
|
2020-08-02 18:02:35 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void quite()
|
|
|
|
|
{
|
|
|
|
|
printf("\nGoodbye!");
|
|
|
|
|
exit(EXIT_SUCCESS);
|
2020-08-02 11:02:12 +07:00
|
|
|
|
}
|