Data_Structure/作業/test/DS4_test.cpp
2025-01-20 21:30:53 +08:00

376 lines
8.9 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>
#include <conio.h>
#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;
}
}
}