sbn.cassigment/work1/single.c

592 lines
12 KiB
C
Raw Normal View History

#include "stdio.h"
#include "stdlib.h"
2020-08-02 19:58:58 +07:00
#include "string.h"
#define BUFFER_SIZE 128
#define MAX_NO_OF_UNITS 4
#define NAME_SIZE 20
2020-08-02 18:30:52 +07:00
const char *FILE_STUDENT_DATA_PATH = "./data/students.test.txt";
2020-08-02 11:43:28 +07:00
struct person_tag
{
char name[20];
char id[10];
};
2020-08-02 11:43:28 +07:00
struct course_tag
{
char course_name[20];
int no_of_units;
int marks[MAX_NO_OF_UNITS];
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;
} * 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 22:04:21 +07:00
// file function
void read_file();
2020-08-02 19:36:32 +07:00
// util functions
void display_menu();
void print_welcome();
void print_student(STUDENT *student);
void release(STUDENT *data);
int find_min_in_array(int *array);
STUDENT *search_student_by_name_or_id(char search_key[NAME_SIZE]);
STUDENT *find_maximum_avg();
STUDENT *add_last_student(STUDENT *nodes, STUDENT *element);
2020-08-02 19:36:32 +07:00
2020-08-02 11:35:29 +07:00
// core functions
void display_students();
void search_student();
void find_maximum();
void find_failed();
void update_file();
void quite();
// Linked list functions
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]);
int count_elements(STUDENT *elements);
int count();
2020-08-02 11:43:28 +07:00
int main(void)
{
// variable use for menu selected
2020-08-02 11:43:28 +07:00
int selected;
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: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 11:35:29 +07:00
}
void print_welcome()
{
printf("Welcome!\n");
}
void display_students()
{
2020-08-02 19:36:32 +07:00
read_file();
STUDENT *student = head;
if (student == NULL)
{
printf("\nNo student!\n");
return;
}
print_student(student);
}
void print_student(STUDENT *student)
{
int records_count = 0;
2020-08-02 21:00:05 +07:00
printf("\n================ Student Details ================\n");
while (student != NULL)
{
printf("\n");
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);
student = student->next;
records_count++;
}
// output the records count
printf("\nRecords: %d has been loaded successfully!\n", records_count);
2020-08-03 11:34:26 +07:00
// clean up the memory
// after output the data
// because we don;t need it anymore after output
release(student);
}
2020-08-02 11:43:28 +07:00
void display_menu()
{
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");
printf("(6) Quit program\n\n");
}
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])
{
STUDENT *temp, *iterator;
temp = (struct student_tag *)malloc(sizeof(struct student_tag));
PERSON info;
2020-08-02 19:58:58 +07:00
memcpy(info.name, student_name, 20);
memcpy(info.id, student_id, 10);
COURSE course;
2020-08-02 19:58:58 +07:00
memcpy(course.course_name, course_name, 20);
course.no_of_units = no_of_units;
// memcpy(course.marks, marks);
float sum = 0;
for (int i = 0; i < no_of_units; i++)
{
course.marks[i] = marks[i];
sum += marks[i];
}
course.avg = sum / no_of_units;
temp->student_info = info;
temp->course_info = course;
// 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_elements(STUDENT *elements)
{
int n = 1;
STUDENT *temp;
temp = elements;
if (head == NULL)
{
return 0;
}
while (temp->next != NULL)
{
n++;
temp = temp->next;
}
return n;
}
int count()
{
return count_elements(head);
}
void search_student()
{
char search_key[NAME_SIZE];
printf("Enter student name or id to search: ");
scanf("%s", &search_key);
STUDENT *found_student = search_student_by_name_or_id(search_key);
if (found_student == NULL)
{
2020-08-03 11:34:26 +07:00
printf("\nNo student found!\n");
return;
}
print_student(found_student);
}
STUDENT *search_student_by_name_or_id(char search_key[NAME_SIZE])
{
// refresh data from file first
read_file();
STUDENT *temp = head;
while (temp != NULL)
{
2020-08-02 21:00:05 +07:00
if (strcmp(temp->student_info.name, search_key) == 0 || strcmp(temp->student_info.id, search_key) == 0)
{
2020-08-02 21:00:05 +07:00
printf("\nSearch found with key: %s\n", search_key);
2020-08-03 11:34:26 +07:00
// set the temp next to null
// and free up the memory
temp->next = NULL;
free(temp->next);
// return the current temp
// that found in current search
return temp;
}
temp = temp->next;
}
return NULL;
}
STUDENT *find_maximum_avg()
{
// refresh data from file first
read_file();
STUDENT *temp = head, *max;
max = temp->next;
while (temp != NULL)
{
if (max == NULL)
{
return temp;
}
if (max->course_info.avg < temp->course_info.avg)
{
max = temp;
}
temp = temp->next;
}
// release the max next record
2020-08-02 21:57:57 +07:00
// set max next element to NULL
// because we use only one record
release(max->next);
2020-08-02 21:57:57 +07:00
max->next = NULL;
return max;
}
int find_min_in_array(int *array)
{
if (array == NULL)
{
return -1;
}
int min = array[0];
2020-08-02 21:56:11 +07:00
size_t size = sizeof(array) / sizeof(array[0]);
for (int i = 1; i < size; i++)
{
if (array[i] < min)
{
min = array[i];
}
}
return min;
}
STUDENT *add_last_student(STUDENT *nodes, STUDENT *element)
{
STUDENT *temp = nodes, *node;
2020-08-03 11:34:26 +07:00
node = (struct student_tag *)malloc(sizeof(struct student_tag));
node->student_info = element->student_info;
node->course_info = element->course_info;
node->next = NULL;
if (nodes == NULL)
{
nodes = node;
return nodes;
}
// store current as tempo
// ref for nodes
temp = nodes;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = node;
return nodes;
}
// ISSUE: can't find all failed students
// It's just return one record back
STUDENT *find_failed_mark(int upper_mark)
{
// refresh data from file first
read_file();
2020-08-02 22:04:21 +07:00
printf("Count elements: %d\n", count());
STUDENT *temp = head, *failed_students = NULL;
int count = count_elements(temp);
printf("Temp count elements: %d", count);
int run_count = 0;
while (temp != NULL)
{
run_count++;
2020-08-02 21:56:11 +07:00
int min = find_min_in_array(temp->course_info.marks);
if (min < upper_mark)
{
printf("\nRun min: %d\n", min);
failed_students = add_last_student(failed_students, temp);
}
temp = temp->next;
}
printf("\nRun count: %d", run_count);
return failed_students;
}
void find_maximum()
{
2020-08-02 22:04:21 +07:00
// refresh data from file first
read_file();
STUDENT *max_student = find_maximum_avg();
if (max_student == NULL)
{
2020-08-02 21:56:11 +07:00
printf("\nNo maximum student found!\n");
return;
}
printf("\nFind maximum avg was found with: %0.2f\n", max_student->course_info.avg);
print_student(max_student);
}
void find_failed()
{
int upper_mark = 50;
STUDENT *failed_students = find_failed_mark(upper_mark);
if (failed_students == NULL)
{
2020-08-02 21:56:11 +07:00
printf("\nNo failed student found!\n");
return;
}
printf("\nFind the failed students that at least one mark less than %d\n", upper_mark);
print_student(failed_students);
}
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;
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);
if (no_of_units > MAX_NO_OF_UNITS && no_of_units <= 0)
2020-08-02 19:36:32 +07:00
{
printf("you cannot input the units bigger than %d or less than 0\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 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);
2020-08-02 21:56:11 +07:00
printf("\nRecord saved successfully!");
// reload data into linked list again
read_file();
}
void read_file()
{
// release nodes
// we need to clean up the memory
if (head != NULL)
2020-08-02 19:49:41 +07:00
{
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);
}
void quite()
{
printf("\nGoodbye!");
exit(EXIT_SUCCESS);
}
void release(STUDENT *data)
{
if (data == NULL)
{
return;
}
// 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 (data != NULL)
{
temp = data;
data = data->next;
free(temp);
}
}