317 lines
6.8 KiB
C
317 lines
6.8 KiB
C
#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;
|
||
}
|