Data_Structure/作業/unit4/DS4/sheng_v2.cpp
2025-01-20 21:30:53 +08:00

365 lines
9.5 KiB
C++
Raw Permalink 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>
#include <ctype.h>
typedef struct Student
{
char name[40];
int eng;
int math;
struct Student *prev;
struct Student *next;
} Student;
Student *head = NULL, *tail = NULL, *current;
// 新增節點到鏈結串列尾部
void addToList(const char *name, int eng, int math)
{
// 配置新節點記憶體
Student *newStudent = (Student*)malloc(sizeof(Student));
// 複製資料到新節點
strncpy(newStudent->name, name, sizeof(newStudent->name) - 1);
newStudent->name[sizeof(newStudent->name) - 1] = '\0';
newStudent->eng = eng;
newStudent->math = math;
newStudent->next = NULL;
// 如果是第一個節點
if (head == NULL)
{
newStudent->prev = NULL;
head = tail = newStudent;
}
else // 加入到尾部
{
newStudent->prev = tail;
tail->next = newStudent;
tail = newStudent;
}
}
// 顯示所有學生資料
void displayList()
{
//Student *
current = head;
printf("學生資料列表(從頭開始)\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i=0; current!=NULL; current=current->next,i++)
{
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, current->name, current->eng, current->math);
}
printf("---------------------------------------------\n");
}
// 從尾開始列印
void displayList_inverse()
{
Student *current = tail;
printf("學生資料列表(從尾開始)\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i=0; current!=NULL; current=current->prev,i++)
{
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, current->name, current->eng, current->math);
}
printf("---------------------------------------------\n");
}
// 釋放所有動態分配的節點
void cleanup()
{
Student *current = head;
while (current != NULL)
{
Student *temp = current;
current = current->next;
free(temp);
}
head = tail = NULL;
}
// 更新後的刪除函數
void deletedate(const char *name, int eng, int math)
{
Student *current = head;
while(current != NULL)
{
if(strcmp(current->name, name) == 0)
{
if(current->prev != NULL) current->prev->next = current->next;
else head = current->next;
if(current->next != NULL) current->next->prev = current->prev;
else tail = current->prev;
free(current);
return;
}
current = current->next;
}
}
// 移除字串前後的空格
void trim(char *str)
{
char *end;
while(isspace(*str)) str++;
if(*str == 0) return;
end = str + strlen(str) - 1;
while(end > str && isspace(*end)) end--;
end[1] = '\0';
}
//void displayOriginal(Student **array, int length)
//{
// printf("\n原始資料列表\n\n");
// printf("姓名\t\t\t\t英文\t數學\n");
// printf("---------------------------------------------\n");
// for(int i = 0; i < length; i++) {
// printf("%d.\t%-16s\t%d\t%d\n\n", i+1, array[i]->name, array[i]->eng, array[i]->math);
// }
// printf("---------------------------------------------\n");
//}//如果想在排序後看還有switch,就把下面的註釋調
void displayOriginal()
{
//Student *
current = head;
printf("\n原始資料列表:\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i = 0; current != NULL; i++) {
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, current->name, current->eng, current->math);
current = current->next;
}
printf("---------------------------------------------\n");
}
// 排序函數
void bubble_name()
{
int length = 0;
Student *current = head;
// 計算鏈表長度
while(current != NULL)
{
length++;
current = current->next;
}
// 創建指針數組
Student **array = (Student**)malloc(length * sizeof(Student*));
current = head;
for(int i = 0; i < length; i++)
{
array[i] = current;
current = current->next;
}
// 顯示原始資料
//displayOriginal(array, length);
// 按名字排序
for(int i = 0; i < length-1; i++)
{
for(int j = 0; j < length-1-i; j++)
{
if(strcmp(array[j]->name, array[j+1]->name) > 0)
{
Student *temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
// 顯示排序後的結果
printf("學生資料列表(依名字排序)\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i = 0; i < length; i++) {
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, array[i]->name, array[i]->eng, array[i]->math);
}
printf("---------------------------------------------\n");
free(array);
}
// 按英文成績排序
void bubble_eng()
{
int length = 0;
Student *current = head;
// 計算鏈表長度
while(current != NULL) {
length++;
current = current->next;
}
// 創建指針數組
Student **array = (Student**)malloc(length * sizeof(Student*));
current = head;
for(int i = 0; i < length; i++) {
array[i] = current;
current = current->next;
}
// 顯示原始資料
//displayOriginal(array, length);
// 按英文成績排序
for(int i = 0; i < length-1; i++) {
for(int j = 0; j < length-1-i; j++) {
if(array[j]->eng < array[j+1]->eng) {
Student *temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
// 顯示排序後的結果
printf("學生資料列表(依英文成績排序)\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i = 0; i < length; i++) {
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, array[i]->name, array[i]->eng, array[i]->math);
}
printf("---------------------------------------------\n");
free(array);
}
// 按數學成績排序
void bubble_math()
{
int length = 0;
Student *current = head;
// 計算鏈表長度
while(current != NULL) {
length++;
current = current->next;
}
// 創建指針數組
Student **array = (Student**)malloc(length * sizeof(Student*));
current = head;
for(int i = 0; i < length; i++) {
array[i] = current;
current = current->next;
}
// 顯示原始資料
//displayOriginal(array, length);
// 按數學成績排序
for(int i = 0; i < length-1; i++) {
for(int j = 0; j < length-1-i; j++) {
if(array[j]->math < array[j+1]->math) {
Student *temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
// 顯示排序後的結果
printf("學生資料列表(依數學成績排序)\n\n");
printf("姓名\t\t\t\t英文\t數學\n");
printf("---------------------------------------------\n");
for(int i = 0; i < length; i++) {
printf("%d.\t%-16s\t%d\t%d\n\n", i+1, array[i]->name, array[i]->eng, array[i]->math);
}
printf("---------------------------------------------\n");
free(array);
}
void select()
{
Student *current=head;
int j;
printf("請選擇查看第幾名的資料\n\n");
scanf("%d",&j);
for(int i=1;i<j;i++)
{
current=current->next;
}
printf("\n%d. Name = %s Eng = %d\tMath = %d",j,current->name,current->eng,current->math);
}
int main()
{
FILE *file;
char line[100];
char name[40];
int eng, math;
char op;
file = fopen("YunTechStudents.txt", "r");
while(fgets(line, sizeof(line), file))
{
if(strstr(line, "****") != NULL)
break;
if(sscanf(line, "%[^\t]%d%d", name, &eng, &math) == 3)
{
trim(name);
addToList(name, eng, math);
}
}
displayList();
displayList_inverse();
while(fgets(line, sizeof(line), file))
{
op = line[0];
if(op == '+' || op == '-')
{
char fullname[40];
if(sscanf(line + 1, " %[^0-9]%d%d", fullname, &eng, &math) == 3)
{
trim(fullname);
if(op == '+')
{
addToList(fullname, eng, math);
printf("\n新增資料為:\t%s\t%d\t%d\n\n", fullname, eng, math);
}
else
{
deletedate(fullname, eng, math);
printf("\n刪除資料為:\t%s\t%d\t%d\n\n", fullname, eng, math);
}
displayList();
displayList_inverse();
}
}
}
int choice;
while(1)
{
printf("\n\n請輸入選擇\n\n");
printf("1. 以名字排列\t2. 以英文分數排列\t3. 以數學分數排列\t4. 顯示原本資料\t5. 離開\n\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
bubble_name();
select();
break;
case 2:
bubble_eng();
select();
break;
case 3:
bubble_math();
select();
break;
case 4:
displayOriginal();
break;
case 5:
printf("\n歡迎再來");
cleanup();
exit(0);
break;
}
}
fclose(file);
return 0;
}