sbn.cassigment/work1/single.c

429 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define BUFFER_SIZE 128
#define MAX_NO_OF_UNITS 4
#define NAME_SIZE 20
const char *FILE_STUDENT_DATA_PATH = "./data/students.test.txt";
struct person_tag
{
char name[20];
char id[10];
};
struct course_tag
{
char course_name[20];
int no_of_units;
int marks[MAX_NO_OF_UNITS];
float avg;
};
struct student_tag
{
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;
// util functions
void display_menu();
void print_welcome();
void print_student(STUDENT *student);
void release(STUDENT *data);
STUDENT *search_student_by_name_or_id(char search_key[NAME_SIZE]);
// core functions
void display_students();
void search_student();
void find_maximum();
void find_failed();
void update_file();
void read_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();
int main(void)
{
// variable use for menu selected
int selected;
print_welcome();
// init the read data from the file
read_file();
while (1)
{
display_menu();
printf("Enter your option: ");
scanf("%d", &selected);
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;
}
}
}
void print_welcome()
{
printf("Welcome!\n");
}
void display_students()
{
read_file();
STUDENT *student = head;
if (student == NULL)
{
printf("No student!");
return;
}
printf("\n================ Student Details ================\n");
print_student(student);
}
void print_student(STUDENT *student)
{
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;
}
// clean up the memory
// after output the data
// because we don;t need it anymore after output
release(student);
}
void display_menu()
{
printf("\n(1) Display students’ details\n");
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;
memcpy(info.name, student_name, 20);
memcpy(info.id, student_id, 10);
COURSE course;
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()
{
int n = 1;
STUDENT *temp;
temp = head;
if (head == NULL)
{
return 0;
}
while (temp->next != NULL)
{
n++;
temp = temp->next;
}
return n;
}
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)
{
printf("No student found!");
return;
}
print_student(found_student);
}
STUDENT *search_student_by_name_or_id(char search_key[NAME_SIZE])
{
STUDENT *temp = head;
while (temp != NULL)
{
if (temp->student_info.name == search_key || temp->student_info.id == search_key)
{
return temp;
}
temp = temp->next;
}
return NULL;
}
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");
char name[20];
char id[10];
char course_name[20];
int no_of_units;
int marks[MAX_NO_OF_UNITS];
printf("Enter student name: ");
scanf("%s", &name);
printf("Enter student id: ");
scanf("%s", &id);
printf("Enter course name: ");
scanf("%s", &course_name);
again:
printf("Enter no of units: ");
scanf("%d", &no_of_units);
if (no_of_units > MAX_NO_OF_UNITS && no_of_units <= 0)
{
printf("you cannot input the units bigger than %d or less than 0\n", MAX_NO_OF_UNITS);
getchar();
goto again;
}
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);
}
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");
// reload data into linked list again
read_file();
}
void read_file()
{
// release nodes
// we need to clean up the memory
if (head != NULL)
{
STUDENT *temp;
while (head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
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);
}
}