/* sList.c */ #include #include #include /* 定義一指向 FILE 的指標 */ FILE *fptr; /* 函式的原型宣告 */ void init_f(void); void insertStudent(int id, char* name, double score); void readFromFile(const char* filename); void saveToFile(const char* filename); void insert(void); void del(void); void modify(void); void display(void); // 定義學生節點結構 typedef struct Student { long int id; char name[10]; double score; struct Student *rlink; struct Student *llink; } Student; Student *head, *pNode ,*tail, *current, *prev, *temp ; //設一個 head,將左右鏈結皆指向本身 void init_f() { head = (Student *) malloc(sizeof(Student)); tail = (Student *) malloc(sizeof(Student)); // 初始化 head 和 tail head->llink = NULL; head->rlink = tail; tail->llink = head; tail->rlink = NULL; } // 在尾部插入新學生節點 void insertStudent(int id, char* name, double score) { Student* newNode = (Student*)malloc(sizeof(Student)); newNode->id = id; strcpy(newNode->name, name); newNode->name[9] = '\0'; newNode->score = score; // 插入到尾部之前 newNode->rlink = tail; newNode->llink = tail->llink; tail->llink->rlink = newNode; tail->llink = newNode; } // 讀檔 void readFromFile(const char* filename) { char line[100]; FILE* fptr = fopen(filename, "r"); if (fptr == NULL) { printf("無法打開檔案 %s\n", filename); return; } long int id; char name[10]; double score; while(fgets(line ,sizeof(line) ,fptr)!=NULL){ if(sscanf(line,"%ld\t%9s\t%lf", &id, name, &score) == 3){ insertStudent(id, name, score); } } fclose(fptr); printf("顯示檔案資料\n"); } // 存檔 void saveToFile(const char* filename ) { FILE* fptr = fopen(filename, "w"); if (fptr == NULL) { printf("無法打開檔案 %s 進行寫入\n", filename); return; } Student* current = head->rlink; while (current != tail ) { fprintf(fptr, "%ld\t%s\t%.lf\n", current->id, current->name, current->score); current = current->rlink; } fclose(fptr); printf("資料已成功\儲存到 %s\n", filename); } //顯示串列資料 void printStudentList() { Student* current = head->rlink; printf("\n*******************************"); if (current != NULL) { printf("\n%6s %10s %8s\n", "ID", "Name", "Score"); printf("-------------------------------\n"); while (current != tail) { printf("%6ld %10s %8.1f\n", current->id,current->name, current->score); /* 將指標移到下一個節點 */ current = current->rlink; } } /* 若是空的,則輸出鏈結串列無資料 */ else { printf("\n鏈結串列無資料\n"); } printf("*******************************\n\n"); } int main(){ init_f(); readFromFile("list.txt"); printStudentList(); /* 利用一選單讓使用選擇功能項目 */ int choice; do { printf("************************\n"); printf("鏈結串列的運作選單\n"); printf("1. 加入一節點\n"); printf("2. 刪除一節點\n"); printf("3. 修改一節點\n"); printf("4. 顯示所有節點\n"); printf("5. 結束\n"); printf("請選擇: "); scanf("%d", &choice); switch (choice) { case 1: insert(); break; case 2: del(); break; case 3: modify(); break; case 4: printStudentList(); break; case 5: printf("\n程式結束\n"); saveToFile("list.txt"); exit(0); default: printf("輸入號碼不正確,請重新輸入\n"); } printf("\n"); } while(choice != 5); getchar(); return 0; } /* 按照分數由大至小加入一節點於鏈結串列 */ void insert() { /* 利用 malloc() 函式配置記憶體*/ Student* newNode = (Student*)malloc(sizeof(Student)); printf("\n請輸入ID: "); scanf("%ld", &newNode->id); printf("請輸入姓名: "); scanf("%s", newNode->name); printf("請輸入分數: "); scanf("%lf", &newNode->score); /* 加入一節點於鏈結串列 */ current = head->rlink; prev = head; // 插入到尾部之前 newNode->rlink = tail; newNode->llink = tail->llink; tail->llink->rlink = newNode; tail->llink = newNode; } /* 刪除某一節點*/ void del() { long int deleteID; /* 將 current 指標指向 head 的下一個節點 */ current = head->rlink; prev = head; /* 先判斷鏈結串列是否為空 */ if (current != NULL) { /* 若不是空的,則找尋欲刪除的節點 */ printf("\n請輸入欲刪除的 ID: "); scanf("%ld", &deleteID); /* 找尋欲刪除的節點 */ while ((current != tail) && (current->id != deleteID)) { prev = current; current = current->rlink; } /* 若找到,則將它刪除 */ if (current != tail) { current->rlink->llink = prev; prev->rlink = current->rlink; printf("ID: %ld 已刪除\n", current->id); free(current); } /* 若沒有找到,則輸出找不到欲刪除節點的訊息*/ else { printf("\n找不到欲刪除的節點\n"); } } /* 若是空的,則輸出鏈結串列是空的訊息 */ else { printf("鏈結串列是空的\n"); } } /* 修改某一節點 */ void modify() { Student *temp; long int modifyID; double modifyScore; int flag = 0; printf("\n請輸入欲修改節點的 ID: "); scanf("%ld", &modifyID); current = head->rlink; prev = head; /* 找尋欲修改的節點 */ while (current != tail) { if (current->id == modifyID) { printf("目前欲修改節點的資料如下:\n"); printf("%6ld %10s %8.1f\n\n", current->id,current->name, current->score); printf("請輸入欲修改的分數: "); scanf("%lf", &modifyScore); current->score = modifyScore; flag = 1; break; } else { prev = current; current = current->rlink; } } /* 判斷是否有找到欲修改的節點 */ if (flag != 0) { /* 將 current 的節點指定給 temp */ // temp = current; // prev->rlink = current->rlink; /* 將 temp 節點加入於鏈結串列 */ // current = head->rlink; // prev = head; // while ((current != tail) && (temp->score < current->score)) { // prev = current; // current = current->rlink; // } // prev->rlink = temp; // temp->rlink = current; } else { printf("找不到欲修改的節點\n"); } }