#include #include #include #include #define MAX_NAME_LENGTH 24 FILE* file; // 定義學生節點結構 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; //設一個 head,將左右鏈結皆指向本身 void init_f() { head = (Student *) malloc(sizeof(Student)); // 直接用 head head->llink = head; // 左鏈結指向自己 head->rlink = head; // 右鏈結指向自己 tail = 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; if(head->rlink == tail) { // 這是第一個插入的節點 head->rlink = newNode; tail->llink = newNode; newNode->llink = head; newNode->rlink = tail; } else { //不是第一筆 插入尾部 newNode->llink = tail->llink; newNode->rlink = tail; tail->llink->rlink = newNode; tail->llink = newNode; } } // 執行**後的增加或減少資料 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+2, "%23[^\t]\t%d\t%d\n", name, &english, &math); // printf("\n*******************************\n"); // printf("增加一筆資料\n\n"); // printf("%s\n",name); // add_data(name, english, math); // printStudentList(); // }else if(line[0]=='-'){ // sscanf(line+2, "%23[^\t]\t%d\t%d\n", name, &english, &math); // printf("\n*******************************\n"); // printf("減少一筆資料\n\n"); // printf("%s\n",name); // remove_data(name); // printStudentList(); // } // } fclose(file); } //增加資料 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 != head){ 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); return; } 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就讀 // 若成功讀取到資料會回傳3 若讀取失敗 只讀到name或沒讀到資料則回傳值不等於3 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; } } } // 列印學生列表 void printStudentList() { Student* current = head->rlink; printf("從頭開始\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; } } void sort_name(){ Student* temp ; Student* current; //若沒有資料或只有一筆資料 if (head->rlink == tail || head->rlink->rlink == tail) { return; } int flag = 1; while(flag){ flag = 0; current = head->rlink; while(current->rlink != tail){ temp = current->rlink; if(strcmp(current->name,temp->name) < 0){ // 只使用兩個節點進行節點交換 // 要注意指標改變後的順序 // 若下列程式順序交換指標指向的位址會出錯 // 也可以多宣告兩個節點 紀錄current->llink及temp->rlink // 這樣就可以無腦不管順序 temp->llink = current->llink; current->rlink = temp->rlink; temp->rlink->llink = current; temp->rlink = current; current->llink->rlink = temp; current->llink = temp; flag = 1; } else{ current = current->rlink; } } } print("以名字排序\n"); // printStudentList(); } void sort_eng(){ Student* temp ; Student* current; //若沒有資料或只有一筆資料 if (head->rlink == tail || head->rlink->rlink == tail) { return; } int flag = 1; while(flag){ flag = 0; current = head->rlink; while(current->rlink != tail){ temp = current->rlink; if(current->english < temp->english){ // 只使用兩個節點進行節點交換 // 要注意指標改變後的順序 // 若下列程式順序交換指標指向的位址會出錯 // 也可以多宣告兩個節點 紀錄current->llink及temp->rlink // 這樣就可以無腦不管順序 temp->llink = current->llink; current->rlink = temp->rlink; temp->rlink->llink = current; temp->rlink = current; current->llink->rlink = temp; current->llink = temp; flag = 1; } else{ current = current->rlink; } } } print("以英文成績排序\n"); // printStudentList(); } void sort_math(){ Student* temp ; Student* current; //若沒有資料或只有一筆資料 if (head->rlink == tail || head->rlink->rlink == tail) { return; } int flag = 1; while(flag){ flag = 0; current = head->rlink; while(current->rlink != tail){ temp = current->rlink; if(current->math < temp->math){ // 只使用兩個節點進行節點交換 // 要注意指標改變後的順序 // 若下列程式順序交換指標指向的位址會出錯 // 也可以多宣告兩個節點 紀錄current->llink及temp->rlink // 這樣就可以無腦不管順序 temp->llink = current->llink; current->rlink = temp->rlink; temp->rlink->llink = current; temp->rlink = current; current->llink->rlink = temp; current->llink = temp; flag = 1; } else{ current = current->rlink; } } } print("以數學成績排序\n"); // printStudentList(); } int main() { init_f(); readStudentsFromFile("YunTechStudents.txt"); // printStudentList(); modify_list(); sort_name(); sort_math(); sort_eng(); return 0; }