376 lines
8.9 KiB
C++
376 lines
8.9 KiB
C++
#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;
|
||
}
|
||
}
|
||
}
|