Data_Structure/作業/unit4/TWICE.c
2025-01-20 21:30:53 +08:00

317 lines
6.8 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>
#include <ctype.h>
#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;
}
}
fclose(file);
}
// 列印學生列表
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;
}