#include #include #include #include #include #define MAX_NAME_LENGTH 24 //宣告函式原型 void init_f(); void readStudentsFromFile(char* filename); void insertStudent(char* name, int english, int math); void printStudentList(); void sort(int mode , int target); void modify_list(); void add_data(char* name, int english, int math); void remove_data(char* name); void choose_subject(); // 定義學生節點結構 typedef struct Student { char name[MAX_NAME_LENGTH]; int english; int math; struct Student* llink; struct Student* rlink; } Student; Student *head, *tail, *current, *prev, *temp ,**arr; FILE* file; int list_length ; void init_f() { head = (Student *) malloc(sizeof(Student)); tail = (Student *) malloc(sizeof(Student)); // head->llink = head; // 左鏈結指向自己 // head->rlink = head; // 右鏈結指向自己 // tail = head; // head->llink = tail; head->rlink = tail; // tail->rlink = head; tail->llink = head; } // 在尾部插入新學生節點 void insertStudent(char* name, int english, int math) { Student* newNode = (Student*)malloc(sizeof(Student)); strcpy(newNode->name, name); newNode->english = english; newNode->math = math; // 插入尾部 newNode->llink = tail->llink; newNode->rlink = tail; tail->llink->rlink = newNode; tail->llink = newNode; } //增加資料 void add_data(char* name, int english, int math){ Student* newNode = (Student*)malloc(sizeof(Student)); strcpy(newNode->name, name); newNode->english = english; newNode->math = math; newNode->llink = tail->llink; newNode->rlink = tail; tail->llink->rlink = newNode; tail->llink = newNode; printf("%s 已增加\n", name); } //減少資料 void remove_data(char* name){ prev = head; current = head->rlink; while(current!=tail &&strcmp(name,current->name)!=0){ prev=current; current=current->rlink; } if(current != tail){ current->rlink->llink = prev; prev->rlink = current->rlink; printf("%s 已刪除\n", name); free(current); }else /* 找不到資料則顯示錯誤 */ printf(" %s 不在串列中\n", name); } // 從文件讀取學生資料 void readStudentsFromFile(char* filename) { file = fopen(filename, "r"); if (file == NULL) { printf("無法開啟檔案 %s\n", filename); exit(0); } char line[100]; int lineCount = 0; // 跳過前四行 while (lineCount < 4 && fgets(line, sizeof(line), file)) { lineCount++; } // 讀取學生資料 char name[MAX_NAME_LENGTH]; int english, math; // %[ ]表示要讀入一個字符集合 // %23[^\t]為「讀取最多23個字符,直到遇到\t為止」 ^為非 不是\t就讀 while(fgets(line, sizeof(line), file)!=NULL){ if(isalpha(line[0])){ sscanf(line, "%23[^\t]\t%d\t%d\n", name, &english, &math); insertStudent(name, english, math); }else if(line[0]=='*'){ break; } } // 此flocse為測試用 正常使用應在modify_list的尾端 // fclose(file); } // 執行***後的增加或減少資料 void modify_list(){ char name[MAX_NAME_LENGTH]; int english, math; char line[100]; while(fgets(line, sizeof(line), file)!=NULL){ if(line[0]=='+'){ sscanf(line, "%*[^ ] %[^\t]\t%d\t%d\n", name, &english, &math); printf("\n===============================\n"); printf("增加一筆資料\n\n"); add_data(name, english, math); printStudentList(); }else if(line[0]=='-'){ sscanf(line, "%*[^ ] %[^\t]\t%d\t%d\n", name, &english, &math); printf("\n===============================\n"); printf("刪除一筆資料\n\n"); remove_data(name); printStudentList(); } } fclose(file); } // 列印學生列表 void printStudentList() { current = head->rlink; printf("\n從頭開始\n"); printf("\n姓名\t\t英文\t數學\n"); printf("--------------------------------\n"); while (current != tail) { printf("%-15s\t%d\t%d\n", current->name, current->english, current->math); current = current->rlink; } current = tail->llink; printf("\n從尾開始\n"); printf("\n姓名\t\t英文\t數學\n"); printf("--------------------------------\n"); while (current != head) { printf("%-15s\t%d\t%d\n", current->name, current->english, current->math); current = current->llink; } } //依照mode進行排序 void sort(int mode , int target){ list_length = 0; //若沒有資料或只有一筆資料 if (head->rlink == tail || head->rlink->rlink == tail) { return; } current = head->rlink; while(current!=tail){ list_length++; current = current->rlink; } Student **arr = (Student**)malloc(list_length*(sizeof(Student*))); current = head->rlink; for(int i = 0; i < list_length; i++) { arr[i] = current; current = current->rlink; } for(int i = 0; i < list_length-1; i++) { for(int j = 0; j < list_length-1-i; j++) { if(mode==0) { if(strcmp(arr[j]->name, arr[j+1]->name) > 0){ Student *temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } }else if(mode==1){ if(arr[j]->english < arr[j+1]->english ){ Student *temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } else if(mode==2){ if(arr[j]->math < arr[j+1]->math ){ Student *temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } } if(target != -1){ if(target != 0 && target<=list_length){ printf("排名第%d的學生為\n\n" "姓名\t\t英文\t數學\n%-15s\t%d\t%d", target, arr[target-1]->name, arr[target-1]->english, arr[target-1]->math); printf("\n*****************************\n"); }else if(target == 0 && target >= list_length){ printf("\n*****************************\n"); printf("資料不存在"); printf("\n*****************************\n"); } } // 顯示排序後的結果 printf("\n排名\t姓名\t\t英文\t數學\n"); printf("---------------------------------------------\n"); for(int i = 0; i < list_length; i++) { printf("%d\t%-15s\t%d\t%d\n", i+1, arr[i]->name, arr[i]->english, arr[i]->math); } printf("---------------------------------------------\n"); } //選擇科目及排名 void choose_subject(){ int subject ,number , i=1; printf("\n輸入選擇的科目\n" "1 數學 2 英文 ==> "); subject = getche(); switch(subject){ case '1': printf("\n輸入排名(輸入完畢請按Enter) ==> "); scanf("%d",&number); printf("\n數學"); sort(1,number); break; case '2': printf("\n輸入排名(輸入完畢請按Enter) ==> "); scanf("%d",&number); printf("\n英文"); sort(2,number); break; default : printf("輸入錯誤"); break; } } //釋放所有節點 void freeAllNodes() { current = head->rlink; while (current != tail) { temp = current; current = current->rlink; free(temp); } free(head); // 釋放 head 節點 free(tail); // 釋放 tail 節點 free(arr); } int main() { char mode ,sort_mode , name[15]; int english , math; init_f(); readStudentsFromFile("YunTechStudents.txt"); printStudentList(); modify_list(); while(1){ printf("\n******* 選擇進行排序或是排名第n名的學生 *******\n" "*--------------------------------------*\n" "* 1 進行排序 2 選擇排名第n名的學生 3 結束 *\n" "* 4 顯示原始串列 5 清除畫面 6 增加一筆資料 *\n" "* 7 刪除一筆資料 *\n" "\n請選擇功\能 ==> "); //不打成 功\能 在視窗中會變亂碼 mode = getche(); switch(mode){ case '1': printf("\n\n選擇排序方式\n" "*--------------------------------------*\n" "1 名字 2 英文成績 3 數學成績 \n" "\n請選擇排序方式 ==> "); sort_mode = getche(); switch(sort_mode){ case '1': printf("\n\n以名字進行排序\n"); sort(0 ,-1); break; case '2': printf("\n\n以英文成績進行排序\n"); sort(1 ,-1); break; case '3': printf("\n\n以數學成績進行排序\n"); sort(2 ,-1); break; default: printf("\n輸入錯誤\n"); break; } break; case '2': choose_subject(); break; case '3': printf("\n\n謝謝使用,Bye~\n"); freeAllNodes(); return 0; case '4': printStudentList(); break; case '5': system("cls"); break; case '6': printf("\n輸入名字 ==> "); // scanf("%[^\n]",name); while(getchar() != '\n'); // 清除緩衝區 fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = '\0'; // 移除換行符 printf("\n輸入英文成績 ==> "); scanf("%d",&english); printf("\n輸入數學成績 ==> "); scanf("%d",&math); add_data(name,english,math); printStudentList(); break; case '7': printf("\n欲刪除輸入名字 ==> "); // scanf("%[^\n]",name); while(getchar() != '\n'); // 清除緩衝區 fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = '\0'; // 移除換行符 remove_data(name); printStudentList(); break; default: printf("\n輸入錯誤\n"); break; } } }